fix(settings): confirm before discarding unsaved settings
This commit is contained in:
1 parent
9dbb2ef72f
commit
6a25bd1909
12 files changed
+160
-3
No files matched your search
@@ -1,5 +1,5 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { EDITOR_SETTINGS_DRAFT_KEYS, editorSettingsDraftFromSettings, editorSettingsDraftChanged, editorSettingsPatchFromDraft, normalizeQueryResultMaxRowsDraft, normalizeTableOpenPageSizeDraft } from "../editorSettingsDraft";
|
||||
import { EDITOR_SETTINGS_DRAFT_KEYS, editorSettingsDraftFromSettings, editorSettingsDraftChanged, editorSettingsPatchFromDraft, normalizeQueryResultMaxRowsDraft, normalizeTableOpenPageSizeDraft, shouldConfirmEditorSettingsDialogClose } from "../editorSettingsDraft";
|
||||
import type { EditorSettings } from "@/stores/settingsStore";
|
||||
|
||||
function makeSettings(overrides: Partial<EditorSettings> = {}): EditorSettings {
|
||||
@@ -345,6 +345,33 @@ describe("editorSettingsDraftChanged - tabLayout", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("shouldConfirmEditorSettingsDialogClose", () => {
|
||||
// Regression for https://github.com/t8y2/dbx/issues/5905: customizing a
|
||||
// shortcut or the sidebar activation mode and then dismissing the dialog
|
||||
// via Escape/outside-click/the "Close" button (anything other than Apply)
|
||||
// must not silently drop the draft.
|
||||
it("requests confirmation when the dialog is closing with an unsaved shortcut/sidebarActivation edit", () => {
|
||||
const settings = makeSettings({ sidebarActivation: "single" } as Partial<EditorSettings>);
|
||||
const base = editorSettingsDraftFromSettings(settings);
|
||||
const draft = editorSettingsDraftFromSettings(settings);
|
||||
draft.sidebarActivation = "double";
|
||||
|
||||
expect(shouldConfirmEditorSettingsDialogClose(false, editorSettingsDraftChanged(draft, base))).toBe(true);
|
||||
});
|
||||
|
||||
it("does not block closing when there is no unsaved draft", () => {
|
||||
const settings = makeSettings();
|
||||
const base = editorSettingsDraftFromSettings(settings);
|
||||
const draft = editorSettingsDraftFromSettings(settings);
|
||||
|
||||
expect(shouldConfirmEditorSettingsDialogClose(false, editorSettingsDraftChanged(draft, base))).toBe(false);
|
||||
});
|
||||
|
||||
it("never blocks opening the dialog, even with a stale dirty flag", () => {
|
||||
expect(shouldConfirmEditorSettingsDialogClose(true, true)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("editorSettingsPatchFromDraft - tabLayout", () => {
|
||||
it("includes tabLayout in patch when changed", () => {
|
||||
const settings = makeSettings({ tabLayout: "scroll" });
|
||||
|
||||
@@ -134,3 +134,12 @@ export function editorSettingsPatchFromDraft(draft: EditorSettingsDraft, base: E
|
||||
export function editorSettingsDraftChanged(draft: EditorSettingsDraft, base: EditorSettingsDraft): boolean {
|
||||
return EDITOR_SETTINGS_DRAFT_KEYS.some((key) => draftValueChanged(key, draft[key], base[key]));
|
||||
}
|
||||
|
||||
// Closing the settings dialog (Escape, clicking outside, the X button, or the
|
||||
// "Close" footer button) must never silently drop an unapplied draft — the
|
||||
// dialog only persists shortcuts/sidebarActivation/etc. to the store on an
|
||||
// explicit Apply. Route every close attempt through this check so an unsaved
|
||||
// draft always surfaces a confirmation instead of vanishing.
|
||||
export function shouldConfirmEditorSettingsDialogClose(nextOpen: boolean, hasUnsavedChanges: boolean): boolean {
|
||||
return nextOpen === false && hasUnsavedChanges;
|
||||
}
|
||||
Reference in new issue
Block a user