From c573c249ed3ec42c70767a6e6e939622bf39c8f3 Mon Sep 17 00:00:00 2001 From: Melody Ruch <396921921@qq.com> Date: Sat, 15 Aug 2026 18:56:58 +0800 Subject: [PATCH] fix(sidebar): show loading while global search is in flight --- .../src/components/sidebar/ConnectionTree.vue | 30 ++++++++++--- .../lib/metadata/metadataLoadCoordinator.ts | 5 +++ .../sidebarSearchLoadingTracker.spec.ts | 43 +++++++++++++++++++ .../sidebar/sidebarSearchLoadingTracker.ts | 34 +++++++++++++++ .../connectionStore.metadataLoading.spec.ts | 10 ++++- apps/desktop/src/stores/connectionStore.ts | 9 +++- 6 files changed, 123 insertions(+), 8 deletions(-) create mode 100644 apps/desktop/src/lib/sidebar/__tests__/sidebarSearchLoadingTracker.spec.ts create mode 100644 apps/desktop/src/lib/sidebar/sidebarSearchLoadingTracker.ts diff --git a/apps/desktop/src/components/sidebar/ConnectionTree.vue b/apps/desktop/src/components/sidebar/ConnectionTree.vue index a665ea1aee..7cd41714e2 100644 --- a/apps/desktop/src/components/sidebar/ConnectionTree.vue +++ b/apps/desktop/src/components/sidebar/ConnectionTree.vue @@ -22,6 +22,7 @@ import { import { createSidebarLabelMatcher, matchSidebarLabel } from "@/lib/sidebar/sidebarSearch"; import { collectSidebarRegexIndexScopes, resolveSidebarRemoteSearchQuery, resolveSidebarSearchDispatchMode } from "@/lib/sidebar/sidebarRegexSearchIndex"; import { createSidebarSearchExpansionState } from "@/lib/sidebar/sidebarSearchExpansionState"; +import { createSidebarSearchLoadingTracker } from "@/lib/sidebar/sidebarSearchLoadingTracker"; import { buildTableTreeNodes } from "@/lib/table/tableTree"; import { isCancelSearchShortcut, isCopySidebarSelectionShortcut, isEditSidebarConnectionShortcut, isPasteSidebarSelectionShortcut, isViewTableDdlShortcut } from "@/lib/editor/keyboardShortcuts"; import { sidebarNodeSupportsDdlView } from "@/lib/sidebar/sidebarTreeDdlShortcut"; @@ -78,6 +79,8 @@ const { toast } = useToast(); const searchQuery = ref(""); const deferredSearchQuery = ref(""); const regexMode = ref(false); +const sidebarSearchLoadingTracker = createSidebarSearchLoadingTracker(); +const isSidebarSearchLoading = ref(false); const showConnectedConnectionsOnly = ref(false); const isDisconnectingAllActiveConnections = ref(false); const searchInputRef = ref(); @@ -262,14 +265,20 @@ watch([deferredSearchQuery, regexMode], ([newQuery, isRegexMode], [oldQuery, was // Regex search is a read-only projection over live nodes and the local // table index. It must never trigger ensureConnected/listTables. const restoreTasks = restoreTrackedSearchTargets(); - void Promise.all([loadRegexTableSearchIndexes(), ...restoreTasks]) + const searchGeneration = sidebarSearchLoadingTracker.begin(); + isSidebarSearchLoading.value = true; + void Promise.allSettled([loadRegexTableSearchIndexes(), ...restoreTasks]) .then(() => { if (restoreTasks.length > 0) refreshActiveSidebarTableSearches(); }) - .catch(() => {}); + .finally(() => { + if (sidebarSearchLoadingTracker.end(searchGeneration)) isSidebarSearchLoading.value = false; + }); return; } if (dispatchMode === "none") { + sidebarSearchLoadingTracker.cancel(); + isSidebarSearchLoading.value = false; const restoreTasks = restoreTrackedSearchTargets(); if (restoreTasks.length > 0) { void Promise.all(restoreTasks) @@ -286,11 +295,21 @@ watch([deferredSearchQuery, regexMode], ([newQuery, isRegexMode], [oldQuery, was if (!newQuery && oldQuery) { searchExpansionState.clear(); } - Promise.all(tasks) + let searchGeneration = -1; + if (newQuery && tasks.length > 0) { + searchGeneration = sidebarSearchLoadingTracker.begin(); + isSidebarSearchLoading.value = true; + } else { + sidebarSearchLoadingTracker.cancel(); + isSidebarSearchLoading.value = false; + } + void Promise.allSettled(tasks) .then(() => { if (!newQuery && oldQuery) refreshActiveSidebarTableSearches(); }) - .catch(() => {}); + .finally(() => { + if (searchGeneration >= 0 && sidebarSearchLoadingTracker.end(searchGeneration)) isSidebarSearchLoading.value = false; + }); }); const searchableObjectGroupTypes = new Set(["group-tables", "group-dolt-system-tables", "group-views", "group-materialized-views", "group-procedures", "group-functions", "group-triggers", "group-sequences", "group-synonyms", "group-packages", "group-types"]); @@ -2023,7 +2042,8 @@ defineExpose({ focusSearch, createNewGroup, collapseAllTreeNodes });