import { isCanvasImageReadyForAi } from "@/lib/canvas/local-upload-state"; import type { CanvasNode } from "@/types/canvas"; export type LayoutReplaceSource = { id: string; imageUrl: string; kind: "canvas" | "upload"; nodeId?: string; title: string; }; function resolveCanvasImageUrl(node: CanvasNode) { const data = (node.data || {}) as Record; return String( data.src || data.previewImage || data.imageUrl || data.renderArtifacts?.screenshotUrl || "" ).trim(); } export function getLayoutReplaceSourceIdentity(source: LayoutReplaceSource) { if (source.kind === "canvas" && source.nodeId) { return `canvas:${source.nodeId}`; } return `${source.kind}:${source.imageUrl}`; } export function getReadyCanvasLayoutReplaceSource( node: CanvasNode ): LayoutReplaceSource | null { if (!isCanvasImageReadyForAi(node)) return null; const data = (node.data || {}) as Record; const imageUrl = resolveCanvasImageUrl(node); return { id: `canvas:${node.id}`, imageUrl, kind: "canvas", nodeId: node.id, title: String(data.title || "画布图片").trim() || "画布图片", }; } export function mergeUniqueLayoutReplaceSources( current: LayoutReplaceSource[], incoming: LayoutReplaceSource[], maxCount: number ) { const next = [...current]; const identities = new Set(next.map(getLayoutReplaceSourceIdentity)); for (const source of incoming) { const identity = getLayoutReplaceSourceIdentity(source); if (next.length >= maxCount) break; if (identities.has(identity)) continue; identities.add(identity); next.push(source); } return next; } export function getAvailableCanvasLayoutReplaceSources( canvasSources: LayoutReplaceSource[], currentSources: LayoutReplaceSource[] ) { const existingIdentities = new Set( currentSources.map(getLayoutReplaceSourceIdentity) ); return canvasSources.filter( (source) => Boolean(source.nodeId) && !existingIdentities.has(getLayoutReplaceSourceIdentity(source)) ); }