fix(sidebar): preserve existing table data tabs

This commit is contained in:
t8y2 committed 2026-07-21 18:45:02 +08:00
1 parent 61f442f9b9
commit 678033c82e
5 files changed
+33 -75

No files matched your search

@@ -89,7 +89,7 @@ import {
import { copyNameForTreeNode, isDocumentBrowserTreeNode, objectSourceKindForTreeNode, shouldRunTreeNodeRowAction, treeNodeRowAction, treeNodeRowDoubleClickAction } from "@/lib/sidebar/treeNodeClick";
import { dataTabOpenModeFromTreeClick, type DataTabOpenMode } from "@/lib/sidebar/dataTabOpenPolicy";
import { isCopySidebarSelectionShortcut, isEditSidebarConnectionShortcut, isPasteSidebarSelectionShortcut } from "@/lib/editor/keyboardShortcuts";
import { canRefreshDataTableFromSingleActivationDoubleClick, dataTableDoubleClickAction } from "@/lib/tabs/dataTabActivation";
import { dataTableDoubleClickAction } from "@/lib/tabs/dataTabActivation";
import { attachedDatabaseNameFromPath, buildCreateDatabaseSql, buildDuckDbAttachDatabaseSql, buildSqliteAttachDatabaseSql, supportsCreateDatabaseCharset, uniqueAttachedDatabaseName } from "@/lib/database/createDatabaseSql";
import { appendCreateDatabaseErrorHint } from "@/lib/database/createDatabaseErrorHints";
import { SQLITE_DATABASE_FILE_EXTENSIONS } from "@/lib/database/databaseFileDetection";
@@ -671,9 +671,6 @@ function runRowClickAction(clickDetail: number) {
const action = treeNodeRowAction(node.type, canExpand.value, settingsStore.editorSettings.sidebarActivation);
if (!shouldRunTreeNodeRowAction(action, clickDetail)) return;
if (action === "open-data") {
if (node.type === "table") {
singleActivationDoubleClickRefreshAllowed = canRefreshDataTableFromSingleActivationDoubleClick(findExistingSameTableDataTab());
}
scheduleOpenData(node);
} else if (isDocumentBrowserTreeNode(node.type)) {
openMongoTreeData(node);
@@ -684,8 +681,6 @@ function runRowClickAction(clickDetail: number) {
}
}
let singleActivationDoubleClickRefreshAllowed = false;
function refreshActiveKvBrowserAfterOpen(mode: "etcd" | "zookeeper", connectionId: string) {
void nextTick(() => {
window.dispatchEvent(new CustomEvent("dbx-refresh-active-kv-browser", { detail: { mode, connectionId } }));
@@ -919,8 +914,8 @@ function onDoubleClick(event: MouseEvent) {
if (!activeNode.value.isExpanded) void toggle();
} else if (action === "open-data") {
openDataImmediately(activeNode.value);
} else if (action === "refresh-data") {
void refreshData();
} else if (action === "activate-data") {
activateDataTableFromDoubleClick();
} else if (action === "open-source") {
openObjectSourceDialog(false);
} else if (action === "open-saved-sql") {
@@ -932,24 +927,21 @@ function onDoubleClick(event: MouseEvent) {
}
}
async function refreshData() {
function activateDataTableFromDoubleClick() {
const node = activeNode.value;
if (node.type !== "table" || !hasNodeDatabaseContext(node)) return;
const singleActivationRefreshAllowed = singleActivationDoubleClickRefreshAllowed;
singleActivationDoubleClickRefreshAllowed = false;
const activation = settingsStore.editorSettings.sidebarActivation;
if (activation === "single" && !singleActivationRefreshAllowed) return;
const existingSameTableTab = findExistingSameTableDataTab();
const action = dataTableDoubleClickAction(existingSameTableTab, activation, singleActivationRefreshAllowed);
const action = dataTableDoubleClickAction(existingSameTableTab, activation);
if (action === "none") return;
if (action === "open") {
openDataImmediately(node);
return;
}
if (!existingSameTableTab) return;
// Reopening an available table follows DBeaver's editor reuse model: only
// activate the existing tab so filters, result rows, and in-flight work stay intact.
queryStore.switchTab(existingSameTableTab.id);
if (action === "activate") return;
await queryStore.refreshDataTab(existingSameTableTab.id);
}
function findExistingSameTableDataTab() {
@@ -2,7 +2,7 @@ import type { ObjectSourceKind, TreeNode, TreeNodeType } from "@/types/database"
import { matchesShortcut, type ShortcutLikeEvent } from "@/lib/editor/keyboardShortcuts";
export type TreeNodeRowAction = "open-data" | "toggle" | "none";
export type TreeNodeRowDoubleClickAction = "open-data" | "refresh-data" | "open-object-browser" | "open-object-browser-and-expand" | "open-source" | "open-saved-sql" | "toggle" | "none";
export type TreeNodeRowDoubleClickAction = "open-data" | "activate-data" | "open-object-browser" | "open-object-browser-and-expand" | "open-source" | "open-saved-sql" | "toggle" | "none";
export type SidebarSelectionCopyAction = "copy-name" | "none";
export type SidebarActivation = "single" | "double";
@@ -48,7 +48,9 @@ export function shouldRunTreeNodeRowAction(action: TreeNodeRowAction, clickDetai
}
export function treeNodeRowDoubleClickAction(type: TreeNodeType, canOpenObjectBrowser: boolean, activation: SidebarActivation = "single", canExpand = false): TreeNodeRowDoubleClickAction {
if (type === "table") return "refresh-data";
// Single-click activation already handles the first click in a dblclick
// sequence. Only double-click activation needs a second-stage table action.
if (type === "table") return activation === "double" ? "activate-data" : "none";
if (activation === "double") {
if (dataNodeTypes.has(type)) return "open-data";
if (sourceNodeTypes.has(type)) return "open-source";
@@ -1,6 +1,6 @@
import type { QueryResult, QueryTab } from "@/types/database";
export type DataTableDoubleClickAction = "activate" | "open" | "refresh" | "none";
export type DataTableDoubleClickAction = "activate" | "open" | "none";
function isErrorResult(result: QueryResult | undefined): boolean {
return result?.columns.length === 1 && result.columns[0] === "Error";
@@ -12,13 +12,9 @@ export function canActivateExistingDataTableTab(tab: QueryTab, options: { activa
return !!tab.result || !!tab.results?.length;
}
export function canRefreshDataTableFromSingleActivationDoubleClick(tab: QueryTab | undefined): boolean {
return !!tab && !tab.isExecuting && canActivateExistingDataTableTab(tab);
}
export function dataTableDoubleClickAction(tab: QueryTab | undefined, activation: "single" | "double", singleActivationRefreshAllowed = false): DataTableDoubleClickAction {
if (activation === "single" && !singleActivationRefreshAllowed) return "none";
export function dataTableDoubleClickAction(tab: QueryTab | undefined, activation: "single" | "double"): DataTableDoubleClickAction {
if (activation === "single") return "none";
if (!tab) return activation === "double" ? "open" : "none";
if (!canActivateExistingDataTableTab(tab)) return "open";
return tab.isExecuting ? "activate" : "refresh";
return "activate";
}