feat: confirm before closing unsaved SQL query tabs

This commit is contained in:
t8y2 committed 2026-06-12 01:09:41 +08:00
1 parent 51e2ef0d1f
commit 19b5b70fb7
6 files changed
+157 -5

No files matched your search

+51 -1
View File
@@ -113,6 +113,8 @@ export const useQueryStore = defineStore("query", () => {
const restored = loadSavedTabs();
const tabs = ref<QueryTab[]>(restored.tabs);
const activeTabId = ref<string | null>(restored.activeTabId);
const showCloseConfirm = ref(false);
const pendingCloseTabId = ref<string | null>(null);
for (const tab of restored.tabs) {
if (tab.mode === "data") void deleteTabResultSnapshot(tabResultCacheKey(tab.id));
}
@@ -263,6 +265,7 @@ export const useQueryStore = defineStore("query", () => {
isExplaining: false,
mode,
};
if (mode === "query") tab.originalSql = "";
tabs.value.push(tab);
activeTabId.value = id;
return id;
@@ -353,7 +356,26 @@ export const useQueryStore = defineStore("query", () => {
return id;
}
function closeTab(id: string) {
function isTabDirty(tab: QueryTab): boolean {
if (tab.mode !== "query") return false;
if (!tab.sql.trim()) return false;
const original = tab.originalSql;
if (original === undefined) return !!tab.savedSqlId;
return tab.sql !== original;
}
function markTabClean(tab: QueryTab | undefined) {
if (tab) tab.originalSql = tab.sql;
}
function closeTab(id: string, { force = false }: { force?: boolean } = {}) {
const tab = tabs.value.find((t) => t.id === id);
if (!tab) return;
if (!force && isTabDirty(tab)) {
pendingCloseTabId.value = id;
showCloseConfirm.value = true;
return;
}
const idx = tabs.value.findIndex((t) => t.id === id);
if (idx < 0) return;
clearDataGridPendingSnapshotsForTab(id);
@@ -368,6 +390,26 @@ export const useQueryStore = defineStore("query", () => {
}
}
function forceClosePendingTab() {
const id = pendingCloseTabId.value;
pendingCloseTabId.value = null;
showCloseConfirm.value = false;
if (id) closeTab(id, { force: true });
}
function cancelClosePendingTab() {
pendingCloseTabId.value = null;
showCloseConfirm.value = false;
}
function saveAndClosePendingTab() {
const id = pendingCloseTabId.value;
pendingCloseTabId.value = null;
showCloseConfirm.value = false;
if (id) return id;
return null;
}
function closeOtherTabs(id: string) {
tabs.value
.filter((tab) => tab.id !== id)
@@ -568,6 +610,7 @@ export const useQueryStore = defineStore("query", () => {
schema: file.schema,
sql: file.sql,
savedSqlId: file.id,
originalSql: file.sql,
isExecuting: false,
isCancelling: false,
isExplaining: false,
@@ -1620,8 +1663,15 @@ export const useQueryStore = defineStore("query", () => {
return {
tabs,
activeTabId,
showCloseConfirm,
pendingCloseTabId,
createTab,
closeTab,
forceClosePendingTab,
cancelClosePendingTab,
saveAndClosePendingTab,
isTabDirty,
markTabClean,
closeOtherTabs,
closeAllTabs,
duplicateTab,