From dcbee85de187a766b0a4643b85e8cd638f61ee6e Mon Sep 17 00:00:00 2001 From: Rizky Date: Thu, 23 Nov 2023 10:51:58 +0700 Subject: [PATCH] fix --- app/srv/ws/sync/actions/page_load.ts | 15 +- app/srv/ws/sync/editor/load-page.ts | 255 +++++++++++++++--- .../nova/ed/logic/tree/sync-walk-utils.tsx | 38 ++- app/web/src/nova/ed/logic/tree/sync-walk.tsx | 36 +-- 4 files changed, 269 insertions(+), 75 deletions(-) diff --git a/app/srv/ws/sync/actions/page_load.ts b/app/srv/ws/sync/actions/page_load.ts index 3f37e0e2..4a656d85 100644 --- a/app/srv/ws/sync/actions/page_load.ts +++ b/app/srv/ws/sync/actions/page_load.ts @@ -177,19 +177,20 @@ const scanMeta = async (doc: DPage, sync: SyncConnection) => { const scope = {}; const scope_comps = {}; const loaded = new Set(); - - const portal = { - in: {} as Record, - out: {} as Record, - }; const childs = doc.getMap("map").get("root")?.get("childs") || []; if (childs) { - await Promise.all(childs.map((m) => serverWalkLoad(m, sync, loaded))); + await Promise.all( + childs.map((m) => serverWalkLoad(m, scope_comps, sync, loaded)) + ); await Promise.all( childs.map((m) => serverWalkMap( { sync, scope, scope_comps }, - { isLayout: false, mitem: m, parent_item: { id: "root" }, portal } + { + mitem: m, + parent_item: { id: "root" }, + parent_ids: ["root"], + } ) ) ); diff --git a/app/srv/ws/sync/editor/load-page.ts b/app/srv/ws/sync/editor/load-page.ts index 64793167..99d5e242 100644 --- a/app/srv/ws/sync/editor/load-page.ts +++ b/app/srv/ws/sync/editor/load-page.ts @@ -1,47 +1,71 @@ +import { createId } from "@paralleldrive/cuid2" +import { TypedArray } from "yjs-types" import { EdMeta, IScope, IScopeComp, -} from "../../../../web/src/nova/ed/logic/ed-global"; -import { ensurePropContent } from "../../../../web/src/nova/ed/logic/tree/sync-walk-utils"; -import { MItem } from "../../../../web/src/utils/types/item"; -import { FNComponent } from "../../../../web/src/utils/types/meta-fn"; -import { docs } from "../entity/docs"; -import { SyncConnection } from "../type"; -import { loadComponent } from "./load-component"; +} from "../../../../web/src/nova/ed/logic/ed-global" +import { + ensureMItemProps, + ensureMProp, + ensurePropContent, +} from "../../../../web/src/nova/ed/logic/tree/sync-walk-utils" +import { MContent } from "../../../../web/src/utils/types/general" +import { IItem, MItem } from "../../../../web/src/utils/types/item" +import { FNCompDef, FNComponent } from "../../../../web/src/utils/types/meta-fn" +import { docs } from "../entity/docs" +import { gzipAsync } from "../entity/zlib" +import { SyncConnection } from "../type" +import { loadComponent } from "./load-component" +import { parseJs } from "./parser/parse-js" export const serverWalkLoad = async ( mitem: MItem, + scope_comps: IScopeComp, sync: SyncConnection, loaded: Set ) => { - const mcomp = mitem.get("component"); + const mcomp = mitem.get("component") if (mcomp) { - const id = mcomp.get("id"); - const comp = mcomp.toJSON() as FNComponent; + const id = mcomp.get("id") + const comp = mcomp.toJSON() as FNComponent if (id) { - const isFirstLoaded = !loaded.has(id); - loaded.add(id); + const isFirstLoaded = !loaded.has(id) + loaded.add(id) if (!docs.comp[id]) { - await loadComponent(id, sync); + await loadComponent(id, sync) } - const pcomp = docs.comp[id]; + const pcomp = docs.comp[id] if (pcomp) { - const pitem = pcomp.doc.getMap("map").get("root"); - if (pitem && isFirstLoaded) { - await serverWalkLoad(pitem, sync, loaded); + const pitem = pcomp.doc.getMap("map").get("root") + + if (pitem) { + const id = pitem.get("id") + const name = pitem.get("name") + if (id && name) { + const bin = Y.encodeStateAsUpdate(pcomp.doc as any) + scope_comps[id] = { + id, + name, + scope: {}, + snapshot: await gzipAsync(bin), + } + if (isFirstLoaded) { + await serverWalkLoad(pitem, scope_comps, sync, loaded) + } + } } } } for (const [propName, prop] of Object.entries(comp.props || {})) { if (prop.meta?.type === "content-element") { - const mprop = mcomp.get("props")?.get(propName); + const mprop = mcomp.get("props")?.get(propName) if (mprop) { - const mcontent = ensurePropContent(mprop, propName); + const mcontent = ensurePropContent(mprop, propName) if (mcontent) { - await serverWalkLoad(mcontent, sync, loaded); + await serverWalkLoad(mcontent, scope_comps, sync, loaded) } } } @@ -49,24 +73,187 @@ export const serverWalkLoad = async ( } for (const e of mitem.get("childs")?.map((e) => e) || []) { - await serverWalkLoad(e, sync, loaded); + await serverWalkLoad(e, scope_comps, sync, loaded) } -}; +} export const serverWalkMap = async ( p: { - sync: SyncConnection; - scope: IScope; - scope_comps: IScopeComp; + sync: SyncConnection + scope: IScope + scope_comps: IScopeComp }, arg: { - isLayout: boolean; - mitem: MItem; - portal: { - in: Record; - out: Record; - }; - parent_item: EdMeta["parent_item"]; - parent_mcomp?: EdMeta["parent_mcomp"]; + mitem: MItem + parent_ids: string[] + parent_item: EdMeta["parent_item"] + parent_mcomp?: EdMeta["parent_mcomp"] & { id: string } } -) => {}; +) => { + const { mitem, parent_item, parent_mcomp } = arg + const item = {} as unknown as IItem + + let override_id = "" + const id = mitem.get("id") + + if (parent_mcomp && id) { + const fcomp = parent_mcomp.mitem.get("component") + if (fcomp) { + const ref_ids = fcomp.get("ref_ids") + + if (ref_ids) { + let ref_id = ref_ids.get(id) + + if (!ref_id) { + ref_id = createId() + ref_ids.set(id, ref_id) + } + override_id = ref_id + } + } + + mapItem(mitem, item) + + if (override_id) { + item.id = override_id + } + + const item_comp = item.component + const mitem_comp = mitem.get("component") + + if (item_comp && item_comp.id && parent_item.id !== "root") { + if (!docs.comp[item_comp.id]) { + console.error("Component failed to load: ", item_comp.id) + return + } + + if (!p.scope_comps[item_comp.id]) { + console.error("Failed to assign component: ", item_comp.id) + return + } + + const ref_comp = docs.comp[item_comp.id] + + if (ref_comp && mitem_comp) { + const mcomp = ref_comp.doc.getMap("map").get("root") + + if (mcomp) { + let ref_ids: Record = item_comp.ref_ids + if (!ref_ids) { + mitem_comp.set("ref_ids", new Y.Map() as any) + ref_ids = {} + } + const original_id = item.id + mapItem(mcomp, item) + item.id = original_id + + const pcomp = p.scope_comps[item_comp.id] + pcomp.scope[item.id] = { p: arg.parent_ids, s: null } + const js = item.adv?.js + if (typeof js === "string") { + const scope = parseJs(js) + if (scope) p.scope[item.id].s = scope + } + + const mprops = mcomp + .get("component") + ?.get("props") + ?.toJSON() as Record + + if (mprops) { + const mitem_comp = mitem.get("component") + if (mitem_comp) { + const mitem_props = ensureMItemProps(mitem_comp, item_comp) + if (mitem_props) { + for (const [k, v] of Object.entries(mprops)) { + const mprop = ensureMProp(mitem_props, k, v) + item_comp.props[k] = v + if (mprop && v.meta?.type === "content-element") { + const mcontent = ensurePropContent(mprop, k) + if (mcontent) { + serverWalkMap(p, { + parent_ids: [...arg.parent_ids, item.id], + mitem: mcontent, + parent_item: { id: item.id, mitem: mitem as MItem }, + parent_mcomp: { + id: item_comp.id, + mitem: mitem as MItem, + mcomp, + }, + }) + } + } + } + } + } + } + + const childs = mcomp.get("childs")?.map((e) => e) || [] + for (const e of childs) { + serverWalkMap(p, { + mitem: e, + parent_ids: [...arg.parent_ids, item.id], + parent_item: { + id: item.id, + mitem: mitem as MItem, + }, + parent_mcomp: { + id: item_comp.id, + mitem: mitem as MItem, + mcomp, + }, + }) + } + return + } + } + } + + if (arg.parent_mcomp) { + const pcomp = p.scope_comps[arg.parent_mcomp.id] + pcomp.scope[item.id] = { p: arg.parent_ids, s: null } + const js = item.adv?.js + if (typeof js === "string") { + const scope = parseJs(js) + if (scope) p.scope[item.id].s = scope + } + } else { + p.scope[item.id] = { p: arg.parent_ids, s: null } + const js = item.adv?.js + if (typeof js === "string") { + const scope = parseJs(js) + if (scope) p.scope[item.id].s = scope + } + } + + const childs = mitem.get("childs")?.map((e) => e) || [] + for (const e of childs) { + serverWalkMap(p, { + mitem: e, + parent_item: { id: item.id, mitem: mitem as MItem }, + parent_mcomp: arg.parent_mcomp, + parent_ids: [...arg.parent_ids, item.id], + }) + } + } +} + +const mapItem = (mitem: MContent, item: any) => { + mitem.forEach((e, k) => { + if (k !== "childs") { + let val = e + if (typeof e === "object" && e) { + if ((e as any).toJSON) { + val = e.toJSON() as any + } + } + item[k] = val + } else { + if (!item[k]) item[k] = [] + const childs = e as unknown as TypedArray<{}> + childs.forEach((c) => { + item[k].push({ id: c.get("id") }) + }) + } + }) +} diff --git a/app/web/src/nova/ed/logic/tree/sync-walk-utils.tsx b/app/web/src/nova/ed/logic/tree/sync-walk-utils.tsx index df88f863..22b56b15 100644 --- a/app/web/src/nova/ed/logic/tree/sync-walk-utils.tsx +++ b/app/web/src/nova/ed/logic/tree/sync-walk-utils.tsx @@ -1,6 +1,12 @@ import { createId } from "@paralleldrive/cuid2"; +import { TypedMap } from "yjs-types"; import { MItem } from "../../../../utils/types/item"; -import { FMCompDef } from "../../../../utils/types/meta-fn"; +import { + FMCompDef, + FMComponent, + FNCompDef, + FNComponent, +} from "../../../../utils/types/meta-fn"; export const ensurePropContent = (mprop: FMCompDef, k: string) => { let mcontent = mprop.get("content"); @@ -21,3 +27,33 @@ export const ensurePropContent = (mprop: FMCompDef, k: string) => { } return mcontent; }; + +export const ensureMItemProps = ( + mitem_comp: FMComponent, + item_comp: FNComponent +) => { + let mitem_props = mitem_comp.get("props"); + if (!mitem_props) { + mitem_comp.set("props", new Y.Map() as any); + mitem_props = mitem_comp.get("props"); + } + if (!item_comp.props) { + item_comp.props = {}; + } + return mitem_props; +}; + +export const ensureMProp = ( + mitem_props: TypedMap>, + k: string, + v: FNCompDef +) => { + let mprop = mitem_props.get(k); + if (!mprop) { + const newprop = new Y.Map(); + syncronize(newprop, v); + mitem_props.set(k, newprop as FMCompDef); + mprop = mitem_props.get(k); + } + return mprop; +}; diff --git a/app/web/src/nova/ed/logic/tree/sync-walk.tsx b/app/web/src/nova/ed/logic/tree/sync-walk.tsx index 6df1a7ab..ebb4155f 100644 --- a/app/web/src/nova/ed/logic/tree/sync-walk.tsx +++ b/app/web/src/nova/ed/logic/tree/sync-walk.tsx @@ -1,19 +1,16 @@ import { createId } from "@paralleldrive/cuid2"; import { decompress } from "wasm-gzip"; -import { syncronize } from "y-pojo"; -import { TypedArray, TypedMap } from "yjs-types"; +import { TypedArray } from "yjs-types"; import { MContent } from "../../../../utils/types/general"; import { IItem, MItem } from "../../../../utils/types/item"; import { - FMCompDef, - FMComponent, FNCompDef, - FNComponent, + FNComponent } from "../../../../utils/types/meta-fn"; import { DComp } from "../../../../utils/types/root"; import { MSection } from "../../../../utils/types/section"; import { EdMeta, PG } from "../ed-global"; -import { ensurePropContent } from "./sync-walk-utils"; +import { ensureMItemProps, ensureMProp, ensurePropContent } from "./sync-walk-utils"; export const syncWalkLoad = async ( p: PG, @@ -275,33 +272,6 @@ export const loadComponent = async (p: PG, id_comp: string) => { return false; }; -const ensureMProp = ( - mitem_props: TypedMap>, - k: string, - v: FNCompDef -) => { - let mprop = mitem_props.get(k); - if (!mprop) { - const newprop = new Y.Map(); - syncronize(newprop, v); - mitem_props.set(k, newprop as FMCompDef); - mprop = mitem_props.get(k); - } - return mprop; -}; - -const ensureMItemProps = (mitem_comp: FMComponent, item_comp: FNComponent) => { - let mitem_props = mitem_comp.get("props"); - if (!mitem_props) { - mitem_comp.set("props", new Y.Map() as any); - mitem_props = mitem_comp.get("props"); - } - if (!item_comp.props) { - item_comp.props = {}; - } - return mitem_props; -}; - const mapItem = (mitem: MContent, item: any) => { mitem.forEach((e, k) => { if (k !== "childs") {