This commit is contained in:
Rizky 2023-11-22 23:31:30 +07:00
parent 7320ddb3f0
commit 6c9fa75610
5 changed files with 134 additions and 163 deletions

View File

@ -1,15 +1,7 @@
import { createId } from "@paralleldrive/cuid2";
import {
EPage,
IScope,
IScopeComp,
} from "../../../../web/src/nova/ed/logic/ed-global";
import { IContent } from "../../../../web/src/utils/types/general";
import { IItem } from "../../../../web/src/utils/types/item";
import { DComp, DPage, IRoot } from "../../../../web/src/utils/types/root";
import { EdMeta } from "../../../../web/src/nova/ed/logic/ed-global";
import { DPage } from "../../../../web/src/utils/types/root";
import { SAction } from "../actions";
import { loadComponent } from "../editor/load-component";
import { parseJs } from "../editor/parser/parse-js";
import { serverWalkLoad, serverWalkMap } from "../editor/load-page";
import { activity } from "../entity/activity";
import { conns } from "../entity/conn";
import { docs } from "../entity/docs";
@ -112,7 +104,7 @@ export const page_load: SAction["page"]["load"] = async function (
page_id: page.id,
});
const { scope, comps } = await scanMeta(docs.page[id].doc, this);
const { scope, scope_comps } = await scanMeta(docs.page[id].doc, this);
return {
id: id,
@ -120,7 +112,7 @@ export const page_load: SAction["page"]["load"] = async function (
name: page.name,
snapshot: await gzipAsync(bin),
scope,
comps,
scope_comps,
};
}
} else if (snap && !ydoc) {
@ -148,7 +140,7 @@ export const page_load: SAction["page"]["load"] = async function (
page_id: snap.id,
});
const { scope, comps } = await scanMeta(docs.page[id].doc, this);
const { scope, scope_comps } = await scanMeta(docs.page[id].doc, this);
return {
id: id,
@ -156,7 +148,7 @@ export const page_load: SAction["page"]["load"] = async function (
name: snap.name,
snapshot: await gzipAsync(snap.bin),
scope,
comps,
scope_comps,
};
} else if (snap && ydoc) {
await setActivityPage(snap.id_site, id);
@ -169,139 +161,39 @@ export const page_load: SAction["page"]["load"] = async function (
page_id: snap.id,
});
const { scope, comps } = await scanMeta(ydoc.doc, this);
const { scope, scope_comps } = await scanMeta(ydoc.doc, this);
return {
id: snap.id,
url: snap.url,
name: snap.name,
snapshot: await gzipAsync(snap.bin),
scope,
comps,
scope_comps,
};
}
};
const scanMeta = async (
doc: DPage | DComp,
sync: SyncConnection,
existing?: { scope: IScope; comps: Record<string, IScopeComp> }
) => {
const root = doc.getMap("map").get("root")?.toJSON() as IRoot;
const scanMeta = async (doc: DPage, sync: SyncConnection) => {
const scope = {};
const scope_comps = {};
const loaded = new Set<string>();
const scope = existing ? existing.scope : ({} as IScope);
const comps = existing ? existing.comps : ({} as Record<string, IScopeComp>);
const instantiate = (item: IItem, comp_id: string) => {
const ref = docs.comp[comp_id];
if (ref) {
const item_comp = assignNewID(
ref.doc.getMap("map").get("root")?.toJSON() as IItem
);
parseItem(item_comp, scope, item.id, loadComp);
}
const portal = {
in: {} as Record<string, EdMeta>,
out: {} as Record<string, EdMeta>,
};
const pendingComp = new Set<IItem>();
const loadComp = (item: IItem) => {
const comp_id = item.component?.id;
if (comp_id) {
const comp = comps[comp_id];
if (!comp) {
pendingComp.add(item);
} else {
instantiate(item, comp_id);
}
return false;
}
return true;
};
if (root) {
for (const c of root.childs) {
parseItem(c, scope, "", loadComp);
}
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) =>
serverWalkMap(
{ sync, scope, scope_comps },
{ isLayout: false, mitem: m, parent_item: { id: "root" }, portal }
)
)
);
}
for (const item of pendingComp) {
const comp_id = item.component?.id;
if (comp_id) {
let ref = docs.comp[comp_id];
if (!ref) {
await loadComponent(comp_id, sync);
ref = docs.comp[comp_id];
if (ref) {
await scanMeta(ref.doc, sync, {
scope,
comps,
});
}
}
if (ref) {
instantiate(item, comp_id);
}
}
}
Object.entries(comps)
.filter(([k, v]) => !v)
.map(async ([id, v]) => {});
return { scope, comps };
};
const assignNewID = (item: IItem) => {
item.id = createId();
for (const c of item.childs) {
if (c.type !== "text") {
assignNewID(c);
}
}
return item;
};
export const parseItem = (
item: IContent,
result: EPage["scope"],
parent_id: string,
each: (item: IItem) => boolean
) => {
const js = item.adv?.js;
const parent_ids: string[] = [];
if (!!parent_id) {
if (!!result[parent_id]) {
result[parent_id].p.forEach((e) => parent_ids.push(e));
} else {
throw new Error(
`Parent item not found: ${JSON.stringify(
parent_id
)} \nitem:\n${JSON.stringify(
{ id: item.id, name: item.name, type: item.type },
null,
2
)}`
);
}
parent_ids.push(parent_id);
}
result[item.id] = { p: parent_ids, s: null };
if (!!each && !each(item as IItem)) {
return;
}
if (typeof js === "string") {
const res = parseJs(js);
if (res) {
result[item.id].s = res;
}
}
if (item.type !== "text") {
for (const c of item.childs) {
parseItem(c, result, item.id, each);
}
}
return { scope, scope_comps };
};

View File

@ -0,0 +1,72 @@
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";
export const serverWalkLoad = async (
mitem: MItem,
sync: SyncConnection,
loaded: Set<string>
) => {
const mcomp = mitem.get("component");
if (mcomp) {
const id = mcomp.get("id");
const comp = mcomp.toJSON() as FNComponent;
if (id) {
const isFirstLoaded = !loaded.has(id);
loaded.add(id);
if (!docs.comp[id]) {
await loadComponent(id, sync);
}
const pcomp = docs.comp[id];
if (pcomp) {
const pitem = pcomp.doc.getMap("map").get("root");
if (pitem && isFirstLoaded) {
await serverWalkLoad(pitem, sync, loaded);
}
}
}
for (const [propName, prop] of Object.entries(comp.props || {})) {
if (prop.meta?.type === "content-element") {
const mprop = mcomp.get("props")?.get(propName);
if (mprop) {
const mcontent = ensurePropContent(mprop, propName);
if (mcontent) {
await serverWalkLoad(mcontent, sync, loaded);
}
}
}
}
}
for (const e of mitem.get("childs")?.map((e) => e) || []) {
await serverWalkLoad(e, sync, loaded);
}
};
export const serverWalkMap = async (
p: {
sync: SyncConnection;
scope: IScope;
scope_comps: IScopeComp;
},
arg: {
isLayout: boolean;
mitem: MItem;
portal: {
in: Record<string, EdMeta>;
out: Record<string, EdMeta>;
};
parent_item: EdMeta["parent_item"];
parent_mcomp?: EdMeta["parent_mcomp"];
}
) => {};

View File

@ -28,19 +28,22 @@ export type IScope = Record<
{ p: string[]; s: null | Exclude<ReturnType<typeof parseJs>, undefined> }
>;
export type IScopeComp = {
id: string;
name: string;
snapshot: Uint8Array;
scope: IScope;
};
export type IScopeComp = Record<
string,
{
id: string;
name: string;
snapshot: Uint8Array;
scope: IScope;
}
>;
const EmptyPage = {
id: "",
name: "",
url: "",
snapshot: null as null | Uint8Array,
scope: {} as IScope,
comps: {} as Record<string, IScopeComp>,
scope_comps: {} as IScopeComp,
};
const EmptyComp = {

View File

@ -0,0 +1,23 @@
import { createId } from "@paralleldrive/cuid2";
import { MItem } from "../../../../utils/types/item";
import { FMCompDef } from "../../../../utils/types/meta-fn";
export const ensurePropContent = (mprop: FMCompDef, k: string) => {
let mcontent = mprop.get("content");
if (!mcontent) {
const newcontent = new Y.Map();
syncronize(newcontent, {
id: createId(),
name: k,
type: "item",
dim: { w: "full", h: "full" },
childs: [],
adv: {
css: "",
},
});
mprop.set("content", newcontent as MItem);
mcontent = mprop.get("content");
}
return mcontent;
};

View File

@ -13,6 +13,7 @@ import {
import { DComp } from "../../../../utils/types/root";
import { MSection } from "../../../../utils/types/section";
import { EdMeta, PG } from "../ed-global";
import { ensurePropContent } from "./sync-walk-utils";
export const syncWalkLoad = async (
p: PG,
@ -274,26 +275,6 @@ export const loadComponent = async (p: PG, id_comp: string) => {
return false;
};
const ensurePropContent = (mprop: FMCompDef, k: string) => {
let mcontent = mprop.get("content");
if (!mcontent) {
const newcontent = new Y.Map();
syncronize(newcontent, {
id: createId(),
name: k,
type: "item",
dim: { w: "full", h: "full" },
childs: [],
adv: {
css: "",
},
});
mprop.set("content", newcontent as MItem);
mcontent = mprop.get("content");
}
return mcontent;
};
const ensureMProp = (
mitem_props: TypedMap<Record<string, FMCompDef>>,
k: string,