mirror of
https://github.com/langgenius/dify.git
synced 2026-04-15 09:57:03 +08:00
Knowledge Retrieval panel effects depend on setInputs. In the collaboration branch the callback chain started changing identity on every render, so adding this node could repeatedly write node data and freeze the browser. Stabilize the collaborative workflow API returned by useCollaborativeWorkflow and keep useNodeCrud.setInputs stable while forwarding to the latest updater. Add a regression test for the stable setInputs contract.
86 lines
2.3 KiB
TypeScript
86 lines
2.3 KiB
TypeScript
import type { Edge, Node } from '../types'
|
|
import { useCallback, useMemo } from 'react'
|
|
import { useStoreApi } from 'reactflow'
|
|
import { collaborationManager } from '../collaboration/core/collaboration-manager'
|
|
|
|
const sanitizeNodeForBroadcast = (node: Node): Node => {
|
|
if (!node.data)
|
|
return node
|
|
|
|
if (!Object.prototype.hasOwnProperty.call(node.data, 'selected'))
|
|
return node
|
|
|
|
const sanitizedData = { ...node.data }
|
|
delete (sanitizedData as Record<string, unknown>).selected
|
|
|
|
return {
|
|
...node,
|
|
data: sanitizedData,
|
|
}
|
|
}
|
|
|
|
const sanitizeEdgeForBroadcast = (edge: Edge): Edge => {
|
|
if (!edge.data)
|
|
return edge
|
|
|
|
if (!Object.prototype.hasOwnProperty.call(edge.data, '_connectedNodeIsSelected'))
|
|
return edge
|
|
|
|
const sanitizedData = { ...edge.data }
|
|
delete (sanitizedData as Record<string, unknown>)._connectedNodeIsSelected
|
|
|
|
return {
|
|
...edge,
|
|
data: sanitizedData,
|
|
}
|
|
}
|
|
|
|
export const useCollaborativeWorkflow = () => {
|
|
const store = useStoreApi()
|
|
const { setNodes: collabSetNodes, setEdges: collabSetEdges } = collaborationManager
|
|
|
|
const setNodes = useCallback((newNodes: Node[], shouldBroadcast: boolean = true, source = 'use-collaborative-workflow:setNodes') => {
|
|
const { getNodes, setNodes: reactFlowSetNodes } = store.getState()
|
|
if (shouldBroadcast) {
|
|
const oldNodes = getNodes()
|
|
collabSetNodes(
|
|
oldNodes.map(sanitizeNodeForBroadcast),
|
|
newNodes.map(sanitizeNodeForBroadcast),
|
|
source,
|
|
)
|
|
}
|
|
reactFlowSetNodes(newNodes)
|
|
}, [store, collabSetNodes])
|
|
|
|
const setEdges = useCallback((newEdges: Edge[], shouldBroadcast: boolean = true) => {
|
|
const { edges, setEdges: reactFlowSetEdges } = store.getState()
|
|
if (shouldBroadcast) {
|
|
collabSetEdges(
|
|
edges.map(sanitizeEdgeForBroadcast),
|
|
newEdges.map(sanitizeEdgeForBroadcast),
|
|
)
|
|
}
|
|
|
|
reactFlowSetEdges(newEdges)
|
|
}, [store, collabSetEdges])
|
|
|
|
const collaborativeStore = useCallback(() => {
|
|
const state = store.getState()
|
|
return {
|
|
|
|
nodes: state.getNodes(),
|
|
edges: state.edges,
|
|
|
|
setNodes,
|
|
setEdges,
|
|
|
|
}
|
|
}, [store, setNodes, setEdges])
|
|
|
|
return useMemo(() => ({
|
|
getState: collaborativeStore,
|
|
setNodes,
|
|
setEdges,
|
|
}), [collaborativeStore, setEdges, setNodes])
|
|
}
|