From c1bc4bfac184eed8576d0c1b1b23ace3ac31836d Mon Sep 17 00:00:00 2001 From: Xingkai98 Date: Sat, 9 May 2026 01:36:46 +0800 Subject: [PATCH 1/2] feat(dashboard): add file/class dual-view toggle to reduce graph clutter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add detailLevel state ("file" | "class") to separate architecture-level file dependencies from code-structure class views. File view shows only file nodes and file→file edges (imports/depends_on), eliminating ~85% of nodes/edges that previously caused severe zoom/pan lag. Class view adds class nodes via contains edges with an optional function toggle. Co-Authored-By: Claude Opus 4.6 --- .../packages/dashboard/src/App.tsx | 50 +++++++++++++++++++ .../dashboard/src/components/GraphView.tsx | 22 ++++++-- .../packages/dashboard/src/store.ts | 29 +++++++++++ 3 files changed, 98 insertions(+), 3 deletions(-) diff --git a/understand-anything-plugin/packages/dashboard/src/App.tsx b/understand-anything-plugin/packages/dashboard/src/App.tsx index 8abc0e8..9aa7edd 100644 --- a/understand-anything-plugin/packages/dashboard/src/App.tsx +++ b/understand-anything-plugin/packages/dashboard/src/App.tsx @@ -109,6 +109,10 @@ function Dashboard({ accessToken }: { accessToken: string }) { const togglePathFinder = useDashboardStore((s) => s.togglePathFinder); const nodeTypeFilters = useDashboardStore((s) => s.nodeTypeFilters); const toggleNodeTypeFilter = useDashboardStore((s) => s.toggleNodeTypeFilter); + const detailLevel = useDashboardStore((s) => s.detailLevel); + const setDetailLevel = useDashboardStore((s) => s.setDetailLevel); + const showFunctionsInClassView = useDashboardStore((s) => s.showFunctionsInClassView); + const toggleShowFunctionsInClassView = useDashboardStore((s) => s.toggleShowFunctionsInClassView); const [loadError, setLoadError] = useState(null); const [graphIssues, setGraphIssues] = useState([]); const [showKeyboardHelp, setShowKeyboardHelp] = useState(false); @@ -443,6 +447,52 @@ function Dashboard({ accessToken }: { accessToken: string }) {
+ {/* Detail level: file view (architecture) / class view (code structure) */} + {!isKnowledgeGraph && ( + <> +
+
+ + +
+ {detailLevel === "class" && ( + + )} + + )}
{(isKnowledgeGraph ? [ { key: "knowledge" as const, label: "All", color: "var(--color-node-article)" }, diff --git a/understand-anything-plugin/packages/dashboard/src/components/GraphView.tsx b/understand-anything-plugin/packages/dashboard/src/components/GraphView.tsx index 891d997..2c438c6 100644 --- a/understand-anything-plugin/packages/dashboard/src/components/GraphView.tsx +++ b/understand-anything-plugin/packages/dashboard/src/components/GraphView.tsx @@ -366,6 +366,7 @@ function useLayerDetailTopology(): LayerDetailTopology & { layoutStatus: "computing" | "ready"; } { const graph = useDashboardStore((s) => s.graph); + const nodesById = useDashboardStore((s) => s.nodesById); const activeLayerId = useDashboardStore((s) => s.activeLayerId); const selectNode = useDashboardStore((s) => s.selectNode); const persona = useDashboardStore((s) => s.persona); @@ -375,6 +376,8 @@ function useLayerDetailTopology(): LayerDetailTopology & { const focusNodeId = useDashboardStore((s) => s.focusNodeId); const nodeTypeFilters = useDashboardStore((s) => s.nodeTypeFilters); const drillIntoLayer = useDashboardStore((s) => s.drillIntoLayer); + const detailLevel = useDashboardStore((s) => s.detailLevel); + const showFunctionsInClassView = useDashboardStore((s) => s.showFunctionsInClassView); const handleNodeSelect = useCallback( (nodeId: string) => { @@ -404,10 +407,20 @@ function useLayerDetailTopology(): LayerDetailTopology & { // Expand layer membership to include sub-file nodes (function/class) // whose parent file is in this layer. Joined via "contains" edges. + // File view: file nodes only (architecture-level dependencies). + // Class view: file nodes + class nodes, functions only when toggle is on. const expandedLayerNodeIds = new Set(layerNodeIds); - for (const edge of graph.edges) { - if (edge.type === "contains" && layerNodeIds.has(edge.source)) { - expandedLayerNodeIds.add(edge.target); + if (detailLevel !== "file") { + for (const edge of graph.edges) { + if (edge.type === "contains" && layerNodeIds.has(edge.source)) { + const child = nodesById.get(edge.target); + if (!child) continue; + if (child.type === "class") { + expandedLayerNodeIds.add(edge.target); + } else if (child.type === "function" && showFunctionsInClassView) { + expandedLayerNodeIds.add(edge.target); + } + } } } @@ -625,6 +638,7 @@ function useLayerDetailTopology(): LayerDetailTopology & { }; }, [ graph, + nodesById, activeLayerId, persona, diffMode, @@ -633,6 +647,8 @@ function useLayerDetailTopology(): LayerDetailTopology & { focusNodeId, nodeTypeFilters, drillIntoLayer, + detailLevel, + showFunctionsInClassView, handleNodeSelect, handleContainerToggle, ]); diff --git a/understand-anything-plugin/packages/dashboard/src/store.ts b/understand-anything-plugin/packages/dashboard/src/store.ts index ea398a1..aff4339 100644 --- a/understand-anything-plugin/packages/dashboard/src/store.ts +++ b/understand-anything-plugin/packages/dashboard/src/store.ts @@ -15,6 +15,7 @@ export type NodeType = "file" | "function" | "class" | "module" | "concept" | "c export type Complexity = "simple" | "moderate" | "complex"; export type EdgeCategory = "structural" | "behavioral" | "data-flow" | "dependencies" | "semantic" | "infrastructure" | "domain" | "knowledge"; export type ViewMode = "structural" | "domain" | "knowledge"; +export type DetailLevel = "file" | "class"; export interface FilterState { nodeTypes: Set; @@ -146,6 +147,13 @@ interface DashboardStore { nodeTypeFilters: Record; toggleNodeTypeFilter: (category: NodeCategory) => void; + // Detail level: "file" shows only file nodes (architecture view), + // "class" shows files + class nodes (code structure view) with optional function expansion. + detailLevel: DetailLevel; + setDetailLevel: (level: DetailLevel) => void; + showFunctionsInClassView: boolean; + toggleShowFunctionsInClassView: () => void; + setGraph: (graph: KnowledgeGraph) => void; selectNode: (nodeId: string | null) => void; navigateToNode: (nodeId: string) => void; @@ -331,6 +339,27 @@ export const useDashboardStore = create()((set, get) => ({ pendingFocusContainer: null, })), + detailLevel: "file", + setDetailLevel: (level) => + set({ + detailLevel: level, + // Detail level changes which nodes are visible; cached positions stale. + containerLayoutCache: new Map(), + containerSizeMemory: new Map(), + expandedContainers: new Set(), + pendingFocusContainer: null, + }), + + showFunctionsInClassView: false, + toggleShowFunctionsInClassView: () => + set((state) => ({ + showFunctionsInClassView: !state.showFunctionsInClassView, + containerLayoutCache: new Map(), + containerSizeMemory: new Map(), + expandedContainers: new Set(), + pendingFocusContainer: null, + })), + setGraph: (graph) => { const searchEngine = new SearchEngine(graph.nodes); const query = get().searchQuery; From e29f46157494f06b67d15cf43d83effa47d21650 Mon Sep 17 00:00:00 2001 From: Xingkai98 Date: Sun, 10 May 2026 16:24:26 +0800 Subject: [PATCH 2/2] fix(dashboard): reset fn toggle on view switch; hide detail toolbar in domain view - Issue 1: setDetailLevel now resets showFunctionsInClassView so the fn toggle doesn't resurrect when re-entering class view after a file-view round-trip. - Issue 2: detail-level toolbar (Files/+Classes/fn) now gated on viewMode !== "domain" so it doesn't render in domain view where it has no effect. --- understand-anything-plugin/packages/dashboard/src/App.tsx | 2 +- understand-anything-plugin/packages/dashboard/src/store.ts | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/understand-anything-plugin/packages/dashboard/src/App.tsx b/understand-anything-plugin/packages/dashboard/src/App.tsx index 9aa7edd..4aed9bf 100644 --- a/understand-anything-plugin/packages/dashboard/src/App.tsx +++ b/understand-anything-plugin/packages/dashboard/src/App.tsx @@ -448,7 +448,7 @@ function Dashboard({ accessToken }: { accessToken: string }) {
{/* Detail level: file view (architecture) / class view (code structure) */} - {!isKnowledgeGraph && ( + {!isKnowledgeGraph && viewMode !== "domain" && ( <>
diff --git a/understand-anything-plugin/packages/dashboard/src/store.ts b/understand-anything-plugin/packages/dashboard/src/store.ts index aff4339..b3b2a96 100644 --- a/understand-anything-plugin/packages/dashboard/src/store.ts +++ b/understand-anything-plugin/packages/dashboard/src/store.ts @@ -344,6 +344,8 @@ export const useDashboardStore = create()((set, get) => ({ set({ detailLevel: level, // Detail level changes which nodes are visible; cached positions stale. + // Reset fn toggle so it doesn't resurrect when re-entering class view. + showFunctionsInClassView: false, containerLayoutCache: new Map(), containerSizeMemory: new Map(), expandedContainers: new Set(),