fix(dashboard): clear pendingFocusContainer on layer/state resets

Codex review on PR #114 flagged that `layerResetIfChanged` cleared
`containerLayoutCache` and `expandedContainers` but left
`pendingFocusContainer` intact. Because container ids collide across
layers (the very reason the cache reset exists), a manual expand in
layer A that hadn't yet hit its 1.2s clear timer could leak its id
into layer B's namespace and recenter the viewport on an unrelated
container right after navigation.

The same hazard applies to every other reset path that drops the
container caches. Add `pendingFocusContainer: null` to all of them:

  - layerResetIfChanged (tour cross-layer reset, the originally flagged
    site)
  - drillIntoLayer
  - navigateToOverview
  - setFocusNode
  - setPersona
  - setGraph
  - toggleNodeTypeFilter
  - clearContainerLayouts

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Lum1104
2026-05-04 19:21:06 +08:00
co-authored by Claude Opus 4.7
parent 4b86c696a5
commit f58f0edd62
@@ -271,6 +271,10 @@ function layerResetIfChanged(
containerLayoutCache: new Map(),
containerSizeMemory: new Map(),
expandedContainers: new Set(),
// Drop any pending focus too — its id was scoped to the previous
// layer and would otherwise re-collide with a same-id container in
// the new layer for the duration of the 1.2s timer.
pendingFocusContainer: null,
};
}
@@ -324,6 +328,7 @@ export const useDashboardStore = create<DashboardStore>()((set, get) => ({
containerLayoutCache: new Map(),
containerSizeMemory: new Map(),
expandedContainers: new Set(),
pendingFocusContainer: null,
})),
setGraph: (graph) => {
@@ -350,6 +355,7 @@ export const useDashboardStore = create<DashboardStore>()((set, get) => ({
activeDomainId: keepDomainView ? activeDomainId : null,
containerLayoutCache: new Map(),
expandedContainers: new Set(),
pendingFocusContainer: null,
containerSizeMemory: new Map(),
stage1Tick: 0,
layoutIssues: [],
@@ -449,6 +455,7 @@ export const useDashboardStore = create<DashboardStore>()((set, get) => ({
containerLayoutCache: new Map(),
containerSizeMemory: new Map(),
expandedContainers: new Set(),
pendingFocusContainer: null,
}),
navigateToOverview: () =>
@@ -463,6 +470,7 @@ export const useDashboardStore = create<DashboardStore>()((set, get) => ({
containerLayoutCache: new Map(),
containerSizeMemory: new Map(),
expandedContainers: new Set(),
pendingFocusContainer: null,
}),
setFocusNode: (nodeId) =>
@@ -475,6 +483,7 @@ export const useDashboardStore = create<DashboardStore>()((set, get) => ({
containerLayoutCache: new Map(),
containerSizeMemory: new Map(),
expandedContainers: new Set(),
pendingFocusContainer: null,
}),
setSearchMode: (mode) => set({ searchMode: mode }),
setSearchQuery: (query) => {
@@ -498,6 +507,7 @@ export const useDashboardStore = create<DashboardStore>()((set, get) => ({
containerLayoutCache: new Map(),
containerSizeMemory: new Map(),
expandedContainers: new Set(),
pendingFocusContainer: null,
}),
openCodeViewer: (nodeId) =>
@@ -718,7 +728,7 @@ export const useDashboardStore = create<DashboardStore>()((set, get) => ({
return { containerLayoutCache: next, containerSizeMemory: sizeNext };
}),
clearContainerLayouts: () =>
set({ containerLayoutCache: new Map(), expandedContainers: new Set() }),
set({ containerLayoutCache: new Map(), expandedContainers: new Set(), pendingFocusContainer: null }),
containerSizeMemory: new Map(),