@@ -99,7 +99,12 @@ const WorkflowContent = React.memo(() => {
9999 const { workflows, activeWorkflowId, isLoading, setActiveWorkflow, createWorkflow } =
100100 useWorkflowRegistry ( )
101101
102- const { blocks, edges, updateNodeDimensions } = useWorkflowStore ( )
102+ const {
103+ blocks,
104+ edges,
105+ updateNodeDimensions,
106+ updateBlockPosition : storeUpdateBlockPosition ,
107+ } = useWorkflowStore ( )
103108 // Use collaborative operations for real-time sync
104109 const currentWorkflow = useMemo ( ( ) => workflows [ workflowId ] , [ workflows , workflowId ] )
105110 const workspaceId = currentWorkflow ?. workspaceId
@@ -117,7 +122,7 @@ const WorkflowContent = React.memo(() => {
117122 collaborativeAddBlock : addBlock ,
118123 collaborativeAddEdge : addEdge ,
119124 collaborativeRemoveEdge : removeEdge ,
120- collaborativeUpdateBlockPosition : updateBlockPosition ,
125+ collaborativeUpdateBlockPosition,
121126 collaborativeUpdateParentId : updateParentId ,
122127 isConnected,
123128 currentWorkflowId,
@@ -186,12 +191,12 @@ const WorkflowContent = React.memo(() => {
186191 nodeId ,
187192 newParentId ,
188193 getNodes ,
189- updateBlockPosition ,
194+ collaborativeUpdateBlockPosition ,
190195 updateParentId ,
191196 ( ) => resizeLoopNodes ( getNodes , updateNodeDimensions , blocks )
192197 )
193198 } ,
194- [ getNodes , updateBlockPosition , updateParentId , updateNodeDimensions , blocks ]
199+ [ getNodes , collaborativeUpdateBlockPosition , updateParentId , updateNodeDimensions , blocks ]
195200 )
196201
197202 // Function to resize all loop nodes with improved hierarchy handling
@@ -256,13 +261,20 @@ const WorkflowContent = React.memo(() => {
256261 [ detectedOrientation ]
257262 )
258263
259- applyAutoLayoutSmooth ( blocks , edges , updateBlockPosition , fitView , resizeLoopNodesWrapper , {
260- ...orientationConfig ,
261- alignByLayer : true ,
262- animationDuration : 500 , // Smooth 500ms animation
263- isSidebarCollapsed,
264- handleOrientation : detectedOrientation , // Explicitly set the detected orientation
265- } )
264+ applyAutoLayoutSmooth (
265+ blocks ,
266+ edges ,
267+ collaborativeUpdateBlockPosition ,
268+ fitView ,
269+ resizeLoopNodesWrapper ,
270+ {
271+ ...orientationConfig ,
272+ alignByLayer : true ,
273+ animationDuration : 500 , // Smooth 500ms animation
274+ isSidebarCollapsed,
275+ handleOrientation : detectedOrientation , // Explicitly set the detected orientation
276+ }
277+ )
266278
267279 const orientationMessage =
268280 detectedOrientation === 'vertical'
@@ -273,7 +285,14 @@ const WorkflowContent = React.memo(() => {
273285 orientation : detectedOrientation ,
274286 blockCount : Object . keys ( blocks ) . length ,
275287 } )
276- } , [ blocks , edges , updateBlockPosition , fitView , isSidebarCollapsed , resizeLoopNodesWrapper ] )
288+ } , [
289+ blocks ,
290+ edges ,
291+ collaborativeUpdateBlockPosition ,
292+ fitView ,
293+ isSidebarCollapsed ,
294+ resizeLoopNodesWrapper ,
295+ ] )
277296
278297 const debouncedAutoLayout = useCallback ( ( ) => {
279298 const debounceTimer = setTimeout ( ( ) => {
@@ -841,7 +860,7 @@ const WorkflowContent = React.memo(() => {
841860 return
842861 }
843862
844- // Always call setActiveWorkflow when workflow ID changes to ensure proper state
863+ // Get current active workflow state
845864 const { activeWorkflowId } = useWorkflowRegistry . getState ( )
846865
847866 if ( activeWorkflowId !== currentId ) {
@@ -955,18 +974,20 @@ const WorkflowContent = React.memo(() => {
955974 return nodeArray
956975 } , [ blocks , activeBlockIds , pendingBlocks , isDebugModeEnabled , nestedSubflowErrors ] )
957976
958- // Update nodes
977+ // Update nodes - use store version to avoid collaborative feedback loops
959978 const onNodesChange = useCallback (
960979 ( changes : any ) => {
961980 changes . forEach ( ( change : any ) => {
962981 if ( change . type === 'position' && change . position ) {
963982 const node = nodes . find ( ( n ) => n . id === change . id )
964983 if ( ! node ) return
965- updateBlockPosition ( change . id , change . position )
984+ // Use store version to avoid collaborative feedback loop
985+ // React Flow position changes can be triggered by collaborative updates
986+ storeUpdateBlockPosition ( change . id , change . position )
966987 }
967988 } )
968989 } ,
969- [ nodes , updateBlockPosition ]
990+ [ nodes , storeUpdateBlockPosition ]
970991 )
971992
972993 // Effect to resize loops when nodes change (add/remove/position change)
@@ -1001,11 +1022,11 @@ const WorkflowContent = React.memo(() => {
10011022 const absolutePosition = getNodeAbsolutePositionWrapper ( id )
10021023
10031024 // Update the node to remove parent reference and use absolute position
1004- updateBlockPosition ( id , absolutePosition )
1025+ collaborativeUpdateBlockPosition ( id , absolutePosition )
10051026 updateParentId ( id , '' , 'parent' )
10061027 }
10071028 } )
1008- } , [ blocks , updateBlockPosition , updateParentId , getNodeAbsolutePositionWrapper ] )
1029+ } , [ blocks , collaborativeUpdateBlockPosition , updateParentId , getNodeAbsolutePositionWrapper ] )
10091030
10101031 // Validate nested subflows whenever blocks change
10111032 useEffect ( ( ) => {
@@ -1108,6 +1129,9 @@ const WorkflowContent = React.memo(() => {
11081129 // Store currently dragged node ID
11091130 setDraggedNodeId ( node . id )
11101131
1132+ // Emit collaborative position update during drag for smooth real-time movement
1133+ collaborativeUpdateBlockPosition ( node . id , node . position )
1134+
11111135 // Get the current parent ID of the node being dragged
11121136 const currentParentId = blocks [ node . id ] ?. data ?. parentId || null
11131137
@@ -1254,6 +1278,7 @@ const WorkflowContent = React.memo(() => {
12541278 getNodeHierarchyWrapper ,
12551279 getNodeAbsolutePositionWrapper ,
12561280 getNodeDepthWrapper ,
1281+ collaborativeUpdateBlockPosition ,
12571282 ]
12581283 )
12591284
@@ -1276,7 +1301,11 @@ const WorkflowContent = React.memo(() => {
12761301 } )
12771302 document . body . style . cursor = ''
12781303
1279- // Don't process if the node hasn't actually changed parent or is being moved within same parent
1304+ // Emit collaborative position update for the final position
1305+ // This ensures other users see the smooth final position
1306+ collaborativeUpdateBlockPosition ( node . id , node . position )
1307+
1308+ // Don't process parent changes if the node hasn't actually changed parent or is being moved within same parent
12801309 if ( potentialParentId === dragStartParentId ) return
12811310
12821311 // Check if this is a starter block - starter blocks should never be in containers
@@ -1319,7 +1348,14 @@ const WorkflowContent = React.memo(() => {
13191348 setDraggedNodeId ( null )
13201349 setPotentialParentId ( null )
13211350 } ,
1322- [ getNodes , dragStartParentId , potentialParentId , updateNodeParent , getNodeHierarchyWrapper ]
1351+ [
1352+ getNodes ,
1353+ dragStartParentId ,
1354+ potentialParentId ,
1355+ updateNodeParent ,
1356+ getNodeHierarchyWrapper ,
1357+ collaborativeUpdateBlockPosition ,
1358+ ]
13231359 )
13241360
13251361 // Update onPaneClick to only handle edge selection
0 commit comments