Skip to content
Open
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
b59950f
feat: enhance workflow component with viewport visibility management …
ZeroZ-lab Oct 29, 2025
3535a4c
feat: implement node dragging enhancements with visual feedback and p…
ZeroZ-lab Oct 29, 2025
9e6e96f
feat: enhance node dragging functionality to support multiple nodes a…
ZeroZ-lab Oct 29, 2025
f81f148
feat: enhance node drag handling to set help line visibility when dra…
ZeroZ-lab Oct 29, 2025
3eba2ea
feat: filter out hidden nodes in helpline calculations for improved v…
ZeroZ-lab Oct 29, 2025
0c256a9
Merge branch 'main' into fix-workflow-performance
ZeroZ-lab Oct 29, 2025
f340032
Merge branch 'main' into fix-workflow-performance
ZeroZ-lab Oct 29, 2025
adb58ed
Merge branch 'main' into fix-workflow-performance
ZeroZ-lab Oct 29, 2025
bc3d649
feat: enhance node dragging interactions and add tools fetching funct…
ZeroZ-lab Oct 29, 2025
d6fc58f
Merge branch 'main' into fix-workflow-performance
ZeroZ-lab Oct 29, 2025
ee31bc3
Merge branch 'main' into fix-workflow-performance
ZeroZ-lab Oct 29, 2025
60b8e0d
Merge branch 'main' into fix-workflow-performance
ZeroZ-lab Oct 29, 2025
ee7d52a
fix: update node drag handlers to include nodes parameter
ZeroZ-lab Oct 29, 2025
947e665
refactor: simplify node IDs collection for movement logic
ZeroZ-lab Oct 29, 2025
ae10ffc
refactor: enhance helpline and node interactions with visible node ID…
ZeroZ-lab Oct 29, 2025
03dbf85
Merge branch 'main' into fix-workflow-performance
ZeroZ-lab Oct 30, 2025
4ab944a
Merge branch 'fix-workflow-performance' of https://github.com/ZeroZ-l…
ZeroZ-lab Oct 30, 2025
4361538
Merge branch 'main' into fix-workflow-performance
ZeroZ-lab Oct 30, 2025
c16861c
fix(workflow): streamline node interaction logic by removing redundan…
ZeroZ-lab Oct 30, 2025
746ad0c
Merge branch 'fix-workflow-performance' of https://github.com/ZeroZ-l…
ZeroZ-lab Oct 30, 2025
e3098ca
Merge branch 'main' into fix-workflow-performance
ZeroZ-lab Oct 31, 2025
f568130
Merge branch 'main' into fix-workflow-performance
ZeroZ-lab Nov 3, 2025
54b9540
Merge branch 'main' into fix-workflow-performance
ZeroZ-lab Nov 11, 2025
40d559c
Merge remote-tracking branch 'origin/main' into fix-workflow-performance
ZeroZ-lab Nov 13, 2025
cf641dd
Merge upstream/main
ZeroZ-lab Nov 13, 2025
2ed51e2
Merge branch 'main' into fix-workflow-performance
ZeroZ-lab Nov 13, 2025
b6c7ca0
Merge branch 'main' into fix-workflow-performance
ZeroZ-lab Nov 13, 2025
e0ad7e2
Merge branch 'main' into fix-workflow-performance
ZeroZ-lab Nov 17, 2025
d786033
Merge branch 'main' into fix-workflow-performance
ZeroZ-lab Nov 18, 2025
7772944
Merge branch 'main' into fix-workflow-performance
ZeroZ-lab Nov 25, 2025
c7cae88
Merge branch 'main' into fix-workflow-performance
ZeroZ-lab Nov 26, 2025
5f253f7
Merge branch 'main' into fix-workflow-performance
ZeroZ-lab Nov 27, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions web/app/components/workflow/hooks/use-helpline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ export const useHelpline = () => {
}

const showHorizontalHelpLineNodes = nodes.filter((n) => {
if (n.hidden)
return false
if (n.id === node.id)
return false

Expand Down Expand Up @@ -74,6 +76,8 @@ export const useHelpline = () => {
}

const showVerticalHelpLineNodes = nodes.filter((n) => {
if (n.hidden)
return false
if (n.id === node.id)
return false
if (n.data.isInIteration)
Expand Down
132 changes: 96 additions & 36 deletions web/app/components/workflow/hooks/use-nodes-interactions.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import type { MouseEvent } from 'react'
import { useCallback, useRef, useState } from 'react'
import {
useCallback,
useEffect,
useRef,
useState,
} from 'react'
import { useTranslation } from 'react-i18next'
import { produce } from 'immer'
import type {
Expand Down Expand Up @@ -82,6 +87,8 @@ export const useNodesInteractions = () => {
x: number;
y: number;
})
const dragAnimationFrameRef = useRef<number | null>(null)
const pendingDragNodesRef = useRef<Map<string, Node>>(new Map())
const { nodesMap: nodesMetaDataMap } = useNodesMetaData()

const { saveStateToHistory, undo, redo } = useWorkflowHistory()
Expand Down Expand Up @@ -112,56 +119,92 @@ export const useNodesInteractions = () => {
[workflowStore, getNodesReadOnly],
)

const handleNodeDrag = useCallback<NodeDragHandler>(
(e, node: Node) => {
if (getNodesReadOnly()) return

if (node.type === CUSTOM_ITERATION_START_NODE) return

if (node.type === CUSTOM_LOOP_START_NODE) return
useEffect(() => {
return () => {
if (dragAnimationFrameRef.current !== null)
cancelAnimationFrame(dragAnimationFrameRef.current)
pendingDragNodesRef.current.clear()
}
}, [])

const { getNodes, setNodes } = store.getState()
e.stopPropagation()
const applyNodeDragPosition = useCallback((pendingNodes: Node[]) => {
if (!pendingNodes.length)
return

const nodes = getNodes()
const { getNodes, setNodes } = store.getState()
const nodes = getNodes()

const { restrictPosition } = handleNodeIterationChildDrag(node)
const { restrictPosition: restrictLoopPosition }
= handleNodeLoopChildDrag(node)
const newNodes = produce(nodes, (draft) => {
pendingNodes.forEach((pendingNode) => {
const currentNode = draft.find(n => n.id === pendingNode.id)
if (!currentNode)
return

const { showHorizontalHelpLineNodes, showVerticalHelpLineNodes }
= handleSetHelpline(node)
const showHorizontalHelpLineNodesLength
= showHorizontalHelpLineNodes.length
const showVerticalHelpLineNodesLength = showVerticalHelpLineNodes.length
const { restrictPosition } = handleNodeIterationChildDrag(pendingNode)
const { restrictPosition: restrictLoopPosition }
= handleNodeLoopChildDrag(pendingNode)

const newNodes = produce(nodes, (draft) => {
const currentNode = draft.find(n => n.id === node.id)!
const { showHorizontalHelpLineNodes, showVerticalHelpLineNodes }
= handleSetHelpline(pendingNode)
const showHorizontalHelpLineNodesLength
= showHorizontalHelpLineNodes.length
const showVerticalHelpLineNodesLength = showVerticalHelpLineNodes.length

if (showVerticalHelpLineNodesLength > 0)
currentNode.position.x = showVerticalHelpLineNodes[0].position.x
else if (restrictPosition.x !== undefined)
currentNode.position.x = restrictPosition.x
else if (restrictLoopPosition.x !== undefined)
currentNode.position.x = restrictLoopPosition.x
else currentNode.position.x = node.position.x
else
currentNode.position.x = pendingNode.position.x

if (showHorizontalHelpLineNodesLength > 0)
currentNode.position.y = showHorizontalHelpLineNodes[0].position.y
else if (restrictPosition.y !== undefined)
currentNode.position.y = restrictPosition.y
else if (restrictLoopPosition.y !== undefined)
currentNode.position.y = restrictLoopPosition.y
else currentNode.position.y = node.position.y
else
currentNode.position.y = pendingNode.position.y
})
})
setNodes(newNodes)
}, [
store,
handleNodeIterationChildDrag,
handleNodeLoopChildDrag,
handleSetHelpline,
])

const handleNodeDrag = useCallback<NodeDragHandler>(
(e, node: Node) => {
if (getNodesReadOnly()) return

if (node.type === CUSTOM_ITERATION_START_NODE) return

if (node.type === CUSTOM_LOOP_START_NODE) return

e.stopPropagation()

pendingDragNodesRef.current.set(node.id, node)

if (dragAnimationFrameRef.current !== null)
return

dragAnimationFrameRef.current = requestAnimationFrame(() => {
dragAnimationFrameRef.current = null
if (!pendingDragNodesRef.current.size)
return

const pendingNodes = Array.from(pendingDragNodesRef.current.values())
pendingDragNodesRef.current.clear()
applyNodeDragPosition(pendingNodes)
})
setNodes(newNodes)
},
[
getNodesReadOnly,
store,
handleNodeIterationChildDrag,
handleNodeLoopChildDrag,
handleSetHelpline,
applyNodeDragPosition,
],
)

Expand All @@ -172,25 +215,42 @@ export const useNodesInteractions = () => {

if (getNodesReadOnly()) return

if (dragAnimationFrameRef.current !== null) {
cancelAnimationFrame(dragAnimationFrameRef.current)
dragAnimationFrameRef.current = null
}
const pendingNodes = pendingDragNodesRef.current.size
? Array.from(pendingDragNodesRef.current.values())
: []
pendingDragNodesRef.current.clear()
const { x, y } = dragNodeStartPosition.current
if (!(x === node.position.x && y === node.position.y)) {
const hasMoved = !(x === node.position.x && y === node.position.y)
if (!hasMoved) {
setHelpLineHorizontal()
setHelpLineVertical()
handleSyncWorkflowDraft()
return
}
if (!pendingNodes.some(pendingNode => pendingNode.id === node.id))
pendingNodes.push(node)
applyNodeDragPosition(pendingNodes)

if (x !== 0 && y !== 0) {
// selecting a note will trigger a drag stop event with x and y as 0
saveStateToHistory(WorkflowHistoryEvent.NodeDragStop, {
nodeId: node.id,
})
}
setHelpLineHorizontal()
setHelpLineVertical()
handleSyncWorkflowDraft()

if (x !== 0 && y !== 0) {
// selecting a note will trigger a drag stop event with x and y as 0
saveStateToHistory(WorkflowHistoryEvent.NodeDragStop, {
nodeId: node.id,
})
}
},
[
workflowStore,
getNodesReadOnly,
saveStateToHistory,
handleSyncWorkflowDraft,
applyNodeDragPosition,
],
)

Expand Down
Loading
Loading