import type { EditorObject, TableData } from "@/pages/editor/store/editorStore"; import { normalizeCustomShapeObject, normalizePencilObject } from "@/pages/editor/utils/customShape"; import type { PageData } from "../types"; type ViewerDataPage = { id: string; name: string; backgroundType?: "color" | "gradient" | "image" | "video"; backgroundColor?: string; backgroundOpacity?: number; backgroundGradient?: { from: string; to: string; angle: number; }; backgroundImageUrl?: string; backgroundVideoUrl?: string; objects: Array<{ id: string; type: string; x: number; y: number; width?: number; height?: number; text?: string; fontSize?: number; fontFamily?: string; fontWeight?: string; lineHeight?: number; textAlign?: "left" | "center" | "right"; fill?: string; fillType?: "solid" | "gradient"; gradient?: { from: string; to: string; angle: number; }; stroke?: string; strokeWidth?: number; shapeType?: string; borderRadius?: number; blur?: number; imageUrl?: string; videoUrl?: string; audioUrl?: string; linkUrl?: string; rotation?: number; opacity?: number; letterSpacing?: number; tableData?: TableData; entranceAnimation?: EditorObject["entranceAnimation"]; entranceDurationMs?: number; entranceDelayMs?: number; isMask?: boolean; maskId?: string; maskInvert?: boolean; points?: number[]; closed?: boolean; tension?: number; }>; }; type ViewerData = { pages: ViewerDataPage[]; }; /** * تبدیل داده‌های viewer-data.json به فرمت PageData */ export function transformViewerDataToPages(data: ViewerData): PageData[] { return data.pages.map((page, index) => { const objects: EditorObject[] = page.objects.map((obj) => { const baseObject: EditorObject = { id: obj.id, type: obj.type as EditorObject["type"], x: obj.x, y: obj.y, // در JSON، opacity به صورت 0-100 است (درصد) // در editor هم opacity به صورت 0-100 است // پس opacity را مستقیماً استفاده می‌کنیم opacity: obj.opacity !== undefined ? obj.opacity : 100, visible: true, }; // برای line و arrow، width و height در viewer-data.json به عنوان مختصات انتهایی هستند // در EditorObject هم به عنوان مختصات انتهایی ذخیره می‌شوند if (obj.type === "line" || obj.type === "arrow") { // width و height مستقیماً مختصات نقطه پایان هستند if (obj.width !== undefined) { baseObject.width = obj.width; } if (obj.height !== undefined) { baseObject.height = obj.height; } } else { if (obj.width !== undefined) baseObject.width = obj.width; if (obj.height !== undefined) baseObject.height = obj.height; } // برای circle در viewer-data.json، x, y به عنوان گوشه بالا-چپ bounding box است // اما در editor، circle با مرکز در x, y ذخیره می‌شود // پس باید تبدیل کنیم // اما بر اساس بررسی، در JSON موقعیت به عنوان مرکز ذخیره شده است // پس نباید تبدیل کنیم - مستقیماً استفاده می‌کنیم // اگر در آینده JSON به صورت گوشه بالا-چپ export شود، باید تبدیل کنیم: // baseObject.x = obj.x + (obj.width || 100) / 2; // baseObject.y = obj.y + (obj.height || 100) / 2; // اما فعلاً JSON به صورت مرکز است، پس تبدیل نمی‌کنیم if (obj.fill !== undefined) baseObject.fill = obj.fill; if (obj.fillType !== undefined) baseObject.fillType = obj.fillType; if (obj.gradient !== undefined) baseObject.gradient = obj.gradient; if (obj.stroke !== undefined) baseObject.stroke = obj.stroke; if (obj.strokeWidth !== undefined) baseObject.strokeWidth = obj.strokeWidth; if (obj.rotation !== undefined) baseObject.rotation = obj.rotation; // ویژگی‌های متنی if (obj.text !== undefined) baseObject.text = obj.text; if (obj.fontSize !== undefined) baseObject.fontSize = obj.fontSize; if (obj.fontFamily !== undefined) baseObject.fontFamily = obj.fontFamily; if (obj.fontWeight !== undefined) baseObject.fontWeight = obj.fontWeight; if (obj.letterSpacing !== undefined) baseObject.letterSpacing = obj.letterSpacing; if (obj.lineHeight !== undefined) baseObject.lineHeight = obj.lineHeight; if (obj.textAlign !== undefined) baseObject.textAlign = obj.textAlign; // انواع خاص objectها if (obj.type === "rectangle" && obj.shapeType) { baseObject.shapeType = obj.shapeType as EditorObject["shapeType"]; } if (obj.borderRadius !== undefined) { baseObject.borderRadius = obj.borderRadius; } if (obj.type === "rectangle" && obj.blur !== undefined) { baseObject.blur = obj.blur; } if ( (obj.type === "image" || obj.type === "sticker" || obj.type === "document") && obj.imageUrl ) { baseObject.imageUrl = obj.imageUrl; } if (obj.type === "video" && obj.videoUrl) { baseObject.videoUrl = obj.videoUrl; } if (obj.type === "audio" && obj.audioUrl) { baseObject.audioUrl = obj.audioUrl; } if (obj.type === "link" && obj.linkUrl) { baseObject.linkUrl = obj.linkUrl; } if (obj.type === "grid" && obj.tableData) { baseObject.tableData = obj.tableData; } if (obj.entranceAnimation !== undefined) { baseObject.entranceAnimation = obj.entranceAnimation; } if (obj.entranceDurationMs !== undefined) { baseObject.entranceDurationMs = obj.entranceDurationMs; } if (obj.entranceDelayMs !== undefined) { baseObject.entranceDelayMs = obj.entranceDelayMs; } if (obj.isMask !== undefined) { baseObject.isMask = obj.isMask; } if (obj.maskId !== undefined) { baseObject.maskId = obj.maskId; } if (obj.maskInvert !== undefined) { baseObject.maskInvert = obj.maskInvert; } if (obj.type === "custom-shape") { if (obj.points !== undefined) baseObject.points = obj.points; if (obj.closed !== undefined) baseObject.closed = obj.closed; } if (obj.type === "pencil") { if (obj.points !== undefined) baseObject.points = obj.points; if (obj.closed !== undefined) baseObject.closed = obj.closed; if (obj.tension !== undefined) baseObject.tension = obj.tension; } const normalized = obj.type === "pencil" ? normalizePencilObject(baseObject) : normalizeCustomShapeObject(baseObject); return normalized; }); return { id: index + 1, width: 794, height: 1123, elements: objects, backgroundType: page.backgroundType, backgroundColor: page.backgroundColor, backgroundOpacity: page.backgroundOpacity, backgroundGradient: page.backgroundGradient, backgroundImageUrl: page.backgroundImageUrl, backgroundVideoUrl: page.backgroundVideoUrl, }; }); }