feat(grid): keep filter editor expanded

This commit is contained in:
二丫讲梵 authored and GitHub committed 2026-09-09 12:04:32 +08:00
1 parent 08edb60772
commit 004b27a3c2
19 files changed
+157 -45

No files matched your search

+35
View File
@@ -47,6 +47,21 @@ describe("normalizeEditorSettings", () => {
expect(normalizeEditorSettings({ dataGridFilterEditorView: "invalid" } as any).dataGridFilterEditorView).toBe("quick");
});
it("keeps filter editor expansion disabled unless explicitly enabled", () => {
expect(normalizeEditorSettings({}).dataGridKeepFilterEditorExpanded).toBe(false);
expect(normalizeEditorSettings({ dataGridKeepFilterEditorExpanded: true }).dataGridKeepFilterEditorExpanded).toBe(true);
expect(normalizeEditorSettings({ dataGridKeepFilterEditorExpanded: false }).dataGridKeepFilterEditorExpanded).toBe(false);
expect(normalizeEditorSettings({ dataGridKeepFilterEditorExpanded: "true" } as any).dataGridKeepFilterEditorExpanded).toBe(false);
expect(normalizeEditorSettings({ dataGridKeepFilterEditorExpanded: null } as any).dataGridKeepFilterEditorExpanded).toBe(false);
expect(normalizeEditorSettings({ dataGridKeepFilterEditorExpanded: "true", dataGridAutoHideFilterBuilder: false } as any).dataGridKeepFilterEditorExpanded).toBe(false);
});
it("migrates the legacy auto-hide preference when the current preference is absent", () => {
expect(normalizeEditorSettings({ dataGridAutoHideFilterBuilder: false } as any).dataGridKeepFilterEditorExpanded).toBe(true);
expect(normalizeEditorSettings({ dataGridAutoHideFilterBuilder: true } as any).dataGridKeepFilterEditorExpanded).toBe(false);
expect(normalizeEditorSettings({ dataGridKeepFilterEditorExpanded: false, dataGridAutoHideFilterBuilder: false } as any).dataGridKeepFilterEditorExpanded).toBe(false);
});
it("normalizes persisted tab group names and colors", () => {
expect(normalizeEditorSettings({}).tabGroupCustomizations).toEqual({});
expect(
@@ -923,6 +938,26 @@ describe("settingsStore persisted settings initialization", () => {
expect(saveEditorSettings).toHaveBeenCalledWith(expect.objectContaining({ fontSize: 17, theme: "xcode-dark", appLayout: "separated" }));
});
it("migrates the legacy filter-editor preference in incremental settings updates", async () => {
const loadEditorSettings = vi.fn().mockResolvedValue({});
const saveEditorSettings = vi.fn().mockResolvedValue(undefined);
vi.doMock("@/lib/backend/api", () => ({ loadEditorSettings, saveEditorSettings }));
const { useSettingsStore } = await import("@/stores/settingsStore");
const store = useSettingsStore();
await store.initEditorSettings();
saveEditorSettings.mockClear();
store.updateEditorSettings({ dataGridAutoHideFilterBuilder: false } as any);
await vi.waitFor(() => expect(saveEditorSettings).toHaveBeenCalledOnce());
expect(store.editorSettings.dataGridKeepFilterEditorExpanded).toBe(true);
expect(saveEditorSettings).toHaveBeenLastCalledWith(expect.objectContaining({ dataGridKeepFilterEditorExpanded: true }));
await store.updateEditorSettingsAndPersist({ dataGridAutoHideFilterBuilder: true } as any);
expect(store.editorSettings.dataGridKeepFilterEditorExpanded).toBe(false);
expect(saveEditorSettings).toHaveBeenLastCalledWith(expect.objectContaining({ dataGridKeepFilterEditorExpanded: false }));
});
it("loads and persists the substitution switch without discarding syntax overrides", async () => {
const loadEditorSettings = vi.fn().mockResolvedValue({
sqlVariableSubstitutionEnabled: false,
+29 -11
View File
@@ -788,7 +788,7 @@ export interface EditorSettings {
columnWidthDensity: ColumnWidthDensity;
dataGridQuickEntry: boolean;
dataGridFilterEditorView: DataGridFilterEditorView;
dataGridAutoHideFilterBuilder: boolean;
dataGridKeepFilterEditorExpanded: boolean;
dataGridTextFilterPanelHeight: number;
localFilterPopoverWidth: number;
dataGridRenderMode: DataGridRenderMode;
@@ -1024,7 +1024,7 @@ export const DEFAULT_EDITOR_SETTINGS: EditorSettings = {
columnWidthDensity: "standard",
dataGridQuickEntry: false,
dataGridFilterEditorView: "quick",
dataGridAutoHideFilterBuilder: true,
dataGridKeepFilterEditorExpanded: false,
dataGridTextFilterPanelHeight: DATA_GRID_TEXT_FILTER_PANEL_HEIGHT_DEFAULT,
localFilterPopoverWidth: 360,
dataGridRenderMode: "canvas",
@@ -1368,6 +1368,8 @@ function normalizeTableInfoTab(value: unknown): TableInfoTab {
export function normalizeEditorSettings(settings: Partial<EditorSettings>, existing?: EditorSettings): EditorSettings {
const legacyTimeoutSettings = settings as Partial<EditorSettings> & { queryTimeoutSecs?: unknown; queryTimeoutInheritanceMigrationVersion?: unknown };
const legacySidebarOpenDatabaseOnSingleClick = (settings as Partial<EditorSettings> & { sidebarOpenDatabaseOnSingleClick?: unknown }).sidebarOpenDatabaseOnSingleClick;
const legacyDataGridAutoHideFilterBuilder = (settings as Partial<EditorSettings> & { dataGridAutoHideFilterBuilder?: unknown }).dataGridAutoHideFilterBuilder;
const hasDataGridKeepFilterEditorExpanded = Object.prototype.hasOwnProperty.call(settings, "dataGridKeepFilterEditorExpanded");
const sqlSemanticDiagnosticsMode = normalizeSqlSemanticDiagnosticsMode(settings.sqlSemanticDiagnosticsMode, settings.sqlSemanticDiagnosticsEnabled);
const savedExecuteModeDefaultVersion = settings.executeModeDefaultVersion;
const executeModeDefaultVersion = typeof savedExecuteModeDefaultVersion === "number" && savedExecuteModeDefaultVersion >= EXECUTE_MODE_CURRENT_DEFAULT_VERSION ? savedExecuteModeDefaultVersion : EXECUTE_MODE_CURRENT_DEFAULT_VERSION;
@@ -1479,7 +1481,7 @@ export function normalizeEditorSettings(settings: Partial<EditorSettings>, exist
columnWidthDensity: normalizeColumnWidthDensity(settings.columnWidthDensity),
dataGridQuickEntry: settings.dataGridQuickEntry ?? DEFAULT_EDITOR_SETTINGS.dataGridQuickEntry,
dataGridFilterEditorView: normalizeDataGridFilterEditorView(settings.dataGridFilterEditorView),
dataGridAutoHideFilterBuilder: settings.dataGridAutoHideFilterBuilder ?? DEFAULT_EDITOR_SETTINGS.dataGridAutoHideFilterBuilder,
dataGridKeepFilterEditorExpanded: typeof settings.dataGridKeepFilterEditorExpanded === "boolean" ? settings.dataGridKeepFilterEditorExpanded : hasDataGridKeepFilterEditorExpanded ? false : legacyDataGridAutoHideFilterBuilder === false,
dataGridTextFilterPanelHeight: normalizeDataGridTextFilterPanelHeight(settings.dataGridTextFilterPanelHeight),
localFilterPopoverWidth: normalizeDrawerWidth(settings.localFilterPopoverWidth, 240, DEFAULT_EDITOR_SETTINGS.localFilterPopoverWidth),
dataGridRenderMode: normalizeDataGridRenderMode(settings.dataGridRenderMode),
@@ -1613,6 +1615,20 @@ export function normalizeEditorSettings(settings: Partial<EditorSettings>, exist
};
}
/**
* Cloud snapshots are applied as partial settings updates rather than loaded
* through `normalizeEditorSettings`. Translate the removed inverse flag here
* so older snapshots retain their behavior on every incremental update path.
*/
function migrateLegacyFilterEditorExpansionPatch(partial: Partial<EditorSettings>): Partial<EditorSettings> {
const patch = partial as Partial<EditorSettings> & { dataGridAutoHideFilterBuilder?: unknown };
const { dataGridAutoHideFilterBuilder: legacyAutoHide, ...current } = patch;
if (Object.prototype.hasOwnProperty.call(patch, "dataGridKeepFilterEditorExpanded") || typeof legacyAutoHide !== "boolean") {
return current;
}
return { ...current, dataGridKeepFilterEditorExpanded: !legacyAutoHide };
}
function loadLegacyEditorSettings(): EditorSettings | null {
const raw = safeLocalStorageGet(STORAGE_KEY);
if (raw) {
@@ -2223,7 +2239,7 @@ export const useSettingsStore = defineStore("settings", () => {
if (partial.columnWidthDensity !== undefined) editorSettings.value.columnWidthDensity = normalizeColumnWidthDensity(partial.columnWidthDensity);
if (partial.dataGridQuickEntry !== undefined) editorSettings.value.dataGridQuickEntry = partial.dataGridQuickEntry;
if (partial.dataGridFilterEditorView !== undefined) editorSettings.value.dataGridFilterEditorView = normalizeDataGridFilterEditorView(partial.dataGridFilterEditorView);
if (partial.dataGridAutoHideFilterBuilder !== undefined) editorSettings.value.dataGridAutoHideFilterBuilder = partial.dataGridAutoHideFilterBuilder;
if (partial.dataGridKeepFilterEditorExpanded !== undefined) editorSettings.value.dataGridKeepFilterEditorExpanded = partial.dataGridKeepFilterEditorExpanded === true;
if (partial.dataGridTextFilterPanelHeight !== undefined) editorSettings.value.dataGridTextFilterPanelHeight = normalizeDataGridTextFilterPanelHeight(partial.dataGridTextFilterPanelHeight);
if (partial.localFilterPopoverWidth !== undefined) editorSettings.value.localFilterPopoverWidth = normalizeDrawerWidth(partial.localFilterPopoverWidth, 240, DEFAULT_EDITOR_SETTINGS.localFilterPopoverWidth);
if (partial.dataGridRenderMode !== undefined) editorSettings.value.dataGridRenderMode = normalizeDataGridRenderMode(partial.dataGridRenderMode);
@@ -2309,10 +2325,11 @@ export const useSettingsStore = defineStore("settings", () => {
}
function updateEditorSettings(partial: Partial<EditorSettings>) {
applyEditorSettingsPatch(partial);
markEditorSettingsPatch(partial);
const patch = migrateLegacyFilterEditorExpansionPatch(partial);
applyEditorSettingsPatch(patch);
markEditorSettingsPatch(patch);
if (!isEditorSettingsLoaded.value) {
pendingEditorSettingsPatches.push(editorSettingsPatchSnapshot(partial));
pendingEditorSettingsPatches.push(editorSettingsPatchSnapshot(patch));
return;
}
saveEditorSettings();
@@ -2332,16 +2349,17 @@ export const useSettingsStore = defineStore("settings", () => {
return enqueueEditorSettingsAtomicMutation(async () => {
await initEditorSettings();
const previous = editorSettingsSnapshot(editorSettings.value);
applyEditorSettingsPatch(partial);
const revision = markEditorSettingsPatch(partial);
const patch = migrateLegacyFilterEditorExpansionPatch(partial);
applyEditorSettingsPatch(patch);
const revision = markEditorSettingsPatch(patch);
try {
await persistCurrentEditorSettings();
} catch (error) {
const restored = editorSettingsSnapshot(editorSettings.value) as unknown as Record<string, unknown>;
const previousSettings = previous as unknown as Record<string, unknown>;
let changed = false;
for (const key of Object.keys(partial) as (keyof EditorSettings)[]) {
if (partial[key] === undefined || editorSettingsFieldRevisions.get(key) !== revision) continue;
for (const key of Object.keys(patch) as (keyof EditorSettings)[]) {
if (patch[key] === undefined || editorSettingsFieldRevisions.get(key) !== revision) continue;
restored[key] = previousSettings[key];
editorSettingsFieldRevisions.set(key, ++editorSettingsPatchRevision);
changed = true;