Simplify canvas connection rendering

This commit is contained in:
Codex
2026-05-11 22:52:31 +08:00
parent 1f721b62b1
commit 5de0e462f0

View File

@@ -6,7 +6,6 @@ import {
ConnectionLineType,
Controls,
Handle,
MarkerType,
MiniMap,
Position,
ReactFlow,
@@ -100,7 +99,6 @@ const SNAP_GRID: [number, number] = [20, 20];
const MULTI_SELECTION_KEYS = ['Meta', 'Control', 'Shift'];
const FLOW_FIT_VIEW_OPTIONS = { padding: 0.2 };
const CANVAS_NODE_TYPES = { canvasNode: CanvasNodeCard };
const CANVAS_EDGE_CLASS_NAME = 'canvas-flow-edge';
const NODE_TYPE_META: Record<CanvasNode['type'], { label: string; accent: string; bg: string }> = {
text: { label: 'TEXT', accent: '#2563eb', bg: 'rgba(37, 99, 235, 0.1)' },
image: { label: 'ASSET', accent: '#2563eb', bg: 'rgba(37, 99, 235, 0.1)' },
@@ -786,30 +784,16 @@ function CanvasConnectionOverlay({
}}
aria-hidden="true"
>
<defs>
<marker
id="canvas-connection-arrow"
markerWidth="12"
markerHeight="12"
refX="10"
refY="6"
orient="auto"
markerUnits="strokeWidth"
>
<path d="M 2 2 L 10 6 L 2 10 z" fill={edgeStroke} />
</marker>
</defs>
{visibleConnections.map(({ connection, source, target }) => (
<path
key={connection.id}
d={buildConnectionPath(source, target, viewport)}
fill="none"
stroke={edgeStroke}
strokeWidth={3}
strokeWidth={2}
strokeLinecap="round"
strokeLinejoin="round"
markerEnd="url(#canvas-connection-arrow)"
opacity={0.95}
opacity={0.72}
/>
))}
</svg>
@@ -853,10 +837,9 @@ function FlowCanvasInner({
const movingRef = useRef(false);
const paneClickTimerRef = useRef<number | null>(null);
const isDarkTheme = resolvedTheme === 'dark';
const edgeStroke = isDarkTheme ? 'rgba(255, 255, 255, 0.82)' : 'rgba(120, 64, 16, 0.72)';
const edgeStroke = isDarkTheme ? 'rgba(255, 255, 255, 0.52)' : 'rgba(126, 76, 28, 0.56)';
const dotColor = isDarkTheme ? 'rgb(255 255 255 / 0.42)' : 'hsl(var(--foreground) / 0.16)';
const dotAccentColor = isDarkTheme ? 'rgb(255 255 255 / 0.24)' : 'hsl(var(--primary) / 0.28)';
const edgeZIndex = useMemo(() => Math.max(1, ...nodes.map(node => node.zIndex)) + 20, [nodes]);
const incomingNodes = useMemo<CanvasFlowNode[]>(() => nodes.map(node => ({
id: node.id,
@@ -897,32 +880,6 @@ function FlowCanvasInner({
})), [connectingFromId, connections, editable, imageModelOptions, layerCanvasSize, layerColors, nodes, onConnect, onCreateVariationNode, onDownloadNode, onPreviewNode, onRemoveConnection, onRunDownstreamNode, onRunNode, onSelectNode, onStartConnect, onUpdateNode, selectedNodeIds, textModelOptions]);
const [flowNodes, setFlowNodes] = useState<CanvasFlowNode[]>(incomingNodes);
const [localEdges, setLocalEdges] = useState<Edge[]>([]);
const flowEdges = useMemo<Edge[]>(() => connections.map((connection) => ({
id: connection.id,
source: connection.sourceNodeId,
target: connection.targetNodeId,
sourceHandle: 'output',
targetHandle: 'input',
type: 'smoothstep',
markerEnd: { type: MarkerType.ArrowClosed, color: edgeStroke },
className: CANVAS_EDGE_CLASS_NAME,
zIndex: edgeZIndex,
style: {
stroke: edgeStroke,
strokeWidth: 3,
},
interactionWidth: 24,
})), [connections, edgeStroke, edgeZIndex]);
const visibleEdges = useMemo(() => {
const realIds = new Set(flowEdges.map(edge => edge.id));
return [...flowEdges, ...localEdges.filter(edge => !realIds.has(edge.id))];
}, [flowEdges, localEdges]);
useEffect(() => {
setLocalEdges([]);
}, [connections]);
useEffect(() => {
setFlowNodes(current => {
@@ -996,27 +953,8 @@ function FlowCanvasInner({
const handleConnect = useCallback((connection: Connection) => {
if (!connection.source || !connection.target) return;
const edgeId = `pending-${connection.source}-${connection.target}`;
setLocalEdges(current => current.some(edge => edge.source === connection.source && edge.target === connection.target)
? current
: [
...current,
{
id: edgeId,
source: connection.source || '',
target: connection.target || '',
sourceHandle: connection.sourceHandle || 'output',
targetHandle: connection.targetHandle || 'input',
type: 'smoothstep',
markerEnd: { type: MarkerType.ArrowClosed, color: edgeStroke },
className: CANVAS_EDGE_CLASS_NAME,
zIndex: edgeZIndex,
style: { stroke: edgeStroke, strokeWidth: 3 },
interactionWidth: 24,
},
]);
onConnect(connection.source, connection.target);
}, [edgeStroke, edgeZIndex, onConnect]);
}, [onConnect]);
const handleMoveEnd = useCallback((_event: MouseEvent | TouchEvent | null, nextViewport: FlowViewport) => {
if (!movingRef.current) return;
@@ -1079,7 +1017,7 @@ function FlowCanvasInner({
<ReactFlow
className="canvas-flow h-full w-full"
nodes={flowNodes}
edges={visibleEdges}
edges={[]}
nodeTypes={CANVAS_NODE_TYPES}
minZoom={minZoom}
maxZoom={maxZoom}
@@ -1114,23 +1052,9 @@ function FlowCanvasInner({
<Background gap={20} size={1.15} color={dotColor} />
<Background gap={100} size={1.8} color={dotAccentColor} />
<style jsx global>{`
.canvas-flow .react-flow__edges {
z-index: ${edgeZIndex};
}
.canvas-flow .canvas-flow-edge .react-flow__edge-path {
stroke: ${edgeStroke};
stroke-width: 3px;
opacity: 1;
}
.canvas-flow .canvas-flow-edge .react-flow__edge-interaction {
stroke-width: 24px;
}
.canvas-flow .react-flow__connection-path {
stroke: ${edgeStroke};
stroke-width: 3px;
stroke-width: 2px;
opacity: 1;
}
`}</style>