Skip to content

Commit 1e7f85c

Browse files
committed
perf: node fold hook
1 parent 78c234b commit 1e7f85c

File tree

6 files changed

+58
-27
lines changed

6 files changed

+58
-27
lines changed

projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/components/ButtonEdge.tsx

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
import React, { useCallback, useMemo } from 'react';
1+
import React, { useCallback, useMemo, useState } from 'react';
22
import { BezierEdge, getBezierPath, EdgeLabelRenderer, EdgeProps } from 'reactflow';
33
import { Box, Flex } from '@chakra-ui/react';
44
import MyIcon from '@fastgpt/web/components/common/Icon';
55
import { NodeOutputKeyEnum, RuntimeEdgeStatusEnum } from '@fastgpt/global/core/workflow/constants';
66
import { useContextSelector } from 'use-context-selector';
77
import { WorkflowContext } from '../../context';
8+
import { useThrottleEffect } from 'ahooks';
89

910
const ButtonEdge = (props: EdgeProps) => {
1011
const { nodes, nodeList, setEdges, workflowDebugData, hoverEdgeId } = useContextSelector(
@@ -28,13 +29,11 @@ const ButtonEdge = (props: EdgeProps) => {
2829
style
2930
} = props;
3031

32+
// If parentNode is folded, the edge will not be displayed
3133
const parentNode = useMemo(() => {
32-
for (const node of nodeList) {
33-
if ((node.nodeId === source || node.nodeId === target) && node.parentNodeId) {
34-
return nodeList.find((parent) => parent.nodeId === node.parentNodeId);
35-
}
36-
}
37-
return undefined;
34+
return nodeList.find(
35+
(node) => (node.nodeId === source || node.nodeId === target) && node.parentNodeId
36+
);
3837
}, [nodeList, source, target]);
3938

4039
const defaultZIndex = useMemo(
@@ -52,12 +51,20 @@ const ButtonEdge = (props: EdgeProps) => {
5251
[setEdges]
5352
);
5453

55-
const highlightEdge = useMemo(() => {
56-
const connectNode = nodes.find((node) => {
57-
return node.selected && (node.id === props.source || node.id === props.target);
58-
});
59-
return !!(connectNode || selected);
60-
}, [nodes, props.source, props.target, selected]);
54+
// Selected edge or source/target node selected
55+
const [highlightEdge, setHighlightEdge] = useState(false);
56+
useThrottleEffect(
57+
() => {
58+
const connectNode = nodes.find((node) => {
59+
return node.selected && (node.id === props.source || node.id === props.target);
60+
});
61+
setHighlightEdge(!!connectNode || !!selected);
62+
},
63+
[nodes, selected, props.source, props.target],
64+
{
65+
wait: 100
66+
}
67+
);
6168

6269
const [, labelX, labelY] = getBezierPath({
6370
sourceX,

projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/components/FlowController.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { useTranslation } from 'next-i18next';
1717
import styles from './index.module.scss';
1818
import { maxZoom, minZoom } from '../index';
1919
import { useKeyPress } from 'ahooks';
20+
import { FlowNodeItemType } from '@fastgpt/global/core/workflow/type/node';
2021

2122
const buttonStyle = {
2223
border: 'none',
@@ -61,11 +62,16 @@ const FlowController = React.memo(function FlowController() {
6162
zoomOut();
6263
});
6364

65+
/*
66+
id: Render node id
67+
*/
6468
const MiniMapNode = useCallback(
6569
({ x, y, width, height, color, id }: MiniMapNodeProps) => {
70+
// If the node parentNode is folded, the child node will not be displayed
6671
const node = nodeList.find((node) => node.nodeId === id);
67-
const parentNode = nodeList.find((n) => n.nodeId === node?.parentNodeId);
68-
72+
const parentNode = node?.parentNodeId
73+
? nodeList.find((n) => n.nodeId === node?.parentNodeId)
74+
: undefined;
6975
if (parentNode?.isFolded) {
7076
return null;
7177
}

projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/hooks/useWorkflow.tsx

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,7 @@ export const useWorkflow = () => {
277277
const {
278278
setConnectingEdge,
279279
nodes,
280+
nodeList,
280281
onNodesChange,
281282
setEdges,
282283
onChangeNode,
@@ -370,10 +371,12 @@ export const useWorkflow = () => {
370371
const checkNodeOverLoopNode = useMemoizedFn((node: Node) => {
371372
if (!node) return;
372373

373-
// 获取所有与当前节点相交的节点,不包含折叠的节点
374-
const intersections = getIntersectingNodes(node).filter((node) => !node.data.isFolded);
375-
// 获取所有与当前节点相交的节点中,类型为 loop 的节点
376-
const parentNode = intersections.find((item) => item.type === FlowNodeTypeEnum.loop);
374+
// 获取所有与当前节点相交的节点
375+
const intersections = getIntersectingNodes(node);
376+
// 获取所有与当前节点相交的节点中,类型为 loop 的节点且它不能是折叠状态
377+
const parentNode = intersections.find(
378+
(item) => !item.data.isFolded && item.type === FlowNodeTypeEnum.loop
379+
);
377380

378381
const unSupportedTypes = [
379382
FlowNodeTypeEnum.workflowStart,
@@ -548,8 +551,10 @@ export const useWorkflow = () => {
548551
const onConnectStart = useCallback(
549552
(event: any, params: OnConnectStartParams) => {
550553
if (!params.nodeId) return;
551-
const sourceNode = nodes.find((node) => node.id === params.nodeId);
552-
if (sourceNode?.data.isFolded) {
554+
555+
// If node is folded, unfold it when connecting
556+
const sourceNode = nodeList.find((node) => node.nodeId === params.nodeId);
557+
if (sourceNode?.isFolded) {
553558
return onChangeNode({
554559
nodeId: params.nodeId,
555560
type: 'attr',
@@ -559,7 +564,7 @@ export const useWorkflow = () => {
559564
}
560565
setConnectingEdge(params);
561566
},
562-
[nodes, setConnectingEdge, onChangeNode]
567+
[nodeList, setConnectingEdge, onChangeNode]
563568
);
564569
const onConnectEnd = useCallback(() => {
565570
setConnectingEdge(undefined);

projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/Handle/ConnectionHandle.tsx

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,7 @@ export const ConnectionSourceHandle = ({
1313
nodeId: string;
1414
isFoldNode?: boolean;
1515
}) => {
16-
const connectingEdge = useContextSelector(WorkflowContext, (ctx) => ctx.connectingEdge);
17-
const nodeList = useContextSelector(WorkflowContext, (v) => v.nodeList);
18-
const edges = useContextSelector(WorkflowContext, (v) => v.edges);
16+
const { connectingEdge, nodeList, edges } = useContextSelector(WorkflowContext, (ctx) => ctx);
1917

2018
const { showSourceHandle, RightHandle, LeftHandlee, TopHandlee, BottomHandlee } = useMemo(() => {
2119
const node = nodeList.find((node) => node.nodeId === nodeId);
@@ -32,6 +30,15 @@ export const ConnectionSourceHandle = ({
3230
const rightTargetConnected = edges.some(
3331
(edge) => edge.targetHandle === getHandleId(nodeId, 'target', Position.Right)
3432
);
33+
34+
/*
35+
If the node is folded, must show the handle
36+
hide handle when:
37+
- not folded
38+
- not node
39+
- not sourceHandle
40+
- already connected
41+
*/
3542
if (!isFoldNode && (!node || !node?.sourceHandle?.right || rightTargetConnected)) return null;
3643

3744
return (

projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/NodeCard.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,9 +82,13 @@ const NodeCard = (props: Props) => {
8282
[isTool, nodeList]
8383
);
8484

85+
// Current node and parent node
8586
const { node, parentNode } = useMemo(() => {
8687
const node = nodeList.find((node) => node.nodeId === nodeId);
87-
const parentNode = nodeList.find((n) => n.nodeId === node?.parentNodeId);
88+
const parentNode = node?.parentNodeId
89+
? nodeList.find((n) => n.nodeId === node?.parentNodeId)
90+
: undefined;
91+
8892
return { node, parentNode };
8993
}, [nodeList, nodeId]);
9094

projects/app/src/pages/app/detail/components/WorkflowComponents/utils.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,12 @@ export const uiWorkflow2StoreWorkflow = ({
4848
.filter(
4949
// Filter out edges that do not have both sourceHandle and targetHandle
5050
(item) => {
51-
// Not in react flow page
5251
if (!reactFlowViewport) return true;
5352
const currentSourceNode = nodes.find((node) => node.data.nodeId === item.source);
53+
5454
if (currentSourceNode?.data.isFolded) return true;
55+
56+
// Not in react flow page
5557
return handleIdList.includes(item.sourceHandle) && handleIdList.includes(item.targetHandle);
5658
}
5759
);

0 commit comments

Comments
 (0)