| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  | import { useCallback } from 'react' | 
					
						
							|  |  |  | import produce from 'immer' | 
					
						
							|  |  |  | import type { | 
					
						
							|  |  |  |   EdgeMouseHandler, | 
					
						
							|  |  |  |   OnEdgesChange, | 
					
						
							|  |  |  | } from 'reactflow' | 
					
						
							|  |  |  | import { | 
					
						
							|  |  |  |   useStoreApi, | 
					
						
							|  |  |  | } from 'reactflow' | 
					
						
							|  |  |  | import type { | 
					
						
							|  |  |  |   Node, | 
					
						
							|  |  |  | } from '../types' | 
					
						
							|  |  |  | import { getNodesConnectedSourceOrTargetHandleIdsMap } from '../utils' | 
					
						
							|  |  |  | import { useNodesSyncDraft } from './use-nodes-sync-draft' | 
					
						
							|  |  |  | import { useNodesReadOnly } from './use-workflow' | 
					
						
							| 
									
										
										
										
											2024-06-26 08:37:12 +02:00
										 |  |  | import { WorkflowHistoryEvent, useWorkflowHistory } from './use-workflow-history' | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | export const useEdgesInteractions = () => { | 
					
						
							|  |  |  |   const store = useStoreApi() | 
					
						
							|  |  |  |   const { handleSyncWorkflowDraft } = useNodesSyncDraft() | 
					
						
							|  |  |  |   const { getNodesReadOnly } = useNodesReadOnly() | 
					
						
							| 
									
										
										
										
											2024-06-26 08:37:12 +02:00
										 |  |  |   const { saveStateToHistory } = useWorkflowHistory() | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   const handleEdgeEnter = useCallback<EdgeMouseHandler>((_, edge) => { | 
					
						
							|  |  |  |     if (getNodesReadOnly()) | 
					
						
							|  |  |  |       return | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const { | 
					
						
							|  |  |  |       edges, | 
					
						
							|  |  |  |       setEdges, | 
					
						
							|  |  |  |     } = store.getState() | 
					
						
							|  |  |  |     const newEdges = produce(edges, (draft) => { | 
					
						
							|  |  |  |       const currentEdge = draft.find(e => e.id === edge.id)! | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       currentEdge.data._hovering = true | 
					
						
							|  |  |  |     }) | 
					
						
							|  |  |  |     setEdges(newEdges) | 
					
						
							|  |  |  |   }, [store, getNodesReadOnly]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const handleEdgeLeave = useCallback<EdgeMouseHandler>((_, edge) => { | 
					
						
							|  |  |  |     if (getNodesReadOnly()) | 
					
						
							|  |  |  |       return | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const { | 
					
						
							|  |  |  |       edges, | 
					
						
							|  |  |  |       setEdges, | 
					
						
							|  |  |  |     } = store.getState() | 
					
						
							|  |  |  |     const newEdges = produce(edges, (draft) => { | 
					
						
							|  |  |  |       const currentEdge = draft.find(e => e.id === edge.id)! | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       currentEdge.data._hovering = false | 
					
						
							|  |  |  |     }) | 
					
						
							|  |  |  |     setEdges(newEdges) | 
					
						
							|  |  |  |   }, [store, getNodesReadOnly]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const handleEdgeDeleteByDeleteBranch = useCallback((nodeId: string, branchId: string) => { | 
					
						
							|  |  |  |     if (getNodesReadOnly()) | 
					
						
							|  |  |  |       return | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const { | 
					
						
							|  |  |  |       getNodes, | 
					
						
							|  |  |  |       setNodes, | 
					
						
							|  |  |  |       edges, | 
					
						
							|  |  |  |       setEdges, | 
					
						
							|  |  |  |     } = store.getState() | 
					
						
							| 
									
										
										
										
											2024-12-11 14:21:38 +08:00
										 |  |  |     const edgeWillBeDeleted = edges.filter(edge => edge.source === nodeId && edge.sourceHandle === branchId) | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-11 14:21:38 +08:00
										 |  |  |     if (!edgeWillBeDeleted.length) | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |       return | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-11 14:21:38 +08:00
										 |  |  |     const nodes = getNodes() | 
					
						
							|  |  |  |     const nodesConnectedSourceOrTargetHandleIdsMap = getNodesConnectedSourceOrTargetHandleIdsMap( | 
					
						
							|  |  |  |       edgeWillBeDeleted.map(edge => ({ type: 'remove', edge })), | 
					
						
							|  |  |  |       nodes, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     const newNodes = produce(nodes, (draft: Node[]) => { | 
					
						
							|  |  |  |       draft.forEach((node) => { | 
					
						
							|  |  |  |         if (nodesConnectedSourceOrTargetHandleIdsMap[node.id]) { | 
					
						
							|  |  |  |           node.data = { | 
					
						
							|  |  |  |             ...node.data, | 
					
						
							|  |  |  |             ...nodesConnectedSourceOrTargetHandleIdsMap[node.id], | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       }) | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |     }) | 
					
						
							|  |  |  |     setNodes(newNodes) | 
					
						
							|  |  |  |     const newEdges = produce(edges, (draft) => { | 
					
						
							| 
									
										
										
										
											2024-12-11 14:21:38 +08:00
										 |  |  |       return draft.filter(edge => !edgeWillBeDeleted.find(e => e.id === edge.id)) | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |     }) | 
					
						
							|  |  |  |     setEdges(newEdges) | 
					
						
							|  |  |  |     handleSyncWorkflowDraft() | 
					
						
							| 
									
										
										
										
											2024-06-26 08:37:12 +02:00
										 |  |  |     saveStateToHistory(WorkflowHistoryEvent.EdgeDeleteByDeleteBranch) | 
					
						
							|  |  |  |   }, [getNodesReadOnly, store, handleSyncWorkflowDraft, saveStateToHistory]) | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   const handleEdgeDelete = useCallback(() => { | 
					
						
							|  |  |  |     if (getNodesReadOnly()) | 
					
						
							|  |  |  |       return | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const { | 
					
						
							|  |  |  |       getNodes, | 
					
						
							|  |  |  |       setNodes, | 
					
						
							|  |  |  |       edges, | 
					
						
							|  |  |  |       setEdges, | 
					
						
							|  |  |  |     } = store.getState() | 
					
						
							|  |  |  |     const currentEdgeIndex = edges.findIndex(edge => edge.selected) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (currentEdgeIndex < 0) | 
					
						
							|  |  |  |       return | 
					
						
							|  |  |  |     const currentEdge = edges[currentEdgeIndex] | 
					
						
							|  |  |  |     const nodes = getNodes() | 
					
						
							|  |  |  |     const nodesConnectedSourceOrTargetHandleIdsMap = getNodesConnectedSourceOrTargetHandleIdsMap( | 
					
						
							|  |  |  |       [ | 
					
						
							|  |  |  |         { type: 'remove', edge: currentEdge }, | 
					
						
							|  |  |  |       ], | 
					
						
							|  |  |  |       nodes, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     const newNodes = produce(nodes, (draft: Node[]) => { | 
					
						
							|  |  |  |       draft.forEach((node) => { | 
					
						
							|  |  |  |         if (nodesConnectedSourceOrTargetHandleIdsMap[node.id]) { | 
					
						
							|  |  |  |           node.data = { | 
					
						
							|  |  |  |             ...node.data, | 
					
						
							|  |  |  |             ...nodesConnectedSourceOrTargetHandleIdsMap[node.id], | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       }) | 
					
						
							|  |  |  |     }) | 
					
						
							|  |  |  |     setNodes(newNodes) | 
					
						
							|  |  |  |     const newEdges = produce(edges, (draft) => { | 
					
						
							|  |  |  |       draft.splice(currentEdgeIndex, 1) | 
					
						
							|  |  |  |     }) | 
					
						
							|  |  |  |     setEdges(newEdges) | 
					
						
							|  |  |  |     handleSyncWorkflowDraft() | 
					
						
							| 
									
										
										
										
											2024-06-26 08:37:12 +02:00
										 |  |  |     saveStateToHistory(WorkflowHistoryEvent.EdgeDelete) | 
					
						
							|  |  |  |   }, [getNodesReadOnly, store, handleSyncWorkflowDraft, saveStateToHistory]) | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   const handleEdgesChange = useCallback<OnEdgesChange>((changes) => { | 
					
						
							|  |  |  |     if (getNodesReadOnly()) | 
					
						
							|  |  |  |       return | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const { | 
					
						
							|  |  |  |       edges, | 
					
						
							|  |  |  |       setEdges, | 
					
						
							|  |  |  |     } = store.getState() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const newEdges = produce(edges, (draft) => { | 
					
						
							|  |  |  |       changes.forEach((change) => { | 
					
						
							|  |  |  |         if (change.type === 'select') | 
					
						
							|  |  |  |           draft.find(edge => edge.id === change.id)!.selected = change.selected | 
					
						
							|  |  |  |       }) | 
					
						
							|  |  |  |     }) | 
					
						
							|  |  |  |     setEdges(newEdges) | 
					
						
							|  |  |  |   }, [store, getNodesReadOnly]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return { | 
					
						
							|  |  |  |     handleEdgeEnter, | 
					
						
							|  |  |  |     handleEdgeLeave, | 
					
						
							|  |  |  |     handleEdgeDeleteByDeleteBranch, | 
					
						
							|  |  |  |     handleEdgeDelete, | 
					
						
							|  |  |  |     handleEdgesChange, | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } |