| 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' |
| import { WorkflowHistoryEvent, useWorkflowHistory } from './use-workflow-history' |
|
|
| export const useEdgesInteractions = () => { |
| const store = useStoreApi() |
| const { handleSyncWorkflowDraft } = useNodesSyncDraft() |
| const { getNodesReadOnly } = useNodesReadOnly() |
| const { saveStateToHistory } = useWorkflowHistory() |
|
|
| 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() |
| const currentEdgeIndex = edges.findIndex(edge => edge.source === nodeId && edge.sourceHandle === branchId) |
|
|
| if (currentEdgeIndex < 0) |
| return |
|
|
| const currentEdge = edges[currentEdgeIndex] |
| const newNodes = produce(getNodes(), (draft: Node[]) => { |
| const sourceNode = draft.find(node => node.id === currentEdge.source) |
| const targetNode = draft.find(node => node.id === currentEdge.target) |
|
|
| if (sourceNode) |
| sourceNode.data._connectedSourceHandleIds = sourceNode.data._connectedSourceHandleIds?.filter(handleId => handleId !== currentEdge.sourceHandle) |
|
|
| if (targetNode) |
| targetNode.data._connectedTargetHandleIds = targetNode.data._connectedTargetHandleIds?.filter(handleId => handleId !== currentEdge.targetHandle) |
| }) |
| setNodes(newNodes) |
| const newEdges = produce(edges, (draft) => { |
| draft.splice(currentEdgeIndex, 1) |
| }) |
| setEdges(newEdges) |
| handleSyncWorkflowDraft() |
| saveStateToHistory(WorkflowHistoryEvent.EdgeDeleteByDeleteBranch) |
| }, [getNodesReadOnly, store, handleSyncWorkflowDraft, saveStateToHistory]) |
|
|
| 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() |
| saveStateToHistory(WorkflowHistoryEvent.EdgeDelete) |
| }, [getNodesReadOnly, store, handleSyncWorkflowDraft, saveStateToHistory]) |
|
|
| 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]) |
|
|
| const handleEdgeCancelRunningStatus = useCallback(() => { |
| const { |
| edges, |
| setEdges, |
| } = store.getState() |
|
|
| const newEdges = produce(edges, (draft) => { |
| draft.forEach((edge) => { |
| edge.data._run = false |
| }) |
| }) |
| setEdges(newEdges) |
| }, [store]) |
|
|
| return { |
| handleEdgeEnter, |
| handleEdgeLeave, |
| handleEdgeDeleteByDeleteBranch, |
| handleEdgeDelete, |
| handleEdgesChange, |
| handleEdgeCancelRunningStatus, |
| } |
| } |
|
|