diff --git a/apps/desktop/src/components/editor/EditorSettingsDialog.vue b/apps/desktop/src/components/editor/EditorSettingsDialog.vue index 6066d41564..7b1437a7f0 100644 --- a/apps/desktop/src/components/editor/EditorSettingsDialog.vue +++ b/apps/desktop/src/components/editor/EditorSettingsDialog.vue @@ -512,7 +512,7 @@ const dataTabReuseModeHelp = ref(null); const editRoutineSourceOpenMode = ref(settingsStore.editorSettings.routineSourceOpenMode); const editSidebarTableSearchEnabled = ref(settingsStore.editorSettings.sidebarTableSearchEnabled); const editAutoSelectActiveSidebarNode = ref(settingsStore.editorSettings.autoSelectActiveSidebarNode); -const editSidebarOpenDatabaseOnSingleClick = ref(settingsStore.editorSettings.sidebarOpenDatabaseOnSingleClick); +const editSidebarBrowseObjectsOnDatabaseActivation = ref(settingsStore.editorSettings.sidebarBrowseObjectsOnDatabaseActivation); const editOpenTabsRestoreMode = ref(settingsStore.editorSettings.openTabsRestoreMode); const editDisconnectTabHandlingMode = ref(settingsStore.editorSettings.disconnectTabHandlingMode); const editDataTabReuseMode = ref(settingsStore.editorSettings.dataTabReuseMode); @@ -656,7 +656,7 @@ function currentEditorSettingsDraft(): EditorSettingsDraft { routineSourceOpenMode: editRoutineSourceOpenMode.value, sidebarTableSearchEnabled: editSidebarTableSearchEnabled.value, autoSelectActiveSidebarNode: editAutoSelectActiveSidebarNode.value, - sidebarOpenDatabaseOnSingleClick: editSidebarOpenDatabaseOnSingleClick.value, + sidebarBrowseObjectsOnDatabaseActivation: editSidebarBrowseObjectsOnDatabaseActivation.value, openTabsRestoreMode: editOpenTabsRestoreMode.value, disconnectTabHandlingMode: editDisconnectTabHandlingMode.value, dataTabReuseMode: editDataTabReuseMode.value, @@ -1052,7 +1052,7 @@ function syncEditorSettingsDraftFromStore() { editRoutineSourceOpenMode.value = settingsStore.editorSettings.routineSourceOpenMode; editSidebarTableSearchEnabled.value = settingsStore.editorSettings.sidebarTableSearchEnabled; editAutoSelectActiveSidebarNode.value = settingsStore.editorSettings.autoSelectActiveSidebarNode; - editSidebarOpenDatabaseOnSingleClick.value = settingsStore.editorSettings.sidebarOpenDatabaseOnSingleClick; + editSidebarBrowseObjectsOnDatabaseActivation.value = settingsStore.editorSettings.sidebarBrowseObjectsOnDatabaseActivation; editOpenTabsRestoreMode.value = settingsStore.editorSettings.openTabsRestoreMode; editDisconnectTabHandlingMode.value = settingsStore.editorSettings.disconnectTabHandlingMode; editDataTabReuseMode.value = settingsStore.editorSettings.dataTabReuseMode; @@ -1313,7 +1313,7 @@ function resetDefaultsForTab(tab: SettingsCategory) { editRoutineSourceOpenMode.value = DEFAULT_EDITOR_SETTINGS.routineSourceOpenMode; editSidebarTableSearchEnabled.value = DEFAULT_EDITOR_SETTINGS.sidebarTableSearchEnabled; editAutoSelectActiveSidebarNode.value = DEFAULT_EDITOR_SETTINGS.autoSelectActiveSidebarNode; - editSidebarOpenDatabaseOnSingleClick.value = DEFAULT_EDITOR_SETTINGS.sidebarOpenDatabaseOnSingleClick; + editSidebarBrowseObjectsOnDatabaseActivation.value = DEFAULT_EDITOR_SETTINGS.sidebarBrowseObjectsOnDatabaseActivation; editOpenTabsRestoreMode.value = DEFAULT_EDITOR_SETTINGS.openTabsRestoreMode; editDisconnectTabHandlingMode.value = DEFAULT_EDITOR_SETTINGS.disconnectTabHandlingMode; editDataTabReuseMode.value = DEFAULT_EDITOR_SETTINGS.dataTabReuseMode; @@ -1447,7 +1447,7 @@ function resetAllDefaults() { editRoutineSourceOpenMode.value = DEFAULT_EDITOR_SETTINGS.routineSourceOpenMode; editSidebarTableSearchEnabled.value = DEFAULT_EDITOR_SETTINGS.sidebarTableSearchEnabled; editAutoSelectActiveSidebarNode.value = DEFAULT_EDITOR_SETTINGS.autoSelectActiveSidebarNode; - editSidebarOpenDatabaseOnSingleClick.value = DEFAULT_EDITOR_SETTINGS.sidebarOpenDatabaseOnSingleClick; + editSidebarBrowseObjectsOnDatabaseActivation.value = DEFAULT_EDITOR_SETTINGS.sidebarBrowseObjectsOnDatabaseActivation; editOpenTabsRestoreMode.value = DEFAULT_EDITOR_SETTINGS.openTabsRestoreMode; editDisconnectTabHandlingMode.value = DEFAULT_EDITOR_SETTINGS.disconnectTabHandlingMode; editDataTabReuseMode.value = DEFAULT_EDITOR_SETTINGS.dataTabReuseMode; @@ -5396,6 +5396,15 @@ onUnmounted(() => { +
+
+ + + {{ t("settings.sidebarBrowseObjectsOnDatabaseActivationDescription") }} + +
+ +
@@ -5556,15 +5565,6 @@ onUnmounted(() => {
-
-
- - - {{ t("settings.sidebarOpenDatabaseOnSingleClickDescription") }} - -
- -
diff --git a/apps/desktop/src/components/editor/__tests__/EditorSettingsDialog.previewPosition.spec.ts b/apps/desktop/src/components/editor/__tests__/EditorSettingsDialog.previewPosition.spec.ts index f3e9a33934..e948b1a1fe 100644 --- a/apps/desktop/src/components/editor/__tests__/EditorSettingsDialog.previewPosition.spec.ts +++ b/apps/desktop/src/components/editor/__tests__/EditorSettingsDialog.previewPosition.spec.ts @@ -138,16 +138,16 @@ describe("EditorSettingsDialog live preview placement", () => { const objectDisplay = navigationSection.indexOf('t("settings.sidebarObjectDisplay")'); const routineOpenMode = navigationSection.indexOf('t("settings.routineSourceOpenMode")'); const tableNavigation = navigationSection.indexOf('id="editor-click-table-navigation-ddl"'); - const openDatabaseOnClick = navigationSection.indexOf('id="sidebar-open-database-on-single-click"'); + const browseObjectsOnDatabaseActivation = navigationSection.indexOf('id="sidebar-browse-objects-on-database-activation"'); const tableSearch = navigationSection.indexOf('id="sidebar-table-search-enabled"'); const activeNodeSelection = navigationSection.indexOf('id="auto-select-active-sidebar-node"'); - expect(adjacentDataTabs).toBeGreaterThanOrEqual(0); + expect(browseObjectsOnDatabaseActivation).toBeGreaterThanOrEqual(0); + expect(adjacentDataTabs).toBeGreaterThan(browseObjectsOnDatabaseActivation); expect(objectDisplay).toBeGreaterThan(adjacentDataTabs); expect(routineOpenMode).toBeGreaterThan(objectDisplay); expect(tableNavigation).toBeGreaterThan(routineOpenMode); - expect(openDatabaseOnClick).toBeGreaterThan(tableNavigation); - expect(tableSearch).toBeGreaterThan(openDatabaseOnClick); + expect(tableSearch).toBeGreaterThan(tableNavigation); expect(activeNodeSelection).toBeGreaterThan(tableSearch); }); diff --git a/apps/desktop/src/components/sidebar/SidebarTreeRuntimeHost.vue b/apps/desktop/src/components/sidebar/SidebarTreeRuntimeHost.vue index 88d1092d18..275e4dccb0 100644 --- a/apps/desktop/src/components/sidebar/SidebarTreeRuntimeHost.vue +++ b/apps/desktop/src/components/sidebar/SidebarTreeRuntimeHost.vue @@ -1005,7 +1005,7 @@ function runRowClickAction(clickDetail: number, requestId: number) { void openObjectBrowser(); return; } - const action = treeNodeRowAction(node.type, canExpand.value, settingsStore.editorSettings.sidebarActivation, currentDatabaseType(), settingsStore.editorSettings.sidebarOpenDatabaseOnSingleClick, canOpenObjectBrowser.value); + const action = treeNodeRowAction(node.type, canExpand.value, settingsStore.editorSettings.sidebarActivation, currentDatabaseType(), settingsStore.editorSettings.sidebarBrowseObjectsOnDatabaseActivation, canOpenObjectBrowser.value); // WebKit can keep incrementing click.detail while the pointer moves quickly // between adjacent rows. Nacos entries are idempotent navigation targets, so // do not mistake that rapid one-click switching for a double-click toggle. @@ -1370,7 +1370,7 @@ function onDoubleClick(event: MouseEvent) { void openObjectBrowser(); return; } - const action = treeNodeRowDoubleClickAction(activeNode.value.type, canOpenObjectBrowser.value, settingsStore.editorSettings.sidebarActivation, canExpand.value, currentDatabaseType(), canOpenConnectionDatabaseBrowser.value, settingsStore.editorSettings.sidebarOpenDatabaseOnSingleClick); + const action = treeNodeRowDoubleClickAction(activeNode.value.type, canOpenObjectBrowser.value, settingsStore.editorSettings.sidebarActivation, canExpand.value, currentDatabaseType(), canOpenConnectionDatabaseBrowser.value, settingsStore.editorSettings.sidebarBrowseObjectsOnDatabaseActivation); if (action === "open-database-browser") { void openDatabaseBrowser(); } else if (action === "open-object-browser") { diff --git a/apps/desktop/src/components/sidebar/TreeItem.vue b/apps/desktop/src/components/sidebar/TreeItem.vue index 7c1285f83b..a895229f10 100644 --- a/apps/desktop/src/components/sidebar/TreeItem.vue +++ b/apps/desktop/src/components/sidebar/TreeItem.vue @@ -86,7 +86,7 @@ import { sidebarTreeRuntimeKey } from "@/lib/sidebar/sidebarTreeRuntime"; import { treeNodePinKey } from "@/lib/app/pinnedItems"; import { isTreeGroupNodeType } from "@/lib/sidebar/treeNodeGroup"; import { customTypeCapabilities } from "@/lib/database/databaseObjectCapabilities"; -import { shouldActivateTreeNodeOnSingleClick, shouldOpenObjectBrowserOnSingleClick } from "@/lib/sidebar/treeNodeClick"; +import { shouldActivateTreeNodeOnSingleClick } from "@/lib/sidebar/treeNodeClick"; const { t } = useI18n(); @@ -1362,10 +1362,6 @@ function onClick(event: MouseEvent) { } selectSingleTreeNode(props.node); rowRef.value?.focus({ preventScroll: true }); - if (shouldOpenObjectBrowserOnSingleClick(props.node.type, settingsStore.editorSettings.sidebarOpenDatabaseOnSingleClick)) { - treeRuntime.handleRowClick(props.node, event.detail); - return; - } if (!shouldActivateTreeNodeOnSingleClick(props.node.type, settingsStore.editorSettings.sidebarActivation) && props.node.type !== "load-more") return; treeRuntime.handleRowClick(props.node, event.detail); } diff --git a/apps/desktop/src/i18n/locales/en.ts b/apps/desktop/src/i18n/locales/en.ts index 3909d0af34..6b23386101 100644 --- a/apps/desktop/src/i18n/locales/en.ts +++ b/apps/desktop/src/i18n/locales/en.ts @@ -6486,8 +6486,8 @@ export default { routineSourceOpenModeDialogDescription: "Open source in a popup dialog for quick viewing and editing.", autoSelectActiveSidebarNode: "Always select opened item", autoSelectActiveSidebarNodeDescription: "When switching tabs, select the matching visible table, collection, or SQL file in the sidebar.", - sidebarOpenDatabaseOnSingleClick: "Browse objects on database single click", - sidebarOpenDatabaseOnSingleClickDescription: 'When enabled, single-clicking a database or schema node also expands the sidebar and opens the "Browse Objects" tab.', + sidebarBrowseObjectsOnDatabaseActivation: "Browse objects when activating a database", + sidebarBrowseObjectsOnDatabaseActivationDescription: 'When enabled, activating a database or schema node using the selected single- or double-click mode also opens the "Browse Objects" tab.', openTabsRestoreMode: "Restore tabs on launch", openTabsRestoreModeDescription: "Choose how DBX restores tabs that were open last time.", openTabsRestoreModeAll: "Keep all tabs", diff --git a/apps/desktop/src/i18n/locales/es.ts b/apps/desktop/src/i18n/locales/es.ts index 93aa8009e9..2597459fa9 100644 --- a/apps/desktop/src/i18n/locales/es.ts +++ b/apps/desktop/src/i18n/locales/es.ts @@ -6157,8 +6157,8 @@ export default withEnglishFallback({ sidebarObjectDisplaySimpleDescription: "Muestra tablas y vistas directamente bajo cada base de datos o esquema para reducir niveles intermedios.", autoSelectActiveSidebarNode: "Seleccionar siempre el elemento abierto", autoSelectActiveSidebarNodeDescription: "Al cambiar de pestaña, selecciona la tabla, colección o archivo SQL visible correspondiente en la barra lateral.", - sidebarOpenDatabaseOnSingleClick: "Explorar objetos al hacer clic en la base de datos", - sidebarOpenDatabaseOnSingleClickDescription: 'Si está activado, al hacer un solo clic en un nodo de base de datos o esquema se expande la barra lateral y se abre la pestaña "Explorar objetos".', + sidebarBrowseObjectsOnDatabaseActivation: "Explorar objetos al activar una base de datos", + sidebarBrowseObjectsOnDatabaseActivationDescription: 'Si está activado, al activar un nodo de base de datos o esquema con el modo seleccionado de uno o dos clics también se abre la pestaña "Explorar objetos".', openTabsRestoreMode: "Restaurar pestañas al iniciar", openTabsRestoreModeDescription: "Elige cómo DBX restaura las pestañas que estaban abiertas la última vez.", openTabsRestoreModeAll: "Conservar todas las pestañas", diff --git a/apps/desktop/src/i18n/locales/it.ts b/apps/desktop/src/i18n/locales/it.ts index 4e4f9731d4..0c92b7ba0e 100644 --- a/apps/desktop/src/i18n/locales/it.ts +++ b/apps/desktop/src/i18n/locales/it.ts @@ -6157,8 +6157,8 @@ export default withEnglishFallback({ sidebarObjectDisplaySimpleDescription: "Elenca tabelle e viste direttamente sotto ogni database o schema per ridurre i livelli intermedi.", autoSelectActiveSidebarNode: "Seleziona sempre l'elemento aperto", autoSelectActiveSidebarNodeDescription: "Quando passi da una scheda all'altra, seleziona la tabella, la collezione o il file SQL visibile corrispondente nella barra laterale.", - sidebarOpenDatabaseOnSingleClick: "Sfoglia oggetti al clic sul database", - sidebarOpenDatabaseOnSingleClickDescription: 'Se abilitato, un singolo clic su un nodo database o schema espande la barra laterale e apre la scheda "Esplora Oggetti".', + sidebarBrowseObjectsOnDatabaseActivation: "Esplora oggetti all'attivazione di un database", + sidebarBrowseObjectsOnDatabaseActivationDescription: "Se abilitato, l'attivazione di un nodo database o schema con la modalità a clic singolo o doppio selezionata apre anche la scheda «Esplora oggetti».", openTabsRestoreMode: "Ripristina schede all'avvio", openTabsRestoreModeDescription: "Scegli come DBX ripristina le schede aperte l'ultima volta.", openTabsRestoreModeAll: "Mantieni tutte le schede", diff --git a/apps/desktop/src/i18n/locales/ja.ts b/apps/desktop/src/i18n/locales/ja.ts index f4a2d5945b..222c93b5fb 100644 --- a/apps/desktop/src/i18n/locales/ja.ts +++ b/apps/desktop/src/i18n/locales/ja.ts @@ -6183,8 +6183,8 @@ export default withEnglishFallback({ sidebarObjectDisplaySimpleDescription: "中間レベルを減らすために、各データベースまたはスキーマの直下にテーブルとビューを一覧表示します。", autoSelectActiveSidebarNode: "開いた項目を常に選択", autoSelectActiveSidebarNodeDescription: "タブ切替時に、サイドバーで一致する表示中のテーブル、コレクション、またはSQLファイルを選択します。", - sidebarOpenDatabaseOnSingleClick: "データベースのシングルクリックでオブジェクトを参照", - sidebarOpenDatabaseOnSingleClickDescription: "有効にすると、データベースまたはスキーマノードをシングルクリックした際に、サイドバーを展開すると同時に「オブジェクトを参照」タブを開きます。", + sidebarBrowseObjectsOnDatabaseActivation: "データベースノードのアクティブ化時にオブジェクトを参照", + sidebarBrowseObjectsOnDatabaseActivationDescription: "有効にすると、選択したシングルクリックまたはダブルクリック方式でデータベースまたはスキーマノードをアクティブ化した際に、サイドバーを展開すると同時に「オブジェクトを参照」タブを開きます。", openTabsRestoreMode: "起動時にタブを復元", openTabsRestoreModeDescription: "DBX 起動時に前回開いていたタブをどのように復元するかを選択します。", openTabsRestoreModeAll: "すべてのタブを保持", diff --git a/apps/desktop/src/i18n/locales/ko.ts b/apps/desktop/src/i18n/locales/ko.ts index 54e403f7f1..b5a6da7714 100644 --- a/apps/desktop/src/i18n/locales/ko.ts +++ b/apps/desktop/src/i18n/locales/ko.ts @@ -5877,8 +5877,8 @@ export default withEnglishFallback({ sidebarObjectDisplaySimpleDescription: "중간 수준을 줄이기 위해 각 데이터베이스나 스키마 아래에 테이블과 뷰를 직접 나열합니다.", autoSelectActiveSidebarNode: "열린 항목 항상 선택", autoSelectActiveSidebarNodeDescription: "탭을 전환할 때 사이드바에서 일치하는 표시된 테이블, 컬렉션 또는 SQL 파일을 선택합니다.", - sidebarOpenDatabaseOnSingleClick: "데이터베이스 클릭 시 객체 탐색", - sidebarOpenDatabaseOnSingleClickDescription: '활성화하면 데이터베이스 또는 스키마 노드를 한 번 클릭할 때 사이드바를 펼치면서 "객체 탐색" 탭을 엽니다.', + sidebarBrowseObjectsOnDatabaseActivation: "데이터베이스 노드 활성화 시 객체 탐색", + sidebarBrowseObjectsOnDatabaseActivationDescription: '활성화하면 선택한 한 번 클릭 또는 두 번 클릭 방식으로 데이터베이스나 스키마 노드를 활성화할 때 사이드바를 펼치면서 "객체 탐색" 탭을 엽니다.', openTabsRestoreMode: "실행 시 탭 복원", openTabsRestoreModeDescription: "DBX가 지난번에 열려 있던 탭을 복원하는 방법을 선택하세요.", openTabsRestoreModeAll: "모든 탭 유지", diff --git a/apps/desktop/src/i18n/locales/pt-BR.ts b/apps/desktop/src/i18n/locales/pt-BR.ts index 8fb0065317..409f6346d3 100644 --- a/apps/desktop/src/i18n/locales/pt-BR.ts +++ b/apps/desktop/src/i18n/locales/pt-BR.ts @@ -6159,8 +6159,8 @@ export default withEnglishFallback({ sidebarObjectDisplaySimpleDescription: "Listar tabelas e views diretamente sob cada banco de dados ou schema para reduzir os níveis intermediários.", autoSelectActiveSidebarNode: "Sempre selecionar o item aberto", autoSelectActiveSidebarNodeDescription: "Ao alternar abas, selecionar a tabela, coleção ou arquivo SQL correspondente visível na barra lateral.", - sidebarOpenDatabaseOnSingleClick: "Explorar objetos ao clicar no banco de dados", - sidebarOpenDatabaseOnSingleClickDescription: 'Quando ativado, um clique único em um nó de banco de dados ou esquema expande a barra lateral e abre a aba "Explorar Objetos".', + sidebarBrowseObjectsOnDatabaseActivation: "Explorar objetos ao ativar um banco de dados", + sidebarBrowseObjectsOnDatabaseActivationDescription: 'Quando ativado, ativar um nó de banco de dados ou esquema com o modo selecionado de clique simples ou duplo também abre a aba "Explorar Objetos".', openTabsRestoreMode: "Restaurar abas ao iniciar", openTabsRestoreModeDescription: "Escolha como o DBX restaura as abas que estavam abertas na última vez.", openTabsRestoreModeAll: "Manter todas as abas", diff --git a/apps/desktop/src/i18n/locales/zh-CN.ts b/apps/desktop/src/i18n/locales/zh-CN.ts index f85e6617a0..a8a6ba4aa4 100644 --- a/apps/desktop/src/i18n/locales/zh-CN.ts +++ b/apps/desktop/src/i18n/locales/zh-CN.ts @@ -6469,8 +6469,8 @@ export default withEnglishFallback({ routineSourceOpenModeDialogDescription: "在弹出对话框中打开源码,方便快速查看和编辑。", autoSelectActiveSidebarNode: "始终选中已打开项目", autoSelectActiveSidebarNodeDescription: "切换标签页时,在侧边栏选中匹配的可见表、集合或 SQL 文件。", - sidebarOpenDatabaseOnSingleClick: "单击数据库时浏览对象", - sidebarOpenDatabaseOnSingleClickDescription: "开启后,单击数据库或模式节点时,会同时展开侧边栏并打开“浏览对象”标签页。", + sidebarBrowseObjectsOnDatabaseActivation: "激活数据库节点时浏览对象", + sidebarBrowseObjectsOnDatabaseActivationDescription: "开启后,按照所选的单击或双击激活方式操作数据库或模式节点时,会同时展开侧边栏并打开“浏览对象”标签页。", openTabsRestoreMode: "启动时恢复标签页", openTabsRestoreModeDescription: "选择 DBX 启动时如何恢复上次打开的标签页。", openTabsRestoreModeAll: "保留所有标签", diff --git a/apps/desktop/src/i18n/locales/zh-TW.ts b/apps/desktop/src/i18n/locales/zh-TW.ts index 05bbfc6cdd..4d1dc6c108 100644 --- a/apps/desktop/src/i18n/locales/zh-TW.ts +++ b/apps/desktop/src/i18n/locales/zh-TW.ts @@ -5475,8 +5475,8 @@ export default withEnglishFallback({ sidebarObjectDisplaySimpleDescription: "直接在每個資料庫或 schema 下列出資料表與檢視,減少中間層級。", autoSelectActiveSidebarNode: "一律選取已開啟項目", autoSelectActiveSidebarNodeDescription: "切換分頁時,在側邊欄選取相符的可見資料表、集合或 SQL 檔案。", - sidebarOpenDatabaseOnSingleClick: "單擊資料庫時瀏覽物件", - sidebarOpenDatabaseOnSingleClickDescription: "開啟後,單擊資料庫或結構描述節點時,會同時展開側邊欄並開啟「瀏覽物件」分頁。", + sidebarBrowseObjectsOnDatabaseActivation: "啟用資料庫節點時瀏覽物件", + sidebarBrowseObjectsOnDatabaseActivationDescription: "開啟後,依照所選的單擊或雙擊啟用方式操作資料庫或結構描述節點時,會同時展開側邊欄並開啟「瀏覽物件」分頁。", openTabsRestoreMode: "啟動時還原分頁", openTabsRestoreModeDescription: "選擇 DBX 啟動時如何還原上次開啟的分頁。", openTabsRestoreModeAll: "保留所有分頁", diff --git a/apps/desktop/src/lib/__tests__/sidebar/treeNodeClick.spec.ts b/apps/desktop/src/lib/__tests__/sidebar/treeNodeClick.spec.ts index 134cde172d..c32d0d9ad5 100644 --- a/apps/desktop/src/lib/__tests__/sidebar/treeNodeClick.spec.ts +++ b/apps/desktop/src/lib/__tests__/sidebar/treeNodeClick.spec.ts @@ -5,7 +5,7 @@ import { objectSourceKindForTreeNode, objectSourceTargetForTreeNode, shouldActivateTreeNodeOnSingleClick, - shouldOpenObjectBrowserOnSingleClick, + shouldBrowseObjectsOnDatabaseActivation, shouldRunTreeNodeRowAction, treeNodeRowAction, treeNodeRowDoubleClickAction, @@ -90,51 +90,55 @@ describe("treeNodeClick", () => { expect(treeNodeRowDoubleClickAction("connection", false, "double", false, "postgres", true)).toBe("none"); }); - it("opens the object browser on single click when the database single-click switch is on", () => { + it("browses objects on single-click activation only when enabled", () => { expect(treeNodeRowAction("database", true, "single", "postgres", true, true)).toBe("open-object-browser-and-expand"); expect(treeNodeRowAction("database", false, "single", "postgres", true, true)).toBe("open-object-browser"); expect(treeNodeRowAction("schema", true, "single", "postgres", true, true)).toBe("open-object-browser-and-expand"); - expect(treeNodeRowAction("object-browser", false, "single", "postgres", true, true)).toBe("open-object-browser"); + expect(treeNodeRowAction("database", true, "single", "postgres", false, true)).toBe("toggle"); + expect(treeNodeRowAction("schema", true, "single", "postgres", false, true)).toBe("toggle"); }); - it("lets the database single-click switch override double-click activation", () => { - expect(treeNodeRowAction("database", true, "double", "postgres", true, true)).toBe("open-object-browser-and-expand"); - expect(treeNodeRowAction("schema", false, "double", "postgres", true, true)).toBe("open-object-browser"); + it("keeps the first click selection-only in double-click activation", () => { + expect(treeNodeRowAction("database", true, "double", "postgres", true, true)).toBe("none"); + expect(treeNodeRowAction("schema", true, "double", "postgres", true, true)).toBe("none"); + expect(treeNodeRowAction("database", true, "double", "postgres", false, true)).toBe("none"); }); - it("does not reopen the object browser when the single-click switch already handled the gesture", () => { + it("does not run a second database action after single-click activation", () => { expect(treeNodeRowDoubleClickAction("database", true, "single", true, "postgres", false, true)).toBe("none"); - expect(treeNodeRowDoubleClickAction("schema", true, "double", true, "postgres", false, true)).toBe("none"); - expect(treeNodeRowDoubleClickAction("object-browser", true, "single", false, "postgres", false, true)).toBe("none"); + expect(treeNodeRowDoubleClickAction("database", true, "single", true, "postgres", false, false)).toBe("none"); + expect(treeNodeRowDoubleClickAction("schema", true, "single", true, "postgres", false, true)).toBe("none"); }); - it("keeps the existing double-click fallback when single-click browsing is unavailable", () => { - expect(treeNodeRowDoubleClickAction("database", true, "single", true, "postgres", false, false)).toBe("open-object-browser"); + it("browses objects on double-click activation only when enabled", () => { + expect(treeNodeRowDoubleClickAction("database", true, "double", true, "postgres", false, true)).toBe("open-object-browser-and-expand"); + expect(treeNodeRowDoubleClickAction("schema", true, "double", false, "postgres", false, true)).toBe("open-object-browser"); + expect(treeNodeRowDoubleClickAction("database", true, "double", true, "postgres", false, false)).toBe("toggle"); + expect(treeNodeRowDoubleClickAction("schema", true, "double", false, "postgres", false, false)).toBe("none"); + }); + + it("falls back to expansion when object browsing is unsupported", () => { + expect(treeNodeRowAction("database", true, "single", "postgres", true, false)).toBe("toggle"); + expect(treeNodeRowAction("database", true, "double", "postgres", true, false)).toBe("none"); expect(treeNodeRowDoubleClickAction("database", false, "double", true, "postgres", false, true)).toBe("toggle"); }); - it("keeps the original single-click behavior when the database single-click switch is off or unsupported", () => { - expect(treeNodeRowAction("database", true, "single", "postgres", false, true)).toBe("toggle"); - expect(treeNodeRowAction("database", true, "double", "postgres", false, true)).toBe("none"); - // Capability off (e.g. unsupported database type) falls back to the previous behavior. - expect(treeNodeRowAction("database", true, "single", "postgres", true, false)).toBe("toggle"); - expect(treeNodeRowAction("database", true, "double", "postgres", true, false)).toBe("none"); - }); - - it("does not route non-database nodes through the database single-click switch", () => { + it("does not route non-database nodes through the database activation switch", () => { expect(treeNodeRowAction("table", false, "single", "postgres", true, true)).toBe("open-data"); expect(treeNodeRowAction("table", false, "double", "postgres", true, true)).toBe("none"); - expect(shouldOpenObjectBrowserOnSingleClick("table", true)).toBe(false); - expect(shouldOpenObjectBrowserOnSingleClick("database", true)).toBe(true); - expect(shouldOpenObjectBrowserOnSingleClick("database", false)).toBe(false); - expect(shouldOpenObjectBrowserOnSingleClick("mongo-db", true)).toBe(true); - expect(shouldOpenObjectBrowserOnSingleClick("mongo-db", false)).toBe(false); + expect(shouldBrowseObjectsOnDatabaseActivation("table", true)).toBe(false); + expect(shouldBrowseObjectsOnDatabaseActivation("database", true)).toBe(true); + expect(shouldBrowseObjectsOnDatabaseActivation("database", false)).toBe(false); + expect(shouldBrowseObjectsOnDatabaseActivation("mongo-db", true)).toBe(true); + expect(shouldBrowseObjectsOnDatabaseActivation("object-browser", true)).toBe(false); + expect(treeNodeRowDoubleClickAction("object-browser", true, "double", false, "postgres", false, false)).toBe("open-object-browser"); }); it("opens the MongoDB object browser from mongo-db nodes like SQL databases", () => { expect(treeNodeRowAction("mongo-db", true, "single", "mongodb", true, true)).toBe("open-object-browser-and-expand"); expect(treeNodeRowAction("mongo-db", true, "single", "mongodb", false, true)).toBe("toggle"); - expect(treeNodeRowDoubleClickAction("mongo-db", true, "single", true, "mongodb")).toBe("open-object-browser"); + expect(treeNodeRowDoubleClickAction("mongo-db", true, "single", true, "mongodb", false, true)).toBe("none"); + expect(treeNodeRowDoubleClickAction("mongo-db", true, "double", true, "mongodb", false, true)).toBe("open-object-browser-and-expand"); }); it("expands package containers while preserving source behavior for leaf packages", () => { diff --git a/apps/desktop/src/lib/settings/editorSettingsDraft.ts b/apps/desktop/src/lib/settings/editorSettingsDraft.ts index 53d2ec86ad..01ebc0da92 100644 --- a/apps/desktop/src/lib/settings/editorSettingsDraft.ts +++ b/apps/desktop/src/lib/settings/editorSettingsDraft.ts @@ -65,7 +65,7 @@ export const EDITOR_SETTINGS_DRAFT_KEYS = [ "routineSourceOpenMode", "sidebarTableSearchEnabled", "autoSelectActiveSidebarNode", - "sidebarOpenDatabaseOnSingleClick", + "sidebarBrowseObjectsOnDatabaseActivation", "openTabsRestoreMode", "disconnectTabHandlingMode", "dataTabReuseMode", diff --git a/apps/desktop/src/lib/settings/settingsSearch.ts b/apps/desktop/src/lib/settings/settingsSearch.ts index 434a14273d..e958f05af4 100644 --- a/apps/desktop/src/lib/settings/settingsSearch.ts +++ b/apps/desktop/src/lib/settings/settingsSearch.ts @@ -170,7 +170,7 @@ export const SETTINGS_SEARCH_DEFINITIONS: readonly SettingsSearchDefinition[] = { id: "navigation-object-info", category: "navigation", titleKey: "settings.sidebarObjectInfoMode", descriptionKey: "settings.sidebarObjectInfoModeDescription", targetId: "navigation" }, { id: "navigation-table-search", category: "navigation", titleKey: "settings.sidebarTableSearchEnabled", descriptionKey: "settings.sidebarTableSearchEnabledDescription", targetId: "navigation" }, { id: "navigation-active-node", category: "navigation", titleKey: "settings.autoSelectActiveSidebarNode", descriptionKey: "settings.autoSelectActiveSidebarNodeDescription", targetId: "navigation" }, - { id: "navigation-open-database-on-single-click", category: "navigation", titleKey: "settings.sidebarOpenDatabaseOnSingleClick", descriptionKey: "settings.sidebarOpenDatabaseOnSingleClickDescription", targetId: "navigation" }, + { id: "navigation-browse-objects-on-database-activation", category: "navigation", titleKey: "settings.sidebarBrowseObjectsOnDatabaseActivation", descriptionKey: "settings.sidebarBrowseObjectsOnDatabaseActivationDescription", targetId: "navigation" }, { id: "navigation-tabs-restore", category: "navigation", titleKey: "settings.openTabsRestoreMode", descriptionKey: "settings.openTabsRestoreModeDescription", targetId: "navigation" }, { id: "navigation-sidebar-scroll", category: "navigation", titleKey: "settings.sidebarAllowHorizontalScroll", descriptionKey: "settings.sidebarAllowHorizontalScrollDescription", targetId: "navigation" }, { id: "navigation-sidebar-indent", category: "navigation", titleKey: "settings.sidebarIndent", descriptionKey: "settings.sidebarIndentDescription", targetId: "navigation" }, diff --git a/apps/desktop/src/lib/sidebar/treeNodeClick.ts b/apps/desktop/src/lib/sidebar/treeNodeClick.ts index 992195b300..e6a9a67f72 100644 --- a/apps/desktop/src/lib/sidebar/treeNodeClick.ts +++ b/apps/desktop/src/lib/sidebar/treeNodeClick.ts @@ -49,11 +49,10 @@ export function isRepeatableNavigationTreeNode(type: TreeNodeType): boolean { export function shouldActivateTreeNodeOnSingleClick(type: TreeNodeType, activation: SidebarActivation = "single"): boolean { return activation !== "double" || isDirectNavigationTreeNode(type); } -const objectBrowserNodeTypes = new Set(["database", "schema", "object-browser", "mongo-db"]); +const databaseActivationNodeTypes = new Set(["database", "schema", "mongo-db"]); -/** 开关“单击数据库同时打开数据库项目”命中时,单击数据库类节点直接打开对象浏览器标签页。 */ -export function shouldOpenObjectBrowserOnSingleClick(type: TreeNodeType, enabled: boolean): boolean { - return enabled && objectBrowserNodeTypes.has(type); +export function shouldBrowseObjectsOnDatabaseActivation(type: TreeNodeType, enabled: boolean): boolean { + return enabled && databaseActivationNodeTypes.has(type); } const sourceNodeTypes = new Set(["materialized_view", "procedure", "function", "trigger", "event", "sequence", "synonym", "job", "package", "package-body", "type", "type-body"]); const savedSqlNodeTypes = new Set(["saved-sql-file"]); @@ -132,12 +131,11 @@ function canOpenTreeNodeSource(type: TreeNodeType, dbType?: DatabaseType): boole return true; } -export function treeNodeRowAction(type: TreeNodeType, canExpand: boolean, activation: SidebarActivation = "single", dbType?: DatabaseType, openDatabaseOnSingleClick = false, canOpenObjectBrowser = false): TreeNodeRowAction { - // “单击数据库同时打开数据库项目”开关优先于激活方式:单击即等效双击的打开行为。 - if (openDatabaseOnSingleClick && canOpenObjectBrowser && shouldOpenObjectBrowserOnSingleClick(type, true)) { +export function treeNodeRowAction(type: TreeNodeType, canExpand: boolean, activation: SidebarActivation = "single", dbType?: DatabaseType, browseObjectsOnDatabaseActivation = false, canOpenObjectBrowser = false): TreeNodeRowAction { + if (!shouldActivateTreeNodeOnSingleClick(type, activation)) return "none"; + if (canOpenObjectBrowser && shouldBrowseObjectsOnDatabaseActivation(type, browseObjectsOnDatabaseActivation)) { return canExpand ? "open-object-browser-and-expand" : "open-object-browser"; } - if (!shouldActivateTreeNodeOnSingleClick(type, activation)) return "none"; if (type === "extension") return "open-extension-details"; if (savedSqlNodeTypes.has(type)) return "open-saved-sql"; if (dataNodeTypes.has(type)) return "open-data"; @@ -158,26 +156,26 @@ export function shouldRunTreeNodeRowAction(action: TreeNodeRowAction, clickDetai return action !== "none" && clickDetail <= 1; } -export function treeNodeRowDoubleClickAction(type: TreeNodeType, canOpenObjectBrowser: boolean, activation: SidebarActivation = "single", canExpand = false, dbType?: DatabaseType, canOpenDatabaseBrowser = false, openDatabaseOnSingleClick = false): TreeNodeRowDoubleClickAction { +export function treeNodeRowDoubleClickAction(type: TreeNodeType, canOpenObjectBrowser: boolean, activation: SidebarActivation = "single", canExpand = false, dbType?: DatabaseType, canOpenDatabaseBrowser = false, browseObjectsOnDatabaseActivation = false): TreeNodeRowDoubleClickAction { // 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 (openDatabaseOnSingleClick && canOpenObjectBrowser && shouldOpenObjectBrowserOnSingleClick(type, true)) return "none"; // 双击激活模式下,双击连接节点应当展开树(与单击模式下单击展开一致), // “打开数据库浏览”只保留给单击激活模式下的双击手势。 if (type === "connection" && canOpenDatabaseBrowser && activation !== "double") return "open-database-browser"; if (activation === "double") { + if (canOpenObjectBrowser && shouldBrowseObjectsOnDatabaseActivation(type, browseObjectsOnDatabaseActivation)) { + return canExpand ? "open-object-browser-and-expand" : "open-object-browser"; + } + if (canOpenObjectBrowser && type === "object-browser") return "open-object-browser"; if (type === "extension") return "open-extension-details"; if (dataNodeTypes.has(type)) return "open-data"; if (type === "type" && customTypeCapabilities(dbType).details) return canExpand ? "toggle" : "none"; if (sourceNodeTypes.has(type) && canOpenTreeNodeSource(type, dbType)) return "open-source"; if (savedSqlNodeTypes.has(type)) return "open-saved-sql"; if (toggleLeafNodeTypes.has(type)) return "toggle"; - if (canOpenObjectBrowser && objectBrowserNodeTypes.has(type) && canExpand) return "open-object-browser-and-expand"; - if (canOpenObjectBrowser && objectBrowserNodeTypes.has(type)) return "open-object-browser"; if (canExpand) return "toggle"; } - if (canOpenObjectBrowser && objectBrowserNodeTypes.has(type)) return "open-object-browser"; return "none"; } diff --git a/apps/desktop/src/stores/settingsStore.ts b/apps/desktop/src/stores/settingsStore.ts index 8f2dd87dd8..777377103c 100644 --- a/apps/desktop/src/stores/settingsStore.ts +++ b/apps/desktop/src/stores/settingsStore.ts @@ -660,7 +660,7 @@ export interface EditorSettings { sidebarTableSearchLocal: boolean; sidebarGlobalSearchLocal: boolean; autoSelectActiveSidebarNode: boolean; - sidebarOpenDatabaseOnSingleClick: boolean; + sidebarBrowseObjectsOnDatabaseActivation: boolean; openTabsRestoreMode: OpenTabsRestoreMode; disconnectTabHandlingMode: DisconnectTabHandlingMode; dataTabReuseMode: DataTabReuseMode; @@ -877,7 +877,7 @@ export const DEFAULT_EDITOR_SETTINGS: EditorSettings = { sidebarTableSearchLocal: true, sidebarGlobalSearchLocal: false, autoSelectActiveSidebarNode: false, - sidebarOpenDatabaseOnSingleClick: false, + sidebarBrowseObjectsOnDatabaseActivation: false, openTabsRestoreMode: "all", disconnectTabHandlingMode: "close-tabs", dataTabReuseMode: DEFAULT_DATA_TAB_REUSE_MODE, @@ -1284,7 +1284,12 @@ export function normalizeEditorSettings(settings: Partial, exist sidebarTableSearchLocal: typeof settings.sidebarTableSearchLocal === "boolean" ? settings.sidebarTableSearchLocal : DEFAULT_EDITOR_SETTINGS.sidebarTableSearchLocal, sidebarGlobalSearchLocal: typeof settings.sidebarGlobalSearchLocal === "boolean" ? settings.sidebarGlobalSearchLocal : DEFAULT_EDITOR_SETTINGS.sidebarGlobalSearchLocal, autoSelectActiveSidebarNode: settings.autoSelectActiveSidebarNode ?? DEFAULT_EDITOR_SETTINGS.autoSelectActiveSidebarNode, - sidebarOpenDatabaseOnSingleClick: typeof settings.sidebarOpenDatabaseOnSingleClick === "boolean" ? settings.sidebarOpenDatabaseOnSingleClick : DEFAULT_EDITOR_SETTINGS.sidebarOpenDatabaseOnSingleClick, + sidebarBrowseObjectsOnDatabaseActivation: + typeof settings.sidebarBrowseObjectsOnDatabaseActivation === "boolean" + ? settings.sidebarBrowseObjectsOnDatabaseActivation + : typeof (settings as Partial & { sidebarOpenDatabaseOnSingleClick?: unknown }).sidebarOpenDatabaseOnSingleClick === "boolean" + ? (settings as Partial & { sidebarOpenDatabaseOnSingleClick: boolean }).sidebarOpenDatabaseOnSingleClick + : DEFAULT_EDITOR_SETTINGS.sidebarBrowseObjectsOnDatabaseActivation, openTabsRestoreMode: normalizeOpenTabsRestoreMode( (settings as Partial).openTabsRestoreMode, ( @@ -1907,7 +1912,7 @@ export const useSettingsStore = defineStore("settings", () => { if (partial.sidebarTableSearchLocal !== undefined) editorSettings.value.sidebarTableSearchLocal = partial.sidebarTableSearchLocal; if (partial.sidebarGlobalSearchLocal !== undefined) editorSettings.value.sidebarGlobalSearchLocal = partial.sidebarGlobalSearchLocal; if (partial.autoSelectActiveSidebarNode !== undefined) editorSettings.value.autoSelectActiveSidebarNode = partial.autoSelectActiveSidebarNode; - if (partial.sidebarOpenDatabaseOnSingleClick !== undefined) editorSettings.value.sidebarOpenDatabaseOnSingleClick = partial.sidebarOpenDatabaseOnSingleClick === true; + if (partial.sidebarBrowseObjectsOnDatabaseActivation !== undefined) editorSettings.value.sidebarBrowseObjectsOnDatabaseActivation = partial.sidebarBrowseObjectsOnDatabaseActivation === true; if (partial.openTabsRestoreMode !== undefined) editorSettings.value.openTabsRestoreMode = normalizeOpenTabsRestoreMode(partial.openTabsRestoreMode); if (partial.disconnectTabHandlingMode !== undefined) editorSettings.value.disconnectTabHandlingMode = normalizeDisconnectTabHandlingMode(partial.disconnectTabHandlingMode); if (partial.dataTabReuseMode !== undefined) editorSettings.value.dataTabReuseMode = normalizeDataTabReuseMode(partial.dataTabReuseMode); diff --git a/packages/app-tests/settingsStore.test.ts b/packages/app-tests/settingsStore.test.ts index 1ecdaa9fb5..3ae9bbaf46 100644 --- a/packages/app-tests/settingsStore.test.ts +++ b/packages/app-tests/settingsStore.test.ts @@ -484,6 +484,15 @@ test("defaults sidebar activation to single click", () => { assert.equal(normalizeEditorSettings({}).sidebarActivation, "single"); }); +test("defaults database activation browsing to off and migrates the previous single-click setting", () => { + assert.equal(DEFAULT_EDITOR_SETTINGS.sidebarBrowseObjectsOnDatabaseActivation, false); + assert.equal(normalizeEditorSettings({}).sidebarBrowseObjectsOnDatabaseActivation, false); + assert.equal(normalizeEditorSettings({ sidebarBrowseObjectsOnDatabaseActivation: true }).sidebarBrowseObjectsOnDatabaseActivation, true); + assert.equal(normalizeEditorSettings({ sidebarBrowseObjectsOnDatabaseActivation: "yes" as any }).sidebarBrowseObjectsOnDatabaseActivation, false); + assert.equal(normalizeEditorSettings({ sidebarOpenDatabaseOnSingleClick: true } as any).sidebarBrowseObjectsOnDatabaseActivation, true); + assert.equal(normalizeEditorSettings({ sidebarOpenDatabaseOnSingleClick: false } as any).sidebarBrowseObjectsOnDatabaseActivation, false); +}); + test("defaults active tab sidebar selection to off", () => { assert.equal(DEFAULT_EDITOR_SETTINGS.autoSelectActiveSidebarNode, false); assert.equal(normalizeEditorSettings({}).autoSelectActiveSidebarNode, false); diff --git a/packages/app-tests/treeNodeClick.test.ts b/packages/app-tests/treeNodeClick.test.ts index 7d12bab23e..a27a9e77fe 100644 --- a/packages/app-tests/treeNodeClick.test.ts +++ b/packages/app-tests/treeNodeClick.test.ts @@ -114,23 +114,33 @@ test("maps source-capable sidebar nodes to object source kinds", () => { assert.equal(objectSourceKindForTreeNode("table"), null); }); -test("database and schema rows open object browser only on double click", () => { +test("single-click activation expands database and schema rows without browsing when disabled", () => { assert.equal(treeNodeRowAction("database", true), "toggle"); assert.equal(treeNodeRowAction("schema", true), "toggle"); - assert.equal(treeNodeRowDoubleClickAction("database", true), "open-object-browser"); - assert.equal(treeNodeRowDoubleClickAction("schema", true), "open-object-browser"); + assert.equal(treeNodeRowDoubleClickAction("database", true), "none"); + assert.equal(treeNodeRowDoubleClickAction("schema", true), "none"); +}); + +test("single-click activation expands and browses database and schema rows when enabled", () => { + assert.equal(treeNodeRowAction("database", true, "single", "postgres", true, true), "open-object-browser-and-expand"); + assert.equal(treeNodeRowAction("schema", false, "single", "postgres", true, true), "open-object-browser"); + assert.equal(treeNodeRowDoubleClickAction("database", true, "single", true, "postgres", false, true), "none"); +}); + +test("double-click activation keeps the first click selection-only", () => { assert.equal(treeNodeRowAction("database", true, "double"), "none"); assert.equal(treeNodeRowAction("schema", true, "double"), "none"); + assert.equal(treeNodeRowAction("database", true, "double", "postgres", true, true), "none"); }); -test("double click navigation mode opens object browser for database and schema rows", () => { - assert.equal(treeNodeRowDoubleClickAction("database", true, "double", false), "open-object-browser"); - assert.equal(treeNodeRowDoubleClickAction("schema", true, "double", false), "open-object-browser"); +test("double-click activation only expands database and schema rows when browsing is disabled", () => { + assert.equal(treeNodeRowDoubleClickAction("database", true, "double", true, "postgres", false, false), "toggle"); + assert.equal(treeNodeRowDoubleClickAction("schema", true, "double", false, "postgres", false, false), "none"); }); -test("double click navigation mode opens object browser and expands expandable database and schema rows", () => { - assert.equal(treeNodeRowDoubleClickAction("database", true, "double", true), "open-object-browser-and-expand"); - assert.equal(treeNodeRowDoubleClickAction("schema", true, "double", true), "open-object-browser-and-expand"); +test("double-click activation expands and browses database and schema rows when enabled", () => { + assert.equal(treeNodeRowDoubleClickAction("database", true, "double", true, "postgres", false, true), "open-object-browser-and-expand"); + assert.equal(treeNodeRowDoubleClickAction("schema", true, "double", false, "postgres", false, true), "open-object-browser"); }); test("double click does not open object browser for non-browsable rows", () => {