Browse Source

Merge remote-tracking branch 'origin/develop' into claude/investigate-windows-performance-IoR9j

handoff-20260429-1057
Claude 4 months ago
parent
commit
84ec0b9943
Failed to extract signature
  1. 4
      src/components/__tests__/SplitGridNode.test.tsx
  2. 23
      src/components/nodes/SplitGridNode.tsx
  3. 4
      src/store/execution/splitGridExecutor.ts
  4. 13
      src/store/utils/connectedInputs.ts

4
src/components/__tests__/SplitGridNode.test.tsx

@ -51,6 +51,8 @@ describe("SplitGridNode", () => {
currentNodeIds: [],
groups: {},
nodes: [],
edges: [],
getConnectedInputs: vi.fn(() => ({ images: [], videos: [], audio: [], model3d: null, text: null, dynamicInputs: {}, easeCurve: null })),
getNodesWithComments: vi.fn(() => []),
markCommentViewed: vi.fn(),
setNavigationTarget: vi.fn(),
@ -273,6 +275,8 @@ describe("SplitGridNode", () => {
currentNodeIds: [],
groups: {},
nodes: [],
edges: [],
getConnectedInputs: vi.fn(() => ({ images: [], videos: [], audio: [], model3d: null, text: null, dynamicInputs: {}, easeCurve: null })),
getNodesWithComments: vi.fn(() => []),
markCommentViewed: vi.fn(),
setNavigationTarget: vi.fn(),

23
src/components/nodes/SplitGridNode.tsx

@ -1,6 +1,6 @@
"use client";
import { useCallback, useState, useEffect } from "react";
import { useCallback, useState, useEffect, useMemo } from "react";
import { Handle, Position, NodeProps, Node } from "@xyflow/react";
import { BaseNode } from "./BaseNode";
import { useWorkflowStore } from "@/store/workflowStore";
@ -16,8 +16,29 @@ export function SplitGridNode({ id, data, selected }: NodeProps<SplitGridNodeTyp
const updateNodeData = useWorkflowStore((state) => state.updateNodeData);
const regenerateNode = useWorkflowStore((state) => state.regenerateNode);
const isRunning = useWorkflowStore((state) => state.isRunning);
const getConnectedInputs = useWorkflowStore((state) => state.getConnectedInputs);
const edges = useWorkflowStore((state) => state.edges);
const nodes = useWorkflowStore((state) => state.nodes);
const [showSettings, setShowSettings] = useState(false);
// Reactively track the connected source image
const hasIncomingImageConnection = useMemo(() => {
return edges.some((edge) => edge.target === id && edge.targetHandle === "image");
}, [edges, id]);
const connectedSourceImage = useMemo(() => {
if (!hasIncomingImageConnection) return null;
const { images } = getConnectedInputs(id);
return images[0] || null;
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [hasIncomingImageConnection, id, getConnectedInputs, nodes]);
useEffect(() => {
if (connectedSourceImage !== nodeData.sourceImage) {
updateNodeData(id, { sourceImage: connectedSourceImage });
}
}, [connectedSourceImage, id, updateNodeData, nodeData.sourceImage]);
// Show settings modal on first creation (when not configured)
useEffect(() => {
if (!nodeData.isConfigured && (!nodeData.childNodeIds || nodeData.childNodeIds.length === 0)) {

4
src/store/execution/splitGridExecutor.ts

@ -11,8 +11,8 @@ import type { NodeExecutionContext } from "./types";
export async function executeSplitGrid(ctx: NodeExecutionContext): Promise<void> {
const { node, getConnectedInputs, updateNodeData } = ctx;
const { images } = getConnectedInputs(node.id);
const sourceImage = images[0] || null;
const connectedInputs = getConnectedInputs(node.id);
const sourceImage = connectedInputs.images[0] || null;
if (!sourceImage) {
updateNodeData(node.id, {

13
src/store/utils/connectedInputs.ts

@ -166,6 +166,11 @@ export function getConnectedInputsPure(
});
}
// Cache passthrough node results so multiple edges from the same router/switch
// all receive correct data (the _visited set prevents re-traversal, so we cache
// the result from the first traversal and reuse it for subsequent edges).
const passthroughCache = new Map<string, ConnectedInputs>();
edges
.filter((edge) => edge.target === nodeId)
.forEach((edge) => {
@ -177,7 +182,9 @@ export function getConnectedInputsPure(
// Router passthrough — traverse upstream to find actual data source
if (sourceNode.type === "router") {
const routerInputs = getConnectedInputsPure(sourceNode.id, nodes, edges, _visited, dimmedNodeIds);
const routerInputs = passthroughCache.get(sourceNode.id)
?? getConnectedInputsPure(sourceNode.id, nodes, edges, _visited, dimmedNodeIds);
passthroughCache.set(sourceNode.id, routerInputs);
// Determine which type this edge carries based on the source handle
const edgeType = edge.sourceHandle; // Will be "image", "text", "video", "audio", "3d", or "easeCurve"
@ -210,7 +217,9 @@ export function getConnectedInputsPure(
}
// Enabled switch: recursively get upstream data (same pattern as router)
const switchInputs = getConnectedInputsPure(sourceNode.id, nodes, edges, _visited, dimmedNodeIds);
const switchInputs = passthroughCache.get(sourceNode.id)
?? getConnectedInputsPure(sourceNode.id, nodes, edges, _visited, dimmedNodeIds);
passthroughCache.set(sourceNode.id, switchInputs);
const edgeType = switchData.inputType;
if (edgeType === "image") {

Loading…
Cancel
Save