fix(settings): stop AI deep link from hijacking later settings opens

This commit is contained in:
Melody Ruch authored and GitHub committed 2026-09-05 22:04:12 +08:00
1 parent da03c1f0c4
commit 3907cb1372
3 files changed
+38

No files matched your search

+1
View File
@@ -3509,6 +3509,7 @@ onUnmounted(() => {
class="flex-1 min-h-0"
@update:open="(open: boolean) => (open ? activateSettingsPage() : closeSettingsPage())"
@check-updates="checkUpdates()"
@ai-config-deep-link-handled="settingsAiConfigDraft = null"
/>
<div v-if="queryStore.tabs.length > 0" v-show="!driverStoreActive && !settingsStore.settingsPageActive" class="flex flex-col flex-1 min-h-0">
<SqlEditorWorkspace
@@ -279,6 +279,7 @@ const props = defineProps<{
const emit = defineEmits<{
"update:open": [value: boolean];
"check-updates": [];
"ai-config-deep-link-handled": [];
}>();
const isSettingsPage = computed(() => props.variant === "page");
@@ -3966,6 +3967,7 @@ async function applyPendingAiConfigDeepLinkDraft() {
if (!settingsVisible.value || !requestId || requestId === handledAiConfigRequestId || !draft) return;
handledAiConfigRequestId = requestId;
emit("ai-config-deep-link-handled");
activeSettingsTab.value = "ai";
aiEnterEditMode();
aiEditConfigName.value = draft.name;
@@ -0,0 +1,35 @@
import { readFileSync } from "node:fs";
import { describe, expect, it } from "vitest";
const dialogSource = readFileSync(new URL("../EditorSettingsDialog.vue", import.meta.url), "utf8");
const appSource = readFileSync(new URL("../../../App.vue", import.meta.url), "utf8");
// Regression for https://github.com/t8y2/dbx/issues/7874: after using an AI
// config deep link (dbx://settings/ai/new?...) once, every later "open
// Settings" (even a plain click on the gear icon) got forcibly yanked back to
// the AI tab. Root cause: `settingsAiConfigDraft`/`settingsAiConfigRequestId`
// in App.vue are set once by `openAiConfigDeepLink` and never cleared, while
// the dialog's own "already handled this request" guard
// (`handledAiConfigRequestId`) is a plain local variable that resets to 0
// every time the dialog remounts (it's `v-if`-toggled in App.vue, so closing
// Settings destroys the instance). On the next open, `requestId !==
// handledAiConfigRequestId` is true again even though nothing new happened,
// so `applyPendingAiConfigDeepLinkDraft` reapplies the stale draft and jumps
// the user back into "ai" tab / edit mode forever, once per app run.
describe("EditorSettingsDialog AI config deep-link tab hijack", () => {
function applyDraftBlock(): string {
const start = dialogSource.indexOf("async function applyPendingAiConfigDeepLinkDraft()");
const end = dialogSource.indexOf("\n}\n", start);
if (start < 0 || end < 0) throw new Error("Missing applyPendingAiConfigDeepLinkDraft function block");
return dialogSource.slice(start, end);
}
it("emits an event once the deep-link draft has been consumed", () => {
expect(dialogSource).toContain('"ai-config-deep-link-handled": []');
expect(applyDraftBlock()).toContain('emit("ai-config-deep-link-handled")');
});
it("App.vue clears the draft/request state once notified, so a remounted dialog can't reapply it", () => {
expect(appSource).toContain('@ai-config-deep-link-handled="settingsAiConfigDraft = null"');
});
});