From 6f4a881238e88476b65ded854f6056dc705e552d Mon Sep 17 00:00:00 2001 From: Your Name Date: Tue, 2 Jun 2026 16:34:51 +0800 Subject: [PATCH] fix: speed up psd editor image preview --- .../agents/AgentPsdTemplateEditorDialog.tsx | 177 ++++++++++++++---- 1 file changed, 144 insertions(+), 33 deletions(-) diff --git a/components/agents/AgentPsdTemplateEditorDialog.tsx b/components/agents/AgentPsdTemplateEditorDialog.tsx index 3ffde39f1..812a9d605 100644 --- a/components/agents/AgentPsdTemplateEditorDialog.tsx +++ b/components/agents/AgentPsdTemplateEditorDialog.tsx @@ -400,6 +400,42 @@ function buildPsdLayerPreviewUrl( return buildTemplatePreviewThumbUrl(imageUrl, { width, quality }); } +function buildAssignedPsdLayerPreviewFallbackUrls( + imageUrl: string, + params?: { + width?: number; + quality?: number; + } +) { + const normalizedUrl = String(imageUrl || "").trim(); + if (!normalizedUrl) { + return []; + } + + const width = Math.max(96, Math.min(1280, Math.round(params?.width || 720))); + const quality = Math.max(52, Math.min(82, Math.round(params?.quality || 74))); + const directDisplayUrl = buildImageProxyUrl(normalizedUrl, { + width, + quality, + format: "webp", + }); + const proxyUrl = buildImageProxyUrl(normalizedUrl, { + width, + quality, + format: "webp", + delivery: "proxy", + }); + const seen = new Set(); + + return [normalizedUrl, directDisplayUrl, proxyUrl].filter((url) => { + if (!url || seen.has(url)) { + return false; + } + seen.add(url); + return true; + }); +} + function buildPsdLayerMaskUrl(maskUrl: string, layerWidth: number) { const normalizedUrl = String(maskUrl || "").trim(); if (!normalizedUrl) { @@ -536,6 +572,72 @@ function TemplatePreviewImage({ ); } +function AssignedPsdLayerPreviewImage({ + sourceUrl, + alt, + className, + width, + quality, + style, +}: { + sourceUrl: string; + alt: string; + className?: string; + width?: number; + quality?: number; + style?: CSSProperties; +}) { + const fallbackUrls = useMemo( + () => buildAssignedPsdLayerPreviewFallbackUrls(sourceUrl, { width, quality }), + [quality, sourceUrl, width] + ); + const fallbackUrlKey = fallbackUrls.join("\n"); + const [activeUrlIndex, setActiveUrlIndex] = useState(0); + const [hasLoaded, setHasLoaded] = useState(false); + + useEffect(() => { + setActiveUrlIndex(0); + setHasLoaded(false); + }, [fallbackUrlKey]); + + useEffect(() => { + if (hasLoaded || activeUrlIndex + 1 >= fallbackUrls.length) { + return; + } + + const timeoutId = window.setTimeout(() => { + setActiveUrlIndex((current) => + current + 1 < fallbackUrls.length ? current + 1 : current + ); + }, 6500); + + return () => window.clearTimeout(timeoutId); + }, [activeUrlIndex, fallbackUrls.length, hasLoaded]); + + const src = fallbackUrls[activeUrlIndex] || ""; + if (!src) { + return null; + } + + return ( + {alt} + setActiveUrlIndex((current) => + current + 1 < fallbackUrls.length ? current + 1 : current + ) + } + onLoad={() => setHasLoaded(true)} + src={src} + style={style} + /> + ); +} + function getScrollAreaViewportElement(root: HTMLDivElement | null) { return ( (root?.querySelector( @@ -4293,45 +4395,54 @@ export function AgentPsdTemplateEditorDialog({ }} title={`${getLayerLabel(layer)}:${layer.layerName}`} > - {layer.layerName} + } + width={Math.max( + layer.width, + layer.height + )} + /> + ) : ( + {layer.layerName} + )} ); }