diff --git a/apps/desktop/src/components/sidebar/ConnectionTree.vue b/apps/desktop/src/components/sidebar/ConnectionTree.vue index 258b4bcc1c..b71868c523 100644 --- a/apps/desktop/src/components/sidebar/ConnectionTree.vue +++ b/apps/desktop/src/components/sidebar/ConnectionTree.vue @@ -8,7 +8,11 @@ import { useSettingsStore } from "@/stores/settingsStore"; import type { TreeNode, TreeNodeType } from "@/types/database"; import { filterSidebarTree } from "@/lib/sidebarSearchTree"; import { isCancelSearchShortcut } from "@/lib/keyboardShortcuts"; -import { findSidebarNodeForActiveTab, scrollTopForSidebarNode } from "@/lib/sidebarActiveTabTarget"; +import { + findSidebarNodeForActiveTab, + scrollTopForSidebarNode, + shouldScrollActiveSidebarSelection, +} from "@/lib/sidebarActiveTabTarget"; import { SIDEBAR_TREE_ROW_HEIGHT, SIDEBAR_TREE_PRERENDER_COUNT, @@ -173,12 +177,14 @@ function currentTreeScroller(): HTMLElement | null { ); } -async function selectActiveTabSidebarNode() { +async function selectActiveTabSidebarNode(options: { scroll: boolean }) { if (!settingsStore.editorSettings.autoSelectActiveSidebarNode) return; const match = findSidebarNodeForActiveTab(activeTab.value, flatNodes.value); if (!match) return; store.selectedTreeNodeId = match.id; + if (!options.scroll) return; + await nextTick(); const index = flatNodes.value.findIndex((item) => item.id === match.id); @@ -196,9 +202,16 @@ async function selectActiveTabSidebarNode() { } watch( - [activeTab, flatNodes, () => settingsStore.editorSettings.autoSelectActiveSidebarNode], - () => { - void selectActiveTabSidebarNode(); + [() => activeTab.value?.id ?? null, flatNodes, () => settingsStore.editorSettings.autoSelectActiveSidebarNode], + ([activeTabId, _nodes, autoSelectEnabled], [previousActiveTabId, _previousNodes, previousAutoSelectEnabled]) => { + void selectActiveTabSidebarNode({ + scroll: shouldScrollActiveSidebarSelection({ + activeTabId, + previousActiveTabId, + autoSelectEnabled, + previousAutoSelectEnabled, + }), + }); }, { flush: "post" }, ); diff --git a/apps/desktop/src/lib/sidebarActiveTabTarget.ts b/apps/desktop/src/lib/sidebarActiveTabTarget.ts index 73df63b26d..49c074955d 100644 --- a/apps/desktop/src/lib/sidebarActiveTabTarget.ts +++ b/apps/desktop/src/lib/sidebarActiveTabTarget.ts @@ -90,6 +90,19 @@ export function findSidebarNodeForActiveTab( return flatNodes.find((item) => matchesTarget(item.node, target)) ?? null; } +export function shouldScrollActiveSidebarSelection(options: { + activeTabId: string | null | undefined; + previousActiveTabId: string | null | undefined; + autoSelectEnabled: boolean; + previousAutoSelectEnabled: boolean | undefined; +}): boolean { + if (!options.autoSelectEnabled) return false; + return ( + options.activeTabId !== options.previousActiveTabId || + (options.autoSelectEnabled && options.previousAutoSelectEnabled === false) + ); +} + export function scrollTopForSidebarNode(options: { index: number; currentScrollTop: number; diff --git a/packages/app-tests/sidebarActiveTabTarget.test.ts b/packages/app-tests/sidebarActiveTabTarget.test.ts index d62e8419f9..979151c5d4 100644 --- a/packages/app-tests/sidebarActiveTabTarget.test.ts +++ b/packages/app-tests/sidebarActiveTabTarget.test.ts @@ -4,6 +4,7 @@ import { activeTabSidebarTarget, findSidebarNodeForActiveTab, scrollTopForSidebarNode, + shouldScrollActiveSidebarSelection, } from "../../apps/desktop/src/lib/sidebarActiveTabTarget.ts"; import type { FlatTreeNode } from "../../apps/desktop/src/composables/useFlatTree.ts"; import type { QueryTab, TreeNode } from "../../apps/desktop/src/types/database.ts"; @@ -122,3 +123,33 @@ test("sidebar node scrolling keeps visible rows in place and reveals hidden rows assert.equal(scrollTopForSidebarNode({ index: 20, currentScrollTop: 0, viewportHeight: 140 }), 448); assert.equal(scrollTopForSidebarNode({ index: 1, currentScrollTop: 280, viewportHeight: 140 }), 28); }); + +test("active sidebar selection only scrolls on tab or setting changes", () => { + assert.equal( + shouldScrollActiveSidebarSelection({ + activeTabId: "tab-1", + previousActiveTabId: "tab-1", + autoSelectEnabled: true, + previousAutoSelectEnabled: true, + }), + false, + ); + assert.equal( + shouldScrollActiveSidebarSelection({ + activeTabId: "tab-2", + previousActiveTabId: "tab-1", + autoSelectEnabled: true, + previousAutoSelectEnabled: true, + }), + true, + ); + assert.equal( + shouldScrollActiveSidebarSelection({ + activeTabId: "tab-1", + previousActiveTabId: "tab-1", + autoSelectEnabled: true, + previousAutoSelectEnabled: false, + }), + true, + ); +});