From 995d5ccf6628163fd0b0d1f95fc1572f75c31137 Mon Sep 17 00:00:00 2001 From: hjlarry Date: Mon, 19 Jan 2026 13:45:00 +0800 Subject: [PATCH] fix graph not sync --- .../core/collaboration-manager.ts | 23 +++++++++++++++++++ web/app/components/workflow/index.tsx | 15 +++++++++++- 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/web/app/components/workflow/collaboration/core/collaboration-manager.ts b/web/app/components/workflow/collaboration/core/collaboration-manager.ts index 03863306c0..87f5d45ec2 100644 --- a/web/app/components/workflow/collaboration/core/collaboration-manager.ts +++ b/web/app/components/workflow/collaboration/core/collaboration-manager.ts @@ -73,6 +73,7 @@ export class CollaborationManager { private isUndoRedoInProgress = false private pendingInitialSync = false private rejoinInProgress = false + private pendingGraphImportEmit = false private getActiveSocket(): Socket | null { if (!this.currentAppId) @@ -588,6 +589,10 @@ export class CollaborationManager { return this.eventEmitter.on('syncRequest', callback) } + onGraphImport(callback: (payload: { nodes: Node[], edges: Edge[] }) => void): () => void { + return this.eventEmitter.on('graphImport', callback) + } + onStateChange(callback: (state: Partial) => void): () => void { return this.eventEmitter.on('stateChange', callback) } @@ -849,6 +854,8 @@ export class CollaborationManager { // Call ReactFlow's native setter directly to avoid triggering collaboration state.setNodes(updatedNodes) + + this.scheduleGraphImportEmit() }) } }) @@ -869,11 +876,27 @@ export class CollaborationManager { // Call ReactFlow's native setter directly to avoid triggering collaboration state.setEdges(updatedEdges) + + this.scheduleGraphImportEmit() }) } }) } + private scheduleGraphImportEmit(): void { + if (this.pendingGraphImportEmit) + return + + this.pendingGraphImportEmit = true + requestAnimationFrame(() => { + this.pendingGraphImportEmit = false + this.eventEmitter.emit('graphImport', { + nodes: this.getNodes(), + edges: this.getEdges(), + }) + }) + } + private setupSocketEventListeners(socket: Socket): void { socket.on('collaboration_update', (update: CollaborationUpdate) => { if (update.type === 'mouse_move') { diff --git a/web/app/components/workflow/index.tsx b/web/app/components/workflow/index.tsx index 3941dae7c0..1c490f20d6 100644 --- a/web/app/components/workflow/index.tsx +++ b/web/app/components/workflow/index.tsx @@ -52,6 +52,7 @@ import { import { fetchAllInspectVars } from '@/service/workflow' import { cn } from '@/utils/classnames' import CandidateNode from './candidate-node' +import { collaborationManager } from './collaboration' import UserCursors from './collaboration/components/user-cursors' import { CommentCursor, CommentIcon, CommentInput, CommentThread } from './comment' import CommentManager from './comment-manager' @@ -172,6 +173,7 @@ export const Workflow: FC = memo(({ const workflowContainerRef = useRef(null) const workflowStore = useWorkflowStore() const reactflow = useReactFlow() + const store = useStoreApi() const [isMouseOverCanvas, setIsMouseOverCanvas] = useState(false) const [nodes, setNodes] = useNodesState(originalNodes) const [edges, setEdges] = useEdgesState(originalEdges) @@ -227,6 +229,18 @@ export const Workflow: FC = memo(({ useEffect(() => { setNodesOnlyChangeWithData(currentNodes as Node[]) }, [currentNodes, setNodesOnlyChangeWithData]) + useEffect(() => { + return collaborationManager.onGraphImport(({ nodes: importedNodes, edges: importedEdges }) => { + if (!isEqual(nodes, importedNodes)) { + setNodes(importedNodes) + store.getState().setNodes(importedNodes) + } + if (!isEqual(edges, importedEdges)) { + setEdges(importedEdges) + store.getState().setEdges(importedEdges) + } + }) + }, [edges, nodes, setEdges, setNodes, store]) const { handleSyncWorkflowDraft, syncWorkflowDraftWhenPageClose, @@ -260,7 +274,6 @@ export const Workflow: FC = memo(({ const isCommentInputActive = Boolean(pendingComment) const { t } = useTranslation() - const store = useStoreApi() eventEmitter?.useSubscription((event) => { const workflowEvent = event as unknown as WorkflowEvent if (workflowEvent.type === WORKFLOW_DATA_UPDATE && isWorkflowDataUpdatePayload(workflowEvent.payload)) {