use-edges-interactions.ts 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. import { useCallback } from 'react'
  2. import produce from 'immer'
  3. import type {
  4. EdgeMouseHandler,
  5. OnEdgesChange,
  6. } from 'reactflow'
  7. import {
  8. useStoreApi,
  9. } from 'reactflow'
  10. import type {
  11. Node,
  12. } from '../types'
  13. import { getNodesConnectedSourceOrTargetHandleIdsMap } from '../utils'
  14. import { useNodesSyncDraft } from './use-nodes-sync-draft'
  15. import { useNodesReadOnly } from './use-workflow'
  16. export const useEdgesInteractions = () => {
  17. const store = useStoreApi()
  18. const { handleSyncWorkflowDraft } = useNodesSyncDraft()
  19. const { getNodesReadOnly } = useNodesReadOnly()
  20. const handleEdgeEnter = useCallback<EdgeMouseHandler>((_, edge) => {
  21. if (getNodesReadOnly())
  22. return
  23. const {
  24. edges,
  25. setEdges,
  26. } = store.getState()
  27. const newEdges = produce(edges, (draft) => {
  28. const currentEdge = draft.find(e => e.id === edge.id)!
  29. currentEdge.data._hovering = true
  30. })
  31. setEdges(newEdges)
  32. }, [store, getNodesReadOnly])
  33. const handleEdgeLeave = useCallback<EdgeMouseHandler>((_, edge) => {
  34. if (getNodesReadOnly())
  35. return
  36. const {
  37. edges,
  38. setEdges,
  39. } = store.getState()
  40. const newEdges = produce(edges, (draft) => {
  41. const currentEdge = draft.find(e => e.id === edge.id)!
  42. currentEdge.data._hovering = false
  43. })
  44. setEdges(newEdges)
  45. }, [store, getNodesReadOnly])
  46. const handleEdgeDeleteByDeleteBranch = useCallback((nodeId: string, branchId: string) => {
  47. if (getNodesReadOnly())
  48. return
  49. const {
  50. getNodes,
  51. setNodes,
  52. edges,
  53. setEdges,
  54. } = store.getState()
  55. const currentEdgeIndex = edges.findIndex(edge => edge.source === nodeId && edge.sourceHandle === branchId)
  56. if (currentEdgeIndex < 0)
  57. return
  58. const currentEdge = edges[currentEdgeIndex]
  59. const newNodes = produce(getNodes(), (draft: Node[]) => {
  60. const sourceNode = draft.find(node => node.id === currentEdge.source)
  61. const targetNode = draft.find(node => node.id === currentEdge.target)
  62. if (sourceNode)
  63. sourceNode.data._connectedSourceHandleIds = sourceNode.data._connectedSourceHandleIds?.filter(handleId => handleId !== currentEdge.sourceHandle)
  64. if (targetNode)
  65. targetNode.data._connectedTargetHandleIds = targetNode.data._connectedTargetHandleIds?.filter(handleId => handleId !== currentEdge.targetHandle)
  66. })
  67. setNodes(newNodes)
  68. const newEdges = produce(edges, (draft) => {
  69. draft.splice(currentEdgeIndex, 1)
  70. })
  71. setEdges(newEdges)
  72. handleSyncWorkflowDraft()
  73. }, [store, handleSyncWorkflowDraft, getNodesReadOnly])
  74. const handleEdgeDelete = useCallback(() => {
  75. if (getNodesReadOnly())
  76. return
  77. const {
  78. getNodes,
  79. setNodes,
  80. edges,
  81. setEdges,
  82. } = store.getState()
  83. const currentEdgeIndex = edges.findIndex(edge => edge.selected)
  84. if (currentEdgeIndex < 0)
  85. return
  86. const currentEdge = edges[currentEdgeIndex]
  87. const nodes = getNodes()
  88. const nodesConnectedSourceOrTargetHandleIdsMap = getNodesConnectedSourceOrTargetHandleIdsMap(
  89. [
  90. { type: 'remove', edge: currentEdge },
  91. ],
  92. nodes,
  93. )
  94. const newNodes = produce(nodes, (draft: Node[]) => {
  95. draft.forEach((node) => {
  96. if (nodesConnectedSourceOrTargetHandleIdsMap[node.id]) {
  97. node.data = {
  98. ...node.data,
  99. ...nodesConnectedSourceOrTargetHandleIdsMap[node.id],
  100. }
  101. }
  102. })
  103. })
  104. setNodes(newNodes)
  105. const newEdges = produce(edges, (draft) => {
  106. draft.splice(currentEdgeIndex, 1)
  107. })
  108. setEdges(newEdges)
  109. handleSyncWorkflowDraft()
  110. }, [store, getNodesReadOnly, handleSyncWorkflowDraft])
  111. const handleEdgesChange = useCallback<OnEdgesChange>((changes) => {
  112. if (getNodesReadOnly())
  113. return
  114. const {
  115. edges,
  116. setEdges,
  117. } = store.getState()
  118. const newEdges = produce(edges, (draft) => {
  119. changes.forEach((change) => {
  120. if (change.type === 'select')
  121. draft.find(edge => edge.id === change.id)!.selected = change.selected
  122. })
  123. })
  124. setEdges(newEdges)
  125. }, [store, getNodesReadOnly])
  126. const handleEdgeCancelRunningStatus = useCallback(() => {
  127. const {
  128. edges,
  129. setEdges,
  130. } = store.getState()
  131. const newEdges = produce(edges, (draft) => {
  132. draft.forEach((edge) => {
  133. edge.data._runned = false
  134. })
  135. })
  136. setEdges(newEdges)
  137. }, [store])
  138. return {
  139. handleEdgeEnter,
  140. handleEdgeLeave,
  141. handleEdgeDeleteByDeleteBranch,
  142. handleEdgeDelete,
  143. handleEdgesChange,
  144. handleEdgeCancelRunningStatus,
  145. }
  146. }