Skip to content

Commit

Permalink
fix: Cannot quit app when there is a dirty editor (#13164)
Browse files Browse the repository at this point in the history
Contributed by STMicroelectronics

Signed-off-by: Emil HAMMARSTEDT <[email protected]>
  • Loading branch information
emilhammarstedtst committed Dec 13, 2023
1 parent 469bd74 commit 2b8ed54
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 14 deletions.
25 changes: 16 additions & 9 deletions packages/core/src/browser/common-frontend-contribution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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;

}
};
Expand All @@ -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<void> {
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();
}
}
}
}
Expand Down
21 changes: 16 additions & 5 deletions packages/core/src/browser/dialogs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -458,11 +458,18 @@ export class ConfirmSaveDialog extends AbstractDialog<boolean | undefined> {

}

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<void>): Promise<boolean> {
export async function confirmExitWithOrWithoutSaving(captionsToSave: string[], performSave?: () => Promise<void>): Promise<confirmExitWithOrWithoutSavingResult> {
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'));
Expand All @@ -474,22 +481,26 @@ 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"),
save: nls.localizeByDefault('Save All'),
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()
Expand Down

0 comments on commit 2b8ed54

Please sign in to comment.