use-shortcuts.ts 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. import { useReactFlow } from 'reactflow'
  2. import { useKeyPress } from 'ahooks'
  3. import { useCallback } from 'react'
  4. import {
  5. getKeyboardKeyCodeBySystem,
  6. isEventTargetInputArea,
  7. } from '../utils'
  8. import { useWorkflowHistoryStore } from '../workflow-history-store'
  9. import { useWorkflowStore } from '../store'
  10. import {
  11. useEdgesInteractions,
  12. useNodesInteractions,
  13. useNodesSyncDraft,
  14. useWorkflowMoveMode,
  15. useWorkflowOrganize,
  16. useWorkflowStartRun,
  17. } from '.'
  18. export const useShortcuts = (): void => {
  19. const {
  20. handleNodesCopy,
  21. handleNodesPaste,
  22. handleNodesDuplicate,
  23. handleNodesDelete,
  24. handleHistoryBack,
  25. handleHistoryForward,
  26. } = useNodesInteractions()
  27. const { handleStartWorkflowRun } = useWorkflowStartRun()
  28. const { shortcutsEnabled: workflowHistoryShortcutsEnabled } = useWorkflowHistoryStore()
  29. const { handleSyncWorkflowDraft } = useNodesSyncDraft()
  30. const { handleEdgeDelete } = useEdgesInteractions()
  31. const workflowStore = useWorkflowStore()
  32. const {
  33. handleModeHand,
  34. handleModePointer,
  35. } = useWorkflowMoveMode()
  36. const { handleLayout } = useWorkflowOrganize()
  37. const {
  38. zoomTo,
  39. getZoom,
  40. fitView,
  41. } = useReactFlow()
  42. // Zoom out to a minimum of 0.5 for shortcut
  43. const constrainedZoomOut = () => {
  44. const currentZoom = getZoom()
  45. const newZoom = Math.max(currentZoom - 0.1, 0.5)
  46. zoomTo(newZoom)
  47. }
  48. // Zoom in to a maximum of 1 for shortcut
  49. const constrainedZoomIn = () => {
  50. const currentZoom = getZoom()
  51. const newZoom = Math.min(currentZoom + 0.1, 1)
  52. zoomTo(newZoom)
  53. }
  54. const shouldHandleShortcut = useCallback((e: KeyboardEvent) => {
  55. const { showFeaturesPanel } = workflowStore.getState()
  56. return !showFeaturesPanel && !isEventTargetInputArea(e.target as HTMLElement)
  57. }, [workflowStore])
  58. useKeyPress(['delete', 'backspace'], (e) => {
  59. if (shouldHandleShortcut(e)) {
  60. e.preventDefault()
  61. handleNodesDelete()
  62. handleEdgeDelete()
  63. }
  64. })
  65. useKeyPress(`${getKeyboardKeyCodeBySystem('ctrl')}.c`, (e) => {
  66. const { showDebugAndPreviewPanel } = workflowStore.getState()
  67. if (shouldHandleShortcut(e) && !showDebugAndPreviewPanel) {
  68. e.preventDefault()
  69. handleNodesCopy()
  70. }
  71. }, { exactMatch: true, useCapture: true })
  72. useKeyPress(`${getKeyboardKeyCodeBySystem('ctrl')}.v`, (e) => {
  73. const { showDebugAndPreviewPanel } = workflowStore.getState()
  74. if (shouldHandleShortcut(e) && !showDebugAndPreviewPanel) {
  75. e.preventDefault()
  76. handleNodesPaste()
  77. }
  78. }, { exactMatch: true, useCapture: true })
  79. useKeyPress(`${getKeyboardKeyCodeBySystem('ctrl')}.d`, (e) => {
  80. if (shouldHandleShortcut(e)) {
  81. e.preventDefault()
  82. handleNodesDuplicate()
  83. }
  84. }, { exactMatch: true, useCapture: true })
  85. useKeyPress(`${getKeyboardKeyCodeBySystem('alt')}.r`, (e) => {
  86. if (shouldHandleShortcut(e)) {
  87. e.preventDefault()
  88. handleStartWorkflowRun()
  89. }
  90. }, { exactMatch: true, useCapture: true })
  91. useKeyPress(`${getKeyboardKeyCodeBySystem('ctrl')}.z`, (e) => {
  92. const { showDebugAndPreviewPanel } = workflowStore.getState()
  93. if (shouldHandleShortcut(e) && !showDebugAndPreviewPanel) {
  94. e.preventDefault()
  95. workflowHistoryShortcutsEnabled && handleHistoryBack()
  96. }
  97. }, { exactMatch: true, useCapture: true })
  98. useKeyPress(
  99. [`${getKeyboardKeyCodeBySystem('ctrl')}.y`, `${getKeyboardKeyCodeBySystem('ctrl')}.shift.z`],
  100. (e) => {
  101. if (shouldHandleShortcut(e)) {
  102. e.preventDefault()
  103. workflowHistoryShortcutsEnabled && handleHistoryForward()
  104. }
  105. },
  106. { exactMatch: true, useCapture: true },
  107. )
  108. useKeyPress('h', (e) => {
  109. if (shouldHandleShortcut(e)) {
  110. e.preventDefault()
  111. handleModeHand()
  112. }
  113. }, {
  114. exactMatch: true,
  115. useCapture: true,
  116. })
  117. useKeyPress('v', (e) => {
  118. if (shouldHandleShortcut(e)) {
  119. e.preventDefault()
  120. handleModePointer()
  121. }
  122. }, {
  123. exactMatch: true,
  124. useCapture: true,
  125. })
  126. useKeyPress(`${getKeyboardKeyCodeBySystem('ctrl')}.o`, (e) => {
  127. if (shouldHandleShortcut(e)) {
  128. e.preventDefault()
  129. handleLayout()
  130. }
  131. }, { exactMatch: true, useCapture: true })
  132. useKeyPress(`${getKeyboardKeyCodeBySystem('ctrl')}.1`, (e) => {
  133. if (shouldHandleShortcut(e)) {
  134. e.preventDefault()
  135. fitView()
  136. handleSyncWorkflowDraft()
  137. }
  138. }, {
  139. exactMatch: true,
  140. useCapture: true,
  141. })
  142. useKeyPress('shift.1', (e) => {
  143. if (shouldHandleShortcut(e)) {
  144. e.preventDefault()
  145. zoomTo(1)
  146. handleSyncWorkflowDraft()
  147. }
  148. }, {
  149. exactMatch: true,
  150. useCapture: true,
  151. })
  152. useKeyPress('shift.5', (e) => {
  153. if (shouldHandleShortcut(e)) {
  154. e.preventDefault()
  155. zoomTo(0.5)
  156. handleSyncWorkflowDraft()
  157. }
  158. }, {
  159. exactMatch: true,
  160. useCapture: true,
  161. })
  162. useKeyPress(`${getKeyboardKeyCodeBySystem('ctrl')}.dash`, (e) => {
  163. if (shouldHandleShortcut(e)) {
  164. e.preventDefault()
  165. constrainedZoomOut()
  166. handleSyncWorkflowDraft()
  167. }
  168. }, {
  169. exactMatch: true,
  170. useCapture: true,
  171. })
  172. useKeyPress(`${getKeyboardKeyCodeBySystem('ctrl')}.equalsign`, (e) => {
  173. if (shouldHandleShortcut(e)) {
  174. e.preventDefault()
  175. constrainedZoomIn()
  176. handleSyncWorkflowDraft()
  177. }
  178. }, {
  179. exactMatch: true,
  180. useCapture: true,
  181. })
  182. }