feat: performance 1

This commit is contained in:
2026-03-12 18:01:27 +01:00
parent 4bd2f1b458
commit 923bf4bff0
18 changed files with 404 additions and 146 deletions

View File

@@ -23,7 +23,11 @@ import {
type EdgeChange,
} from '@xyflow/react'
import { AnimatedEdge } from '@/components/graph/AnimatedEdge'
import FlowContext from '@/lib/graph/flowContext'
import {
GraphContext,
ConnectionPathContext,
FlowUIContext,
} from '@/lib/graph/flowContext'
import { useTheme } from '@/lib/themeContext'
import { usePlatform } from '@/app/kosmos/KosmosContext'
import { useCanvasGraph } from '@/app/canvas/useCanvasGraph'
@@ -55,6 +59,7 @@ import {
getRegisteredNodeTypeIds,
getDefaultStyle,
getNodeType,
getConnectionLabelForTarget,
isConnectionAllowed,
} from '@/lib/graph/nodeRegistry'
import type { AppNode, AppEdge } from '@/lib/graph/nodeTypes'
@@ -388,20 +393,12 @@ export function CanvasPage({ projectId }: CanvasPageProps) {
flowActionsRef.current?.pasteAtViewportCenter?.()
}, [])
const flowContextValue = useMemo(
const graphContextValue = useMemo(
() => ({ nodes, setNodes, edges, setEdges }),
[nodes, setNodes, edges, setEdges]
)
const connectionPathContextValue = useMemo(
() => ({
nodes,
setNodes,
edges,
setEdges,
renamingNodeId,
setRenamingNodeId,
connectionFrom,
setConnectionFrom,
isValidConnection,
flowActionsRef,
fullscreenNodeId,
setFullscreenNodeId,
connectionPathUpdatingNodeIds: connectionPath.connectionPathUpdatingNodeIds,
connectionPathTriggerNodeIds: connectionPath.connectionPathTriggerNodeIds,
addConnectionPathTrigger: connectionPath.addConnectionPathTrigger,
@@ -417,11 +414,20 @@ export function CanvasPage({ projectId }: CanvasPageProps) {
startConnectionPathUpdate: connectionPath.startConnectionPathUpdate,
endConnectionPathUpdate: connectionPath.endConnectionPathUpdate,
}),
[
nodes,
setNodes,
edges,
setEdges,
[connectionPath]
)
const flowUIContextValue = useMemo(
() => ({
renamingNodeId,
setRenamingNodeId,
connectionFrom,
setConnectionFrom,
isValidConnection,
flowActionsRef,
fullscreenNodeId,
setFullscreenNodeId,
}),
[
renamingNodeId,
setRenamingNodeId,
connectionFrom,
@@ -430,10 +436,32 @@ export function CanvasPage({ projectId }: CanvasPageProps) {
flowActionsRef,
fullscreenNodeId,
setFullscreenNodeId,
connectionPath,
]
)
const nodesForFlow = useMemo(
() =>
nodes.map((n) => ({
...n,
className: [n.className, 'nowheel'].filter(Boolean).join(' '),
})),
[nodes]
)
const edgesForFlow = useMemo(
() =>
edges.map((e) => {
const targetType = nodes.find((nd) => nd.id === e.target)?.type ?? ''
const connectionLabel = getConnectionLabelForTarget(targetType)
const baseData =
typeof e.data === 'object' && e.data !== null ? (e.data as Record<string, unknown>) : {}
return {
...e,
data: { ...baseData, connectionLabel },
}
}),
[edges, nodes]
)
const onContextMenuCapture = useCallback((ev: React.MouseEvent) => {
const target = ev.target as HTMLElement
if (target.closest('.react-flow__node')) {
@@ -586,7 +614,9 @@ export function CanvasPage({ projectId }: CanvasPageProps) {
)}
<div className="flex-1 min-h-0 relative flex flex-col">
<div className="flex-1 min-h-0 flex flex-col">
<FlowContext.Provider value={flowContextValue}>
<GraphContext.Provider value={graphContextValue}>
<ConnectionPathContext.Provider value={connectionPathContextValue}>
<FlowUIContext.Provider value={flowUIContextValue}>
<ContextMenu>
<ContextMenuTrigger asChild>
<div
@@ -629,11 +659,8 @@ export function CanvasPage({ projectId }: CanvasPageProps) {
<FlowKeyboardShortcuts />
<ReactFlow
className={isPanning ? 'react-flow--panning' : isSelecting ? 'react-flow--selecting' : undefined}
nodes={nodes.map((n) => ({
...n,
className: [n.className, 'nowheel'].filter(Boolean).join(' '),
}))}
edges={edges}
nodes={nodesForFlow}
edges={edgesForFlow}
onNodesChange={onNodesChange}
onEdgesChange={onEdgesChange}
onConnect={onConnect}
@@ -689,7 +716,9 @@ export function CanvasPage({ projectId }: CanvasPageProps) {
onClose={() => setFullscreenNodeId(null)}
/>
)}
</FlowContext.Provider>
</FlowUIContext.Provider>
</ConnectionPathContext.Provider>
</GraphContext.Provider>
</div>
</div>
</div>