From a4d10caacd7c01f994dfca045090ba8b9563acb6 Mon Sep 17 00:00:00 2001 From: hamid zarghami Date: Sat, 2 May 2026 09:42:58 +0330 Subject: [PATCH] fix group 2 --- .../editor/components/canvas/ObjectsLayer.tsx | 20 +----- src/pages/editor/store/editorStore.helpers.ts | 67 +++++++++++++++++++ src/pages/editor/store/editorStore.ts | 2 + 3 files changed, 70 insertions(+), 19 deletions(-) diff --git a/src/pages/editor/components/canvas/ObjectsLayer.tsx b/src/pages/editor/components/canvas/ObjectsLayer.tsx index 8657f75..e8ef668 100644 --- a/src/pages/editor/components/canvas/ObjectsLayer.tsx +++ b/src/pages/editor/components/canvas/ObjectsLayer.tsx @@ -97,25 +97,7 @@ const ObjectsLayer = ({ .filter((obj) => obj.groupId && obj.type !== "group") .map((obj) => { const groupObject = objects.find((o) => o.id === obj.groupId); - // داده قدیمی/ناقص: groupId بدون شیء type:group در صفحه — مثل preview همه را نشان بده - if (!groupObject) { - return ( - - ); - } + if (!groupObject) return null; // Render with absolute position but wrapped in non-listening group return ( diff --git a/src/pages/editor/store/editorStore.helpers.ts b/src/pages/editor/store/editorStore.helpers.ts index 38e6db9..f812821 100644 --- a/src/pages/editor/store/editorStore.helpers.ts +++ b/src/pages/editor/store/editorStore.helpers.ts @@ -262,3 +262,70 @@ export const ungroupById = (objects: EditorObject[], groupId: string) => objects .map((obj) => (obj.groupId === groupId ? { ...obj, groupId: undefined } : obj)) .filter((obj) => obj.id !== groupId); + +/** + * اگر اعضا groupId دارند ولی شیء type:group با همان id در آرایه نیست (ذخیره/سنک ناقص)، + * همانند buildGroupResult یک wrapper اضافه می‌کنیم تا ادیتور گروه را یکپارچه جابه‌جا کند. + * اگر فقط یک عضو با آن groupId باشد، groupId حذف می‌شود (گروه نامعتبر). + */ +export const ensureMissingGroupObjects = (objects: EditorObject[]): EditorObject[] => { + let next = [...objects]; + + const referencedIds = new Set(); + for (const o of next) { + if (o.type !== "group" && o.groupId) { + referencedIds.add(o.groupId); + } + } + + for (const gid of referencedIds) { + const members = next.filter((o) => o.groupId === gid && o.type !== "group"); + if (members.length < 2) { + next = next.map((o) => + o.groupId === gid && o.type !== "group" ? { ...o, groupId: undefined } : o, + ); + } + } + + const stillReferenced = new Set(); + for (const o of next) { + if (o.type !== "group" && o.groupId) { + stillReferenced.add(o.groupId); + } + } + + const existingGroupIds = new Set( + next.filter((o) => o.type === "group").map((o) => o.id), + ); + + const toAppend: EditorObject[] = []; + for (const gid of stillReferenced) { + if (existingGroupIds.has(gid)) continue; + + const members = next.filter((o) => o.groupId === gid && o.type !== "group"); + if (members.length < 2) continue; + + let minX = Infinity; + let minY = Infinity; + let maxX = -Infinity; + let maxY = -Infinity; + for (const m of members) { + const b = getObjectBounds(m); + minX = Math.min(minX, b.minX); + minY = Math.min(minY, b.minY); + maxX = Math.max(maxX, b.maxX); + maxY = Math.max(maxY, b.maxY); + } + + toAppend.push({ + id: gid, + type: "group", + x: minX, + y: minY, + width: maxX - minX, + height: maxY - minY, + }); + } + + return toAppend.length > 0 ? [...next, ...toAppend] : next; +}; diff --git a/src/pages/editor/store/editorStore.ts b/src/pages/editor/store/editorStore.ts index bc67e96..9c46931 100644 --- a/src/pages/editor/store/editorStore.ts +++ b/src/pages/editor/store/editorStore.ts @@ -9,6 +9,7 @@ import { isInvalidPageId, reorderByIds, ungroupById, + ensureMissingGroupObjects, } from "./editorStore.helpers"; import type { EditorObject, @@ -792,6 +793,7 @@ export const useEditorStore = create((set, get) => { ...page, id: isInvalidPageId(page.id) ? createScopedId("page") : page.id, guides: page.guides || [], + objects: ensureMissingGroupObjects(page.objects || []), })); const firstPage = normalizedPages[0]; set({