diff --git a/web/app/components/workflow-app/index.tsx b/web/app/components/workflow-app/index.tsx index 6179d818a4..e6fdf0ddc6 100644 --- a/web/app/components/workflow-app/index.tsx +++ b/web/app/components/workflow-app/index.tsx @@ -10,7 +10,6 @@ import { useStore as useAppStore } from '@/app/components/app/store' import { FeaturesProvider } from '@/app/components/base/features' import Loading from '@/app/components/base/loading' import WorkflowWithDefaultContext from '@/app/components/workflow' -import { collaborationManager } from '@/app/components/workflow/collaboration/core/collaboration-manager' import { WorkflowContextProvider, } from '@/app/components/workflow/context' @@ -81,7 +80,6 @@ const WorkflowAppWithAdditionalContext = () => { const nodesData = useMemo(() => { if (data) { const processedNodes = initialNodes(data.graph.nodes, data.graph.edges) - collaborationManager.setNodes([], processedNodes) return processedNodes } return [] @@ -90,7 +88,6 @@ const WorkflowAppWithAdditionalContext = () => { const edgesData = useMemo(() => { if (data) { const processedEdges = initialEdges(data.graph.edges, data.graph.nodes) - collaborationManager.setEdges([], processedEdges) return processedEdges } return [] diff --git a/web/app/components/workflow/collaboration/core/collaboration-manager.ts b/web/app/components/workflow/collaboration/core/collaboration-manager.ts index 192160eb17..cc6c85e11d 100644 --- a/web/app/components/workflow/collaboration/core/collaboration-manager.ts +++ b/web/app/components/workflow/collaboration/core/collaboration-manager.ts @@ -1538,10 +1538,13 @@ export class CollaborationManager { const wasLeader = this.isLeader this.isLeader = data.isLeader - if (this.isLeader) + if (this.isLeader) { + this.seedCrdtGraphFromReactFlowIfNeeded() this.pendingInitialSync = false - else + } + else { this.requestInitialSyncIfNeeded() + } if (wasLeader !== this.isLeader) this.eventEmitter.emit('leaderChange', this.isLeader) @@ -1603,6 +1606,30 @@ export class CollaborationManager { }) } + private seedCrdtGraphFromReactFlowIfNeeded(): void { + if (!this.doc) + return + if (!this.reactFlowStore) + return + + // CRDT may still be empty when the canvas was initially loaded from HTTP draft data + // before collaboration finished connecting, and no local mutation has been written yet. + // Seed once from the current ReactFlow graph so leader resync can broadcast a full snapshot. + if (this.getNodes().length > 0 || this.getEdges().length > 0) + return + + const state = this.reactFlowStore.getState() + const nodes = state.getNodes() + const edges = state.getEdges() + + if (!nodes.length && !edges.length) + return + + this.syncNodes([], nodes) + this.syncEdges([], edges) + this.doc.commit() + } + private broadcastCurrentGraph(): void { if (!this.currentAppId || !webSocketClient.isConnected(this.currentAppId)) return @@ -1614,6 +1641,8 @@ export class CollaborationManager { return try { + this.seedCrdtGraphFromReactFlowIfNeeded() + if (this.getNodes().length === 0 && this.getEdges().length === 0) return