Skip to content

Commit

Permalink
Feat: shortcut hook (langgenius#7385)
Browse files Browse the repository at this point in the history
  • Loading branch information
YIXIAO0 authored Aug 19, 2024
1 parent 68dc6d5 commit 8b06105
Show file tree
Hide file tree
Showing 14 changed files with 402 additions and 332 deletions.
4 changes: 3 additions & 1 deletion web/app/components/workflow/header/run-and-history.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ const RunMode = memo(() => {
'hover:bg-state-accent-hover cursor-pointer',
isRunning && 'bg-state-accent-hover !cursor-not-allowed',
)}
onClick={() => handleWorkflowStartRunInWorkflow()}
onClick={() => {
handleWorkflowStartRunInWorkflow()
}}
>
{
isRunning
Expand Down
4 changes: 3 additions & 1 deletion web/app/components/workflow/header/view-history.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
useWorkflowInteractions,
useWorkflowRun,
} from '../hooks'
import { WorkflowRunningStatus } from '../types'
import { ControlMode, WorkflowRunningStatus } from '../types'
import cn from '@/utils/classnames'
import {
PortalToFollowElem,
Expand Down Expand Up @@ -58,6 +58,7 @@ const ViewHistory = ({
handleCancelDebugAndPreviewPanel,
} = useWorkflowInteractions()
const workflowStore = useWorkflowStore()
const setControlMode = useStore(s => s.setControlMode)
const { appDetail, setCurrentLogItem, setShowMessageLogModal } = useAppStore(useShallow(state => ({
appDetail: state.appDetail,
setCurrentLogItem: state.setCurrentLogItem,
Expand Down Expand Up @@ -173,6 +174,7 @@ const ViewHistory = ({
setOpen(false)
handleNodesCancelSelected()
handleCancelDebugAndPreviewPanel()
setControlMode(ControlMode.Hand)
}}
>
{
Expand Down
5 changes: 3 additions & 2 deletions web/app/components/workflow/hooks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@ export * from './use-workflow'
export * from './use-workflow-run'
export * from './use-workflow-template'
export * from './use-checklist'
export * from './use-workflow-mode'
export * from './use-workflow-interactions'
export * from './use-selection-interactions'
export * from './use-panel-interactions'
export * from './use-workflow-start-run'
export * from './use-nodes-layout'
export * from './use-workflow-history'
export * from './use-workflow-variables'
export * from './use-shortcuts'
export * from './use-workflow-interactions'
export * from './use-workflow-mode'
53 changes: 13 additions & 40 deletions web/app/components/workflow/hooks/use-nodes-interactions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import { useHelpline } from './use-helpline'
import {
useNodesReadOnly,
useWorkflow,
useWorkflowReadOnly,
} from './use-workflow'
import { WorkflowHistoryEvent, useWorkflowHistory } from './use-workflow-history'

Expand All @@ -62,6 +63,7 @@ export const useNodesInteractions = () => {
getAfterNodesInSameBranch,
} = useWorkflow()
const { getNodesReadOnly } = useNodesReadOnly()
const { getWorkflowReadOnly } = useWorkflowReadOnly()
const { handleSetHelpline } = useHelpline()
const {
handleNodeIterationChildDrag,
Expand Down Expand Up @@ -1029,14 +1031,7 @@ export const useNodesInteractions = () => {
if (getNodesReadOnly())
return

const {
setClipboardElements,
shortcutsDisabled,
showFeaturesPanel,
} = workflowStore.getState()

if (shortcutsDisabled || showFeaturesPanel)
return
const { setClipboardElements } = workflowStore.getState()

const {
getNodes,
Expand All @@ -1062,14 +1057,9 @@ export const useNodesInteractions = () => {

const {
clipboardElements,
shortcutsDisabled,
showFeaturesPanel,
mousePosition,
} = workflowStore.getState()

if (shortcutsDisabled || showFeaturesPanel)
return

const {
getNodes,
setNodes,
Expand Down Expand Up @@ -1107,6 +1097,11 @@ export const useNodesInteractions = () => {
})
newNode.id = newNode.id + index

// If only the iteration start node is copied, remove the isIterationStart flag
// This new node is movable and can be placed anywhere
if (clipboardElements.length === 1 && newNode.data.isIterationStart)
newNode.data.isIterationStart = false

let newChildren: Node[] = []
if (nodeToPaste.data.type === BlockEnum.Iteration) {
newNode.data._children = [];
Expand Down Expand Up @@ -1145,14 +1140,6 @@ export const useNodesInteractions = () => {
if (getNodesReadOnly())
return

const {
shortcutsDisabled,
showFeaturesPanel,
} = workflowStore.getState()

if (shortcutsDisabled || showFeaturesPanel)
return

const {
getNodes,
edges,
Expand All @@ -1175,7 +1162,7 @@ export const useNodesInteractions = () => {

if (selectedNode)
handleNodeDelete(selectedNode.id)
}, [store, workflowStore, getNodesReadOnly, handleNodeDelete])
}, [store, getNodesReadOnly, handleNodeDelete])

const handleNodeResize = useCallback((nodeId: string, params: ResizeParamsWithDirection) => {
if (getNodesReadOnly())
Expand Down Expand Up @@ -1234,14 +1221,7 @@ export const useNodesInteractions = () => {
}, [getNodesReadOnly, store, handleSyncWorkflowDraft, saveStateToHistory])

const handleHistoryBack = useCallback(() => {
if (getNodesReadOnly())
return

const {
shortcutsDisabled,
} = workflowStore.getState()

if (shortcutsDisabled)
if (getNodesReadOnly() || getWorkflowReadOnly())
return

const { setEdges, setNodes } = store.getState()
Expand All @@ -1253,17 +1233,10 @@ export const useNodesInteractions = () => {

setEdges(edges)
setNodes(nodes)
}, [store, undo, workflowHistoryStore, workflowStore, getNodesReadOnly])
}, [store, undo, workflowHistoryStore, getNodesReadOnly, getWorkflowReadOnly])

const handleHistoryForward = useCallback(() => {
if (getNodesReadOnly())
return

const {
shortcutsDisabled,
} = workflowStore.getState()

if (shortcutsDisabled)
if (getNodesReadOnly() || getWorkflowReadOnly())
return

const { setEdges, setNodes } = store.getState()
Expand All @@ -1275,7 +1248,7 @@ export const useNodesInteractions = () => {

setEdges(edges)
setNodes(nodes)
}, [redo, store, workflowHistoryStore, workflowStore, getNodesReadOnly])
}, [redo, store, workflowHistoryStore, getNodesReadOnly, getWorkflowReadOnly])

return {
handleNodeDragStart,
Expand Down
4 changes: 3 additions & 1 deletion web/app/components/workflow/hooks/use-nodes-sync-draft.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ import {
} from '../store'
import { BlockEnum } from '../types'
import { useWorkflowUpdate } from '../hooks'
import { useNodesReadOnly } from './use-workflow'
import {
useNodesReadOnly,
} from './use-workflow'
import { syncWorkflowDraft } from '@/service/workflow'
import { useFeaturesStore } from '@/app/components/base/features/hooks'
import { API_PREFIX } from '@/config'
Expand Down
186 changes: 186 additions & 0 deletions web/app/components/workflow/hooks/use-shortcuts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
import { useReactFlow } from 'reactflow'
import { useKeyPress } from 'ahooks'
import { useCallback } from 'react'
import {
getKeyboardKeyCodeBySystem,
isEventTargetInputArea,
} from '../utils'
import { useWorkflowHistoryStore } from '../workflow-history-store'
import { useWorkflowStore } from '../store'
import {
useEdgesInteractions,
useNodesInteractions,
useNodesSyncDraft,
useWorkflowMoveMode,
useWorkflowOrganize,
useWorkflowStartRun,
} from '.'

export const useShortcuts = (): void => {
const {
handleNodesCopy,
handleNodesPaste,
handleNodesDuplicate,
handleNodesDelete,
handleHistoryBack,
handleHistoryForward,
} = useNodesInteractions()
const { handleStartWorkflowRun } = useWorkflowStartRun()
const { shortcutsEnabled: workflowHistoryShortcutsEnabled } = useWorkflowHistoryStore()
const { handleSyncWorkflowDraft } = useNodesSyncDraft()
const { handleEdgeDelete } = useEdgesInteractions()
const workflowStore = useWorkflowStore()
const {
handleModeHand,
handleModePointer,
} = useWorkflowMoveMode()
const { handleLayout } = useWorkflowOrganize()

const {
zoomIn,
zoomOut,
zoomTo,
fitView,
} = useReactFlow()

const shouldHandleShortcut = useCallback((e: KeyboardEvent) => {
const { showFeaturesPanel } = workflowStore.getState()
return !showFeaturesPanel && !isEventTargetInputArea(e.target as HTMLElement)
}, [workflowStore])

useKeyPress(['delete', 'backspace'], (e) => {
if (shouldHandleShortcut(e)) {
e.preventDefault()
handleNodesDelete()
handleEdgeDelete()
}
})

useKeyPress(`${getKeyboardKeyCodeBySystem('ctrl')}.c`, (e) => {
if (shouldHandleShortcut(e)) {
e.preventDefault()
handleNodesCopy()
}
}, { exactMatch: true, useCapture: true })

useKeyPress(`${getKeyboardKeyCodeBySystem('ctrl')}.v`, (e) => {
if (shouldHandleShortcut(e)) {
e.preventDefault()
handleNodesPaste()
}
}, { exactMatch: true, useCapture: true })

useKeyPress(`${getKeyboardKeyCodeBySystem('ctrl')}.d`, (e) => {
if (shouldHandleShortcut(e)) {
e.preventDefault()
handleNodesDuplicate()
}
}, { exactMatch: true, useCapture: true })

useKeyPress(`${getKeyboardKeyCodeBySystem('alt')}.r`, (e) => {
if (shouldHandleShortcut(e)) {
e.preventDefault()
handleStartWorkflowRun()
}
}, { exactMatch: true, useCapture: true })

useKeyPress(`${getKeyboardKeyCodeBySystem('ctrl')}.z`, (e) => {
if (shouldHandleShortcut(e)) {
e.preventDefault()
workflowHistoryShortcutsEnabled && handleHistoryBack()
}
}, { exactMatch: true, useCapture: true })

useKeyPress(
[`${getKeyboardKeyCodeBySystem('ctrl')}.y`, `${getKeyboardKeyCodeBySystem('ctrl')}.shift.z`],
(e) => {
if (shouldHandleShortcut(e)) {
e.preventDefault()
workflowHistoryShortcutsEnabled && handleHistoryForward()
}
},
{ exactMatch: true, useCapture: true },
)

useKeyPress('h', (e) => {
if (shouldHandleShortcut(e)) {
e.preventDefault()
handleModeHand()
}
}, {
exactMatch: true,
useCapture: true,
})

useKeyPress('v', (e) => {
if (shouldHandleShortcut(e)) {
e.preventDefault()
handleModePointer()
}
}, {
exactMatch: true,
useCapture: true,
})

useKeyPress(`${getKeyboardKeyCodeBySystem('ctrl')}.o`, (e) => {
if (shouldHandleShortcut(e)) {
e.preventDefault()
handleLayout()
}
}, { exactMatch: true, useCapture: true })

useKeyPress(`${getKeyboardKeyCodeBySystem('ctrl')}.1`, (e) => {
if (shouldHandleShortcut(e)) {
e.preventDefault()
fitView()
handleSyncWorkflowDraft()
}
}, {
exactMatch: true,
useCapture: true,
})

useKeyPress('shift.1', (e) => {
if (shouldHandleShortcut(e)) {
e.preventDefault()
zoomTo(1)
handleSyncWorkflowDraft()
}
}, {
exactMatch: true,
useCapture: true,
})

useKeyPress('shift.5', (e) => {
if (shouldHandleShortcut(e)) {
e.preventDefault()
zoomTo(0.5)
handleSyncWorkflowDraft()
}
}, {
exactMatch: true,
useCapture: true,
})

useKeyPress(`${getKeyboardKeyCodeBySystem('ctrl')}.dash`, (e) => {
if (shouldHandleShortcut(e)) {
e.preventDefault()
zoomOut()
handleSyncWorkflowDraft()
}
}, {
exactMatch: true,
useCapture: true,
})

useKeyPress(`${getKeyboardKeyCodeBySystem('ctrl')}.equalsign`, (e) => {
if (shouldHandleShortcut(e)) {
e.preventDefault()
zoomIn()
handleSyncWorkflowDraft()
}
}, {
exactMatch: true,
useCapture: true,
})
}
Loading

0 comments on commit 8b06105

Please sign in to comment.