From 90ad4e62e6c33b8cdefd57ce4c09f4d0873e6a50 Mon Sep 17 00:00:00 2001 From: zipg Date: Thu, 17 Sep 2026 14:32:19 +0800 Subject: [PATCH] fix(sidebar): focus object search after opening a database --- apps/desktop/src/App.vue | 16 ++++++ .../components/objects/DatabaseBrowser.vue | 6 ++- .../sidebar/SidebarTreeRuntimeHost.vue | 17 ++++--- .../SidebarTreeRuntimeHost.expansion.spec.ts | 50 ++++++++++++++++++- .../tabs/objectBrowserSearchFocus.spec.ts | 22 ++++++++ .../src/lib/tabs/objectBrowserSearchFocus.ts | 16 ++++++ 6 files changed, 117 insertions(+), 10 deletions(-) create mode 100644 apps/desktop/src/lib/__tests__/tabs/objectBrowserSearchFocus.spec.ts create mode 100644 apps/desktop/src/lib/tabs/objectBrowserSearchFocus.ts diff --git a/apps/desktop/src/App.vue b/apps/desktop/src/App.vue index 20e4a471ad..47aa823fff 100644 --- a/apps/desktop/src/App.vue +++ b/apps/desktop/src/App.vue @@ -53,6 +53,7 @@ import { translateBackendError } from "@/i18n/backend-errors"; import * as api from "@/lib/backend/api"; import { connectionRedactedNameLabel } from "@/lib/connection/connectionPresentation"; import { quickConnectionOpenTarget } from "@/lib/connection/connectionOpenTarget"; +import { OBJECT_BROWSER_SEARCH_FOCUS_EVENT, objectBrowserSearchFocusTabId } from "@/lib/tabs/objectBrowserSearchFocus"; import { parseRecentConnectionIds, rankRecentConnections, RECENT_CONNECTION_IDS_STORAGE_KEY, recordRecentConnection } from "@/lib/connection/recentConnections"; import { resolveDefaultDatabase } from "@/lib/database/defaultDatabase"; import { normalizeSqliteNamespace } from "@/lib/database/sqliteNamespace"; @@ -1068,6 +1069,19 @@ function activateQuerySurface() { activateMainContentSurface("query"); } +async function focusRequestedObjectBrowserSearch(event: Event) { + const tabId = objectBrowserSearchFocusTabId(event); + if (!tabId) return; + await nextTick(); + let remainingFrames = 8; + const focusWhenReady = () => { + if (queryStore.activeTabId !== tabId || contentAreaRef.value?.focusSearch()) return; + remainingFrames -= 1; + if (remainingFrames > 0) window.requestAnimationFrame(focusWhenReady); + }; + focusWhenReady(); +} + function activateOpenSpecialPageFallback() { if (settingsPageTabOpen.value) { activateMainContentSurface("settings"); @@ -3625,6 +3639,7 @@ onMounted(async () => { document.addEventListener("visibilitychange", handleTabSwitcherVisibilityChange); window.addEventListener("dbx-open-driver-store", openDriverStoreFromEvent); window.addEventListener("dbx:activate-query-surface", activateQuerySurface); + window.addEventListener(OBJECT_BROWSER_SEARCH_FOCUS_EVENT, focusRequestedObjectBrowserSearch); window.addEventListener("dbx-mcp-status-changed", handleMcpStatusChanged); window.addEventListener("dbx:ai-run-notify", handleAiRunNotify); if (isDesktop) { @@ -3708,6 +3723,7 @@ onUnmounted(() => { tabSwitcherKeyboard.reset(); window.removeEventListener("dbx-open-driver-store", openDriverStoreFromEvent); window.removeEventListener("dbx:activate-query-surface", activateQuerySurface); + window.removeEventListener(OBJECT_BROWSER_SEARCH_FOCUS_EVENT, focusRequestedObjectBrowserSearch); window.removeEventListener("dbx-mcp-status-changed", handleMcpStatusChanged); window.removeEventListener("dbx:ai-run-notify", handleAiRunNotify); document.removeEventListener("contextmenu", handleContextMenu); diff --git a/apps/desktop/src/components/objects/DatabaseBrowser.vue b/apps/desktop/src/components/objects/DatabaseBrowser.vue index d1d39fab40..777101ea80 100644 --- a/apps/desktop/src/components/objects/DatabaseBrowser.vue +++ b/apps/desktop/src/components/objects/DatabaseBrowser.vue @@ -1,5 +1,5 @@