fix: harden psd template dialog against malformed payload
This commit is contained in:
parent
49b54c2387
commit
046fff7f2e
@ -42,6 +42,7 @@ import {
|
||||
import {
|
||||
isAgentPsdImageLayerSlot,
|
||||
isAgentPsdTextLayerSlot,
|
||||
parseAgentPsdTemplates,
|
||||
type AgentPsdTemplate,
|
||||
type AgentPsdTemplateImageLayerSlot,
|
||||
type AgentPsdTemplateLayerSlot,
|
||||
@ -51,7 +52,33 @@ import {
|
||||
} from "@/lib/agents/psd-template-config";
|
||||
import { resolveTextLayout } from "@/lib/agents/psd-text-layout";
|
||||
|
||||
const fetcher = (url: string) => fetch(url, { cache: "no-store" }).then((res) => res.json());
|
||||
const fetcher = async (url: string): Promise<AgentPsdTemplateListResponse> => {
|
||||
try {
|
||||
const response = await fetch(url, { cache: "no-store" });
|
||||
const payload = (await response.json().catch(() => null)) as
|
||||
| Partial<AgentPsdTemplateListResponse>
|
||||
| null;
|
||||
|
||||
if (!response.ok || !payload || payload.success !== true || !Array.isArray(payload.templates)) {
|
||||
return {
|
||||
success: false,
|
||||
templates: [],
|
||||
error: typeof payload?.error === "string" ? payload.error : "PSD 模板加载失败",
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
templates: parseAgentPsdTemplates(payload.templates),
|
||||
};
|
||||
} catch {
|
||||
return {
|
||||
success: false,
|
||||
templates: [],
|
||||
error: "PSD 模板加载失败",
|
||||
};
|
||||
}
|
||||
};
|
||||
const PREVIEW_VIEWPORT_PADDING = 56;
|
||||
const PREVIEW_STAGE_MAX_SCALE = 0.82;
|
||||
const PREVIEW_STAGE_TARGET_WIDTH = 760;
|
||||
@ -302,30 +329,36 @@ export function AgentPsdTemplateEditorDialog({
|
||||
() => templates.find((template) => template.id === selectedTemplateId) || null,
|
||||
[selectedTemplateId, templates]
|
||||
);
|
||||
const selectedTemplateLayers = useMemo(() => {
|
||||
if (!selectedTemplate || !Array.isArray(selectedTemplate.layers)) {
|
||||
return [] as AgentPsdTemplateLayerSlot[];
|
||||
}
|
||||
return selectedTemplate.layers;
|
||||
}, [selectedTemplate]);
|
||||
|
||||
const editableImageLayers = useMemo(
|
||||
() =>
|
||||
(selectedTemplate?.layers || []).filter(
|
||||
selectedTemplateLayers.filter(
|
||||
(layer): layer is AgentPsdTemplateImageLayerSlot =>
|
||||
layer.isEditable && isAgentPsdImageLayerSlot(layer)
|
||||
),
|
||||
[selectedTemplate]
|
||||
[selectedTemplateLayers]
|
||||
);
|
||||
const editableTextLayers = useMemo(
|
||||
() =>
|
||||
(selectedTemplate?.layers || []).filter(
|
||||
selectedTemplateLayers.filter(
|
||||
(layer): layer is AgentPsdTemplateTextLayerSlot =>
|
||||
layer.isEditable && isAgentPsdTextLayerSlot(layer)
|
||||
),
|
||||
[selectedTemplate]
|
||||
[selectedTemplateLayers]
|
||||
);
|
||||
const fixedLayerCount = useMemo(() => {
|
||||
if (!selectedTemplate) return 0;
|
||||
return selectedTemplate.layers.filter((layer) => !layer.isEditable).length;
|
||||
}, [selectedTemplate]);
|
||||
return selectedTemplateLayers.filter((layer) => !layer.isEditable).length;
|
||||
}, [selectedTemplate, selectedTemplateLayers]);
|
||||
const orderedPreviewLayers = useMemo(
|
||||
() => (selectedTemplate ? [...selectedTemplate.layers].reverse() : []),
|
||||
[selectedTemplate]
|
||||
() => [...selectedTemplateLayers].reverse(),
|
||||
[selectedTemplateLayers]
|
||||
);
|
||||
const orderedEditableLayers = useMemo(
|
||||
() => orderedPreviewLayers.filter((layer) => layer.isEditable),
|
||||
@ -403,8 +436,8 @@ export function AgentPsdTemplateEditorDialog({
|
||||
}, [editableImageLayers, effectiveImageAssignments, imagePlacements, selectedTemplate]);
|
||||
|
||||
const selectedLayer = useMemo(
|
||||
() => selectedTemplate?.layers.find((layer) => layer.id === selectedLayerId) || null,
|
||||
[selectedLayerId, selectedTemplate]
|
||||
() => selectedTemplateLayers.find((layer) => layer.id === selectedLayerId) || null,
|
||||
[selectedLayerId, selectedTemplateLayers]
|
||||
);
|
||||
const selectedImageLayer = selectedLayer && isAgentPsdImageLayerSlot(selectedLayer) ? selectedLayer : null;
|
||||
const selectedTextLayer = selectedLayer && isAgentPsdTextLayerSlot(selectedLayer) ? selectedLayer : null;
|
||||
@ -562,7 +595,11 @@ export function AgentPsdTemplateEditorDialog({
|
||||
const focusTextarea = () => {
|
||||
textarea.focus();
|
||||
const valueLength = textarea.value.length;
|
||||
textarea.setSelectionRange(valueLength, valueLength);
|
||||
try {
|
||||
textarea.setSelectionRange(valueLength, valueLength);
|
||||
} catch (error) {
|
||||
console.warn("[AgentPsdTemplateEditorDialog] setSelectionRange failed:", error);
|
||||
}
|
||||
};
|
||||
|
||||
if (typeof window !== "undefined" && typeof window.requestAnimationFrame === "function") {
|
||||
@ -664,7 +701,11 @@ export function AgentPsdTemplateEditorDialog({
|
||||
};
|
||||
|
||||
const nextTarget = event.currentTarget;
|
||||
nextTarget.setPointerCapture?.(event.pointerId);
|
||||
try {
|
||||
nextTarget.setPointerCapture?.(event.pointerId);
|
||||
} catch (error) {
|
||||
console.warn("[AgentPsdTemplateEditorDialog] setPointerCapture failed:", error);
|
||||
}
|
||||
|
||||
const handlePointerMove = (moveEvent: PointerEvent) => {
|
||||
const dragState = imageDragStateRef.current;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user