try a lot for yjs, but update data still not work...

This commit is contained in:
hjlarry
2025-07-30 14:36:29 +08:00
parent 41372168b6
commit 4cc01c8aa8
7 changed files with 236 additions and 9 deletions

View File

@ -61,6 +61,7 @@ import {
} from './use-workflow'
import { WorkflowHistoryEvent, useWorkflowHistory } from './use-workflow-history'
import useInspectVarsCrud from './use-inspect-vars-crud'
import { useCollaborationStore } from '@/app/components/workflow/store/collaboration-store'
export const useNodesInteractions = () => {
const { t } = useTranslation()
@ -1496,6 +1497,21 @@ export const useNodesInteractions = () => {
return draft.filter(edge => !connectedEdges.find(connectedEdge => connectedEdge.id === edge.id))
})
setEdges(newEdges)
const { yNodesMap, yEdgesMap, ydoc } = useCollaborationStore.getState()
if (yNodesMap && yEdgesMap && ydoc) {
ydoc.transact(() => {
newNodes.forEach((node) => {
yNodesMap.set(node.id, node)
})
console.log('Before edge delete, yEdgesMap size:', yEdgesMap?.size)
connectedEdges.forEach((edge) => {
yEdgesMap.delete(edge.id)
})
console.log('After edge delete, yEdgesMap size:', yEdgesMap?.size)
})
}
handleSyncWorkflowDraft()
saveStateToHistory(WorkflowHistoryEvent.EdgeDelete)
}, [store, getNodesReadOnly, handleSyncWorkflowDraft, saveStateToHistory])

View File

@ -83,6 +83,7 @@ import Confirm from '@/app/components/base/confirm'
import DatasetsDetailProvider from './datasets-detail-store/provider'
import { HooksStoreContextProvider } from './hooks-store'
import type { Shape as HooksStoreShape } from './hooks-store'
import { useCollaborationStore } from '@/app/components/workflow/store/collaboration-store'
const nodeTypes = {
[CUSTOM_NODE]: CustomNode,
@ -127,6 +128,22 @@ export const Workflow: FC<WorkflowProps> = memo(({
return workflowCanvasHeight - bottomPanelHeight
}, [workflowCanvasHeight, bottomPanelHeight])
const collaborationNodes = useCollaborationStore((state) => {
return state.nodes
})
const collaborationEdges = useCollaborationStore((state) => {
return state.edges
})
useEffect(() => {
setNodes(collaborationNodes)
}, [collaborationNodes, setNodes])
useEffect(() => {
console.log('collaborationEdges changed:', collaborationEdges, 122112)
setEdges(collaborationEdges)
}, [collaborationEdges, setEdges])
// update workflow Canvas width and height
useEffect(() => {
if (workflowContainerRef.current) {

View File

@ -0,0 +1,132 @@
import { create } from 'zustand'
import * as Y from 'yjs'
import type { Edge, Node } from '../types'
import { useWebSocketStore } from './websocket-store'
let globalYDoc: Y.Doc | null = null
let globalYNodesMap: Y.Map<any> | null = null
let globalYEdgesMap: Y.Map<any> | null = null
class YjsSocketIOProvider {
private doc: Y.Doc
private socket: any
private isDestroyed = false
private onRemoteUpdate?: () => void
constructor(socket: any, doc: Y.Doc, onRemoteUpdate?: () => void) {
this.socket = socket
this.doc = doc
this.onRemoteUpdate = onRemoteUpdate
this.setupEventListeners()
}
private setupEventListeners() {
this.doc.on('update', (update: Uint8Array, origin: any) => {
if (origin !== 'remote')
this.socket.emit('yjs_update', update)
})
this.socket.on('yjs_update', (updateData: Uint8Array) => {
Y.applyUpdate(this.doc, new Uint8Array(updateData), 'remote')
if (this.onRemoteUpdate)
this.onRemoteUpdate()
})
}
destroy() {
this.isDestroyed = true
}
}
type CollaborationStore = {
ydoc: Y.Doc | null
provider: YjsSocketIOProvider | null
yNodesMap: Y.Map<any> | null
yEdgesMap: Y.Map<any> | null
yTestMap: Y.Map<any> | null
yTestArray: Y.Array<any> | null
nodes: Node[]
edges: Edge[]
initCollaboration: (appId: string) => void
destroyCollaboration: () => void
}
export const useCollaborationStore = create<CollaborationStore>((set, get) => ({
ydoc: null,
provider: null,
yNodesMap: null,
yEdgesMap: null,
yTestMap: null,
yTestArray: null,
nodes: [],
edges: [],
initCollaboration: (appId: string) => {
if (!globalYDoc) {
console.log('Creating new global Y.Doc instance')
globalYDoc = new Y.Doc()
globalYNodesMap = globalYDoc.getMap<any>('nodes')
globalYEdgesMap = globalYDoc.getMap<any>('edges')
}
else {
console.log('Reusing existing global Y.Doc instance')
}
const ydoc = globalYDoc
const yNodesMap = globalYNodesMap!
const yEdgesMap = globalYEdgesMap!
const { getSocket } = useWebSocketStore.getState()
const socket = getSocket(appId)
const updateReactState = () => {
console.log('updateReactState called')
const nodes = Array.from(yNodesMap.values())
const edges = Array.from(yEdgesMap.values())
console.log('Y.js data - nodes:', nodes.length, 'edges:', edges.length)
set({
nodes: [...nodes] as Node[],
edges: [...edges] as Edge[],
})
}
const provider = new YjsSocketIOProvider(socket, globalYDoc, updateReactState)
yNodesMap.observe((event) => {
console.log('yNodesMap changed:', event)
updateReactState()
})
yEdgesMap.observe((event) => {
console.log('yEdgesMap changed:', event)
updateReactState()
})
updateReactState()
set({
ydoc,
provider,
yNodesMap,
yEdgesMap,
})
},
destroyCollaboration: () => {
const { provider } = get()
provider?.destroy()
set({
ydoc: null,
provider: null,
yNodesMap: null,
yEdgesMap: null,
})
},
}))