mirror of
https://github.com/Egonex-AI/Understand-Anything.git
synced 2026-06-22 10:58:03 +08:00
chore(dashboard): address Task 12 + 13 review concerns
Task 13 onMove auto-expand: - Skip when event === null so React Flow's programmatic moves (fitView at layer entry, zoomTo from search) don't cascade-expand every container the moment the layer paints. - Track previous zoom; only fire when zoom actually increased. Pans and zoom-outs are now no-ops, so a user who manually collapses a container while zoomed in can keep it that way. Task 12 inflated edge ids: - Append index suffix so parallel edges with identical (source, target, type) — which the schema doesn't disallow — don't collide in React Flow's edge map. Other Task 12 concerns (per-container Stage 2 cancellation, O(K·E) edge bucket pre-pass, extent:"parent" clipping pre-Task-15) are known trade-offs documented in the plan; deferring to follow-ups. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1064,16 +1064,20 @@ function useLayerDetailGraph() {
|
||||
const ftc = topo.nodeToContainer.get(fe.target);
|
||||
return fsc === e.source && ftc === e.target;
|
||||
});
|
||||
for (const m of matching) {
|
||||
// Index suffix guards against parallel edges with identical
|
||||
// (source, target, type) — schema doesn't enforce uniqueness on
|
||||
// that triple, so two edges from the same agent run could otherwise
|
||||
// collide in React Flow's edge map.
|
||||
matching.forEach((m, idx) => {
|
||||
out.push({
|
||||
id: `inflated-${m.source}-${m.target}-${m.type}`,
|
||||
id: `inflated-${m.source}-${m.target}-${m.type}-${idx}`,
|
||||
source: m.source,
|
||||
target: m.target,
|
||||
label: m.type,
|
||||
style: { stroke: "rgba(212,165,116,0.5)", strokeWidth: 1.5 },
|
||||
labelStyle: { fill: "#a39787", fontSize: 10 },
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
return out;
|
||||
}, [topo.edges, topo.filteredEdges, topo.nodeToContainer, expandedContainers]);
|
||||
@@ -1185,20 +1189,34 @@ function GraphViewInner() {
|
||||
// user collapses manually). The handler reads expandedContainers via
|
||||
// getState() inside the timeout to avoid re-creating on every expand.
|
||||
const zoomTimeoutRef = useRef<number | null>(null);
|
||||
const onMove = useCallback(() => {
|
||||
if (!containerIds || containerIds.length === 0) return;
|
||||
if (zoomTimeoutRef.current !== null) {
|
||||
window.clearTimeout(zoomTimeoutRef.current);
|
||||
}
|
||||
zoomTimeoutRef.current = window.setTimeout(() => {
|
||||
const vp = getViewport();
|
||||
if (vp.zoom <= 1.0) return;
|
||||
const expanded = useDashboardStore.getState().expandedContainers;
|
||||
for (const cid of containerIds) {
|
||||
if (!expanded.has(cid)) expandContainer(cid);
|
||||
// Only auto-expand on user-driven zoom-INs. Skip programmatic moves
|
||||
// (e.g. fitView at layer entry, which would otherwise cascade-expand
|
||||
// every container the moment the layer paints) and skip pans/zoom-outs
|
||||
// (so a user who manually collapses a container at zoom > 1 can pan
|
||||
// around without seeing it pop back open).
|
||||
const prevZoomRef = useRef<number | null>(null);
|
||||
const onMove = useCallback(
|
||||
(event: MouseEvent | TouchEvent | null) => {
|
||||
if (event === null) return; // programmatic — skip
|
||||
if (!containerIds || containerIds.length === 0) return;
|
||||
if (zoomTimeoutRef.current !== null) {
|
||||
window.clearTimeout(zoomTimeoutRef.current);
|
||||
}
|
||||
}, 200);
|
||||
}, [containerIds, getViewport, expandContainer]);
|
||||
zoomTimeoutRef.current = window.setTimeout(() => {
|
||||
const vp = getViewport();
|
||||
const prev = prevZoomRef.current;
|
||||
prevZoomRef.current = vp.zoom;
|
||||
if (vp.zoom <= 1.0) return;
|
||||
// Only fire when zoom actually increased — pan and zoom-out are no-ops.
|
||||
if (prev !== null && vp.zoom <= prev) return;
|
||||
const expanded = useDashboardStore.getState().expandedContainers;
|
||||
for (const cid of containerIds) {
|
||||
if (!expanded.has(cid)) expandContainer(cid);
|
||||
}
|
||||
}, 200);
|
||||
},
|
||||
[containerIds, getViewport, expandContainer],
|
||||
);
|
||||
|
||||
// Clear any pending zoom timer on unmount or when handler identity changes.
|
||||
useEffect(() => {
|
||||
|
||||
Reference in New Issue
Block a user