fix(sidebar): restore tree node collapsing
This commit is contained in:
parent
f82749163d
commit
24d7dc48ad
|
|
@ -40,6 +40,7 @@ import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, D
|
|||
import { codeMirrorSqlDialect } from "@/lib/database/jdbcDialect";
|
||||
import { sqlFormatDialectForDbType } from "@/lib/sql/sqlFormatter";
|
||||
import { createSidebarActionTarget, findSidebarActionTarget, matchesSidebarActionTarget, type SidebarActionTarget } from "@/lib/sidebar/sidebarActionTarget";
|
||||
import { syncSidebarTreeNodeExpansion } from "@/lib/sidebar/sidebarTreeExpansion";
|
||||
import type { SidebarDangerDialogRequest } from "@/lib/sidebar/sidebarDangerDialog";
|
||||
import { resetSidebarTreeDialogState } from "./sidebarTreeDialogState";
|
||||
import { SidebarDangerConfirmDialog, SidebarDdlViewDialog, SidebarObjectSourceDialog, SidebarProcedureExecutionDialog, SidebarVisibleDatabasesDialog, SidebarVisibleSchemasDialog } from "./sidebarAsyncDialogs";
|
||||
|
|
@ -387,7 +388,7 @@ function filterLocallySearchedTables(nodes: TreeNode[]): TreeNode[] {
|
|||
children,
|
||||
)
|
||||
: children.filter((child) => localTableSearchChildTypes.has(child.type) && !!matchSidebarLabel(child.label.toLowerCase(), query.toLowerCase()));
|
||||
return { ...node, children: matchingChildren, isExpanded: true };
|
||||
return { ...node, children: matchingChildren };
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -670,10 +671,7 @@ watch(flatNodes, (nodes) => {
|
|||
}
|
||||
}
|
||||
stickyScrollTop.value = 0;
|
||||
void nextTick(() => {
|
||||
treeScrollerRef.value?.forceUpdate(true);
|
||||
scheduleSidebarScrollMetricsUpdate();
|
||||
});
|
||||
void nextTick(scheduleSidebarScrollMetricsUpdate);
|
||||
});
|
||||
|
||||
const sidebarTreeOverflowClass = computed(() => (settingsStore.editorSettings.sidebarAllowHorizontalScroll ? "overflow-x-auto sidebar-tree-horizontal-scroll" : "overflow-x-hidden"));
|
||||
|
|
@ -1186,6 +1184,11 @@ function onSearchToggle(node: TreeNode) {
|
|||
searchCollapsedIds.value = next;
|
||||
}
|
||||
|
||||
function onNodeToggled(node: TreeNode) {
|
||||
if (isTreeSearchFiltering.value) return;
|
||||
syncSidebarTreeNodeExpansion(store.treeNodes, node);
|
||||
}
|
||||
|
||||
function openSidebarContextMenu(event: MouseEvent, node: TreeNode, openContextMenu: (event: MouseEvent, itemsOverride?: ContextMenuItem[]) => void) {
|
||||
const items = sidebarTreeRuntime.buildContextMenu(node);
|
||||
sidebarContextMenuTarget.value = createSidebarActionTarget(node);
|
||||
|
|
@ -1666,6 +1669,7 @@ defineExpose({ focusSearch, createNewGroup, collapseAllTreeNodes });
|
|||
:node="sidebarTreeRuntimeInitialNode"
|
||||
:depth="0"
|
||||
@search-toggle="onSearchToggle"
|
||||
@node-toggled="onNodeToggled"
|
||||
@open-ddl="openSidebarDdl"
|
||||
@open-object-source="openSidebarObjectSource"
|
||||
@open-procedure="openSidebarProcedure"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
import type { TreeNode } from "@/types/database";
|
||||
import { findSidebarActionTarget } from "@/lib/sidebar/sidebarActionTarget";
|
||||
|
||||
export function syncSidebarTreeNodeExpansion(nodes: readonly TreeNode[], renderedNode: TreeNode): boolean {
|
||||
const liveNode = findSidebarActionTarget(nodes, renderedNode);
|
||||
if (!liveNode || liveNode === renderedNode || liveNode.isExpanded === renderedNode.isExpanded) return false;
|
||||
liveNode.isExpanded = renderedNode.isExpanded;
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1,6 +1,8 @@
|
|||
import { strict as assert } from "node:assert";
|
||||
import { readFileSync } from "node:fs";
|
||||
import { test } from "vitest";
|
||||
import { syncSidebarTreeNodeExpansion } from "../../apps/desktop/src/lib/sidebar/sidebarTreeExpansion.ts";
|
||||
import type { TreeNode } from "../../apps/desktop/src/types/database.ts";
|
||||
|
||||
const treeItem = readFileSync("apps/desktop/src/components/sidebar/TreeItem.vue", "utf8");
|
||||
const runtimeHost = readFileSync("apps/desktop/src/components/sidebar/SidebarTreeRuntimeHost.vue", "utf8");
|
||||
|
|
@ -24,6 +26,39 @@ test("complex tree changes retain the full rebuild fallback", () => {
|
|||
assert.match(connectionTree, /const flatNodes = computed<FlatTreeNode\[]>/);
|
||||
assert.match(connectionTree, /flattenTree\(filteredNodes\.value\)/);
|
||||
assert.match(connectionTree, /watch\(flatNodes,/);
|
||||
assert.doesNotMatch(connectionTree, /treeScrollerRef\.value\?\.(?:forceUpdate|updateVisibleItems)/);
|
||||
assert.match(connectionTree, /@node-toggled="onNodeToggled"/);
|
||||
});
|
||||
|
||||
test("tree toggles synchronize filtered node clones with the live sidebar tree", () => {
|
||||
const expandedConnection: TreeNode = {
|
||||
id: "connection-1",
|
||||
label: "Connection 1",
|
||||
type: "connection",
|
||||
connectionId: "connection-1",
|
||||
isExpanded: true,
|
||||
};
|
||||
const collapsedClone: TreeNode = { ...expandedConnection, isExpanded: false };
|
||||
const collapsedConnection: TreeNode = {
|
||||
id: "connection-2",
|
||||
label: "Connection 2",
|
||||
type: "connection",
|
||||
connectionId: "connection-2",
|
||||
isExpanded: false,
|
||||
};
|
||||
const expandedClone: TreeNode = { ...collapsedConnection, isExpanded: true };
|
||||
|
||||
assert.equal(syncSidebarTreeNodeExpansion([expandedConnection], collapsedClone), true);
|
||||
assert.equal(expandedConnection.isExpanded, false);
|
||||
assert.equal(syncSidebarTreeNodeExpansion([collapsedConnection], expandedClone), true);
|
||||
assert.equal(collapsedConnection.isExpanded, true);
|
||||
assert.equal(syncSidebarTreeNodeExpansion([expandedConnection], expandedConnection), false);
|
||||
});
|
||||
|
||||
test("local table search preserves live expansion state", () => {
|
||||
assert.match(connectionTree, /return \{ \.\.\.node, children: matchingChildren \};/);
|
||||
assert.doesNotMatch(connectionTree, /children: matchingChildren,\s*isExpanded:\s*true/);
|
||||
assert.match(connectionTree, /function onNodeToggled\(node: TreeNode\) \{\s*if \(isTreeSearchFiltering\.value\) return;\s*syncSidebarTreeNodeExpansion/);
|
||||
});
|
||||
|
||||
test("tree rebuilds keep a context menu only while its target row remains visible", () => {
|
||||
|
|
|
|||
Loading…
Reference in New Issue