Browse Source

fix: outputGallery video handle mismatch and mediaStorage ref/data sync

- Add "video" to outputGallery inputs in getNodeHandles() to match the
  component's rendered handles and isValidConnection logic
- Guard against undefined images/videos arrays in dehydration
- Keep imageRefs/videoRefs in sync when filtering empty entries after
  hydration, preventing index misalignment

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
handoff-20260429-1057
shrimbly 3 months ago
parent
commit
cd7209efe5
  1. 2
      src/components/WorkflowCanvas.tsx
  2. 30
      src/utils/mediaStorage.ts

2
src/components/WorkflowCanvas.tsx

@ -168,7 +168,7 @@ const getNodeHandles = (nodeType: string): { inputs: string[]; outputs: string[]
case "output": case "output":
return { inputs: ["image", "video", "audio"], outputs: [] }; return { inputs: ["image", "video", "audio"], outputs: [] };
case "outputGallery": case "outputGallery":
return { inputs: ["image"], outputs: [] }; return { inputs: ["image", "video"], outputs: [] };
case "imageCompare": case "imageCompare":
return { inputs: ["image"], outputs: [] }; return { inputs: ["image"], outputs: [] };
case "videoStitch": case "videoStitch":

30
src/utils/mediaStorage.ts

@ -469,10 +469,10 @@ async function externalizeNodeMedia(
} }
// Build cleaned arrays: clear base64 data where refs exist, keep HTTP URLs // Build cleaned arrays: clear base64 data where refs exist, keep HTTP URLs
const cleanedImages = d.images.map((img, i) => const cleanedImages = (d.images || []).map((img, i) =>
galleryImageRefs[i] && isDataUrl(img) ? "" : img galleryImageRefs[i] && isDataUrl(img) ? "" : img
); );
const cleanedVideos = d.videos.map((vid, i) => const cleanedVideos = (d.videos || []).map((vid, i) =>
galleryVideoRefs[i] && isDataUrl(vid) ? "" : vid galleryVideoRefs[i] && isDataUrl(vid) ? "" : vid
); );
@ -1062,11 +1062,31 @@ async function hydrateNodeMedia(
} }
} }
// Filter out any empty entries that failed to hydrate // Filter out any empty entries that failed to hydrate, keeping refs in sync
const filteredImages: string[] = [];
const filteredImageRefs: string[] = [];
for (let i = 0; i < images.length; i++) {
if (images[i] && images[i] !== "") {
filteredImages.push(images[i]);
if (d.imageRefs?.[i]) filteredImageRefs.push(d.imageRefs[i]);
else filteredImageRefs.push("");
}
}
const filteredVideos: string[] = [];
const filteredVideoRefs: string[] = [];
for (let i = 0; i < videos.length; i++) {
if (videos[i] && videos[i] !== "") {
filteredVideos.push(videos[i]);
if (d.videoRefs?.[i]) filteredVideoRefs.push(d.videoRefs[i]);
else filteredVideoRefs.push("");
}
}
newData = { newData = {
...d, ...d,
images: images.filter(img => img && img !== ""), images: filteredImages,
videos: videos.filter(vid => vid && vid !== ""), imageRefs: filteredImageRefs.some(r => r !== "") ? filteredImageRefs : d.imageRefs,
videos: filteredVideos,
videoRefs: filteredVideoRefs.some(r => r !== "") ? filteredVideoRefs : d.videoRefs,
}; };
break; break;
} }

Loading…
Cancel
Save