Skip to content

Commit 1bc476f

Browse files
authored
fix(copilot): panning on workflow (#3057)
1 parent 9e40342 commit 1bc476f

File tree

1 file changed

+32
-39
lines changed
  • apps/sim/app/workspace/[workspaceId]/w/[workflowId]

1 file changed

+32
-39
lines changed

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/workflow.tsx

Lines changed: 32 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1800,37 +1800,32 @@ const WorkflowContent = React.memo(() => {
18001800
)
18011801
}, [screenToFlowPosition, handleToolbarDrop])
18021802

1803-
/**
1804-
* Focus canvas on changed blocks when diff appears.
1805-
*/
1803+
/** Tracks blocks to pan to after diff updates. */
18061804
const pendingZoomBlockIdsRef = useRef<Set<string> | null>(null)
1807-
const prevDiffReadyRef = useRef(false)
1805+
const seenDiffBlocksRef = useRef<Set<string>>(new Set())
18081806

1809-
// Phase 1: When diff becomes ready, record which blocks we want to zoom to
1810-
// Phase 2 effect is located after displayNodes is defined (search for "Phase 2")
1807+
/** Queues newly changed blocks for viewport panning. */
18111808
useEffect(() => {
1812-
if (isDiffReady && !prevDiffReadyRef.current && diffAnalysis) {
1813-
// Diff just became ready - record blocks to zoom to
1814-
const changedBlockIds = [
1815-
...(diffAnalysis.new_blocks || []),
1816-
...(diffAnalysis.edited_blocks || []),
1817-
]
1818-
1819-
if (changedBlockIds.length > 0) {
1820-
pendingZoomBlockIdsRef.current = new Set(changedBlockIds)
1821-
} else {
1822-
// No specific blocks to focus on, fit all after a frame
1823-
pendingZoomBlockIdsRef.current = null
1824-
requestAnimationFrame(() => {
1825-
fitViewToBounds({ padding: 0.1, duration: 600 })
1826-
})
1827-
}
1828-
} else if (!isDiffReady && prevDiffReadyRef.current) {
1829-
// Diff was cleared (accepted/rejected) - cancel any pending zoom
1809+
if (!isDiffReady || !diffAnalysis) {
18301810
pendingZoomBlockIdsRef.current = null
1811+
seenDiffBlocksRef.current.clear()
1812+
return
1813+
}
1814+
1815+
const newBlocks = new Set<string>()
1816+
const allBlocks = [...(diffAnalysis.new_blocks || []), ...(diffAnalysis.edited_blocks || [])]
1817+
1818+
for (const id of allBlocks) {
1819+
if (!seenDiffBlocksRef.current.has(id)) {
1820+
newBlocks.add(id)
1821+
}
1822+
seenDiffBlocksRef.current.add(id)
18311823
}
1832-
prevDiffReadyRef.current = isDiffReady
1833-
}, [isDiffReady, diffAnalysis, fitViewToBounds])
1824+
1825+
if (newBlocks.size > 0) {
1826+
pendingZoomBlockIdsRef.current = newBlocks
1827+
}
1828+
}, [isDiffReady, diffAnalysis])
18341829

18351830
/** Displays trigger warning notifications. */
18361831
useEffect(() => {
@@ -2238,18 +2233,12 @@ const WorkflowContent = React.memo(() => {
22382233
})
22392234
}, [derivedNodes, blocks, pendingSelection, clearPendingSelection])
22402235

2241-
// Phase 2: When displayNodes updates, check if pending zoom blocks are ready
2242-
// (Phase 1 is located earlier in the file where pendingZoomBlockIdsRef is defined)
2236+
/** Pans viewport to pending blocks once they have valid dimensions. */
22432237
useEffect(() => {
22442238
const pendingBlockIds = pendingZoomBlockIdsRef.current
2245-
if (!pendingBlockIds || pendingBlockIds.size === 0) {
2246-
return
2247-
}
2239+
if (!pendingBlockIds || pendingBlockIds.size === 0) return
22482240

2249-
// Find the nodes we're waiting for
22502241
const pendingNodes = displayNodes.filter((node) => pendingBlockIds.has(node.id))
2251-
2252-
// Check if all expected nodes are present with valid dimensions
22532242
const allNodesReady =
22542243
pendingNodes.length === pendingBlockIds.size &&
22552244
pendingNodes.every(
@@ -2261,24 +2250,28 @@ const WorkflowContent = React.memo(() => {
22612250
)
22622251

22632252
if (allNodesReady) {
2264-
logger.info('Diff ready - focusing on changed blocks', {
2253+
logger.info('Focusing on changed blocks', {
22652254
changedBlockIds: Array.from(pendingBlockIds),
22662255
foundNodes: pendingNodes.length,
22672256
})
2268-
// Clear pending state before zooming to prevent re-triggers
22692257
pendingZoomBlockIdsRef.current = null
2270-
// Use requestAnimationFrame to ensure React has finished rendering
2258+
2259+
const nodesWithAbsolutePositions = pendingNodes.map((node) => ({
2260+
...node,
2261+
position: getNodeAbsolutePosition(node.id),
2262+
}))
2263+
22712264
requestAnimationFrame(() => {
22722265
fitViewToBounds({
2273-
nodes: pendingNodes,
2266+
nodes: nodesWithAbsolutePositions,
22742267
duration: 600,
22752268
padding: 0.1,
22762269
minZoom: 0.5,
22772270
maxZoom: 1.0,
22782271
})
22792272
})
22802273
}
2281-
}, [displayNodes, fitViewToBounds])
2274+
}, [displayNodes, fitViewToBounds, getNodeAbsolutePosition])
22822275

22832276
/** Handles ActionBar remove-from-subflow events. */
22842277
useEffect(() => {

0 commit comments

Comments
 (0)