diff --git a/packages/core/src/browser/common-frontend-contribution.ts b/packages/core/src/browser/common-frontend-contribution.ts index f436fcf2349b4..9a94250432617 100644 --- a/packages/core/src/browser/common-frontend-contribution.ts +++ b/packages/core/src/browser/common-frontend-contribution.ts @@ -57,7 +57,7 @@ import { QuickInputService, QuickPickItem, QuickPickItemOrSeparator, QuickPickSe import { AsyncLocalizationProvider } from '../common/i18n/localization'; import { nls } from '../common/nls'; import { CurrentWidgetCommandAdapter } from './shell/current-widget-command-adapter'; -import { ConfirmDialog, confirmExitWithOrWithoutSaving, Dialog } from './dialogs'; +import { ConfirmDialog, confirmExitWithOrWithoutSaving, confirmExitWithOrWithoutSavingResult, Dialog } from './dialogs'; import { WindowService } from './window/window-service'; import { FrontendApplicationConfigProvider } from './frontend-application-config-provider'; import { DecorationStyle } from './decoration-style'; @@ -1200,17 +1200,16 @@ export class CommonFrontendContribution implements FrontendApplicationContributi action: async () => { const captionsToSave = this.unsavedTabsCaptions(); const untitledCaptionsToSave = this.unsavedUntitledTabsCaptions(); - const result = await confirmExitWithOrWithoutSaving(captionsToSave, async () => { + const shouldExit = await confirmExitWithOrWithoutSaving(captionsToSave, async () => { await this.saveDirty(untitledCaptionsToSave); await this.shell.saveAll(); }); - if (this.shell.canSaveAll()) { - this.shouldPreventClose = true; - return false; - } else { - this.shouldPreventClose = false; - return result; - } + const allSavedOrDoNotSave = ( + confirmExitWithOrWithoutSavingResult.save === shouldExit && untitledCaptionsToSave.length === 0 // cancel if any captions failed to save + ) || confirmExitWithOrWithoutSavingResult.doNotSave === shouldExit; + + this.shouldPreventClose = !allSavedOrDoNotSave; + return allSavedOrDoNotSave; } }; @@ -1236,11 +1235,19 @@ export class CommonFrontendContribution implements FrontendApplicationContributi this.windowService.reload(); } } + /** + * saves any dirty widget in toSave + * side effect - will pop all widgets from toSave that was saved + * @param toSave + */ protected async saveDirty(toSave: Widget[]): Promise { for (const widget of toSave) { const saveable = Saveable.get(widget); if (saveable?.dirty) { await this.saveResourceService.save(widget); + if (!this.saveResourceService.canSave(widget)) { + toSave.pop(); + } } } } diff --git a/packages/core/src/browser/dialogs.ts b/packages/core/src/browser/dialogs.ts index 2ab0a1203e976..11493b7e59a5f 100644 --- a/packages/core/src/browser/dialogs.ts +++ b/packages/core/src/browser/dialogs.ts @@ -458,11 +458,18 @@ export class ConfirmSaveDialog extends AbstractDialog { } +export enum confirmExitWithOrWithoutSavingResult { + save = 'save', + doNotSave = 'doNotSave', + cancel = 'cancel', +} + // Asks the user to confirm whether they want to exit with or without saving the changes -export async function confirmExitWithOrWithoutSaving(captionsToSave: string[], performSave: () => Promise): Promise { +export async function confirmExitWithOrWithoutSaving(captionsToSave: string[], performSave?: () => Promise): Promise { const div: HTMLElement = document.createElement('div'); div.innerText = nls.localizeByDefault("Your changes will be lost if you don't save them."); + let result; if (captionsToSave.length > 0) { const span = document.createElement('span'); span.appendChild(document.createElement('br')); @@ -474,7 +481,7 @@ export async function confirmExitWithOrWithoutSaving(captionsToSave: string[], p }); span.appendChild(document.createElement('br')); div.appendChild(span); - const result = await new ConfirmSaveDialog({ + result = await new ConfirmSaveDialog({ title: nls.localizeByDefault('Do you want to save the changes to the following {0} files?', captionsToSave.length), msg: div, dontSave: nls.localizeByDefault("Don't Save"), @@ -482,14 +489,18 @@ export async function confirmExitWithOrWithoutSaving(captionsToSave: string[], p cancel: Dialog.CANCEL }).open(); - if (result) { + if (result && performSave) { await performSave(); } - return result !== undefined; } else { // fallback if not passed with an empty caption-list. - return confirmExit(); + result = confirmExit(); } + if (result !== undefined) { + return result === true ? confirmExitWithOrWithoutSavingResult.save : confirmExitWithOrWithoutSavingResult.doNotSave; + } else { + return confirmExitWithOrWithoutSavingResult.cancel; + }; } @injectable()