This commit is contained in:
Rizky 2023-12-14 02:24:16 +07:00
parent 0960724075
commit a3e770bfed
7 changed files with 6 additions and 767 deletions

View File

@ -2,7 +2,6 @@ import { compress, decompress } from "wasm-gzip";
import { PG } from "./ed-global";
import { loadSite } from "./ed-site";
import { treeRebuild } from "./tree/build";
import { loadCompSnapshot } from "./tree/sync-walk-comp";
export const edRoute = async (p: PG) => {
if (p.status === "ready" || p.status === "init") {
@ -50,7 +49,7 @@ export const reloadPage = async (p: PG, page_id: string, note: string) => {
if (remotePage.comps) {
for (const [id_comp, c] of Object.entries(remotePage.comps)) {
if (c && c.snapshot) {
await loadCompSnapshot(p, id_comp, c.snapshot);
// await loadCompSnapshot(p, id_comp, c.snapshot);
}
}
}

View File

@ -1,189 +0,0 @@
// import { createId } from "@paralleldrive/cuid2";
// import { deepClone } from "web-utils";
// import { IContent } from "../../../../utils/types/general";
// import { IItem } from "../../../../utils/types/item";
// import { FNComponent } from "../../../../utils/types/meta-fn";
// import { IMeta, PG } from "../ed-global";
// export const walkLoad = async (
// p: { map: PG["comp"]["map"] },
// item: IContent,
// loaded: Set<string>,
// loadComponent: (id: string) => Promise<boolean>
// ) => {
// if (item.type === "item" && item.component?.id) {
// const id = item.component?.id;
// const comp = item.component as FNComponent;
// if (id && comp) {
// const isFirstLoaded = !loaded.has(id);
// loaded.add(id);
// if (!p.map[id]) {
// await loadComponent(comp.id);
// }
// if (p.map[id] && isFirstLoaded) {
// await walkLoad(p, p.map[id].item, loaded, loadComponent);
// }
// }
// for (const [propName, prop] of Object.entries(comp.props || {})) {
// if (prop.meta?.type === "content-element") {
// const mprop = comp.props[propName];
// if (mprop) {
// const mcontent = mprop.content;
// if (mcontent) {
// await walkLoad(p, mcontent, loaded, loadComponent);
// }
// }
// }
// }
// }
// if (item.type !== "text") {
// await Promise.all(
// item.childs.map((e) => walkLoad(p, e, loaded, loadComponent))
// );
// }
// };
// export const walkMap = (
// p: {
// meta: Record<string, IMeta>;
// comps: Record<string, { id: string; item: IItem }>;
// },
// arg: {
// isLayout: boolean;
// item: IContent;
// parent_item: { id: string };
// portal: {
// in: Record<string, IMeta>;
// out: Record<string, IMeta>;
// };
// each?: (meta: IMeta) => void;
// parent_comp?: { id: string; comp_id: string };
// }
// ) => {
// const { parent_item, parent_comp } = arg;
// let override_id = "";
// const id = arg.item.id;
// if (parent_comp && id) {
// const cmeta = p.meta[parent_comp.id];
// if (cmeta && cmeta.item.type === "item") {
// const comp = cmeta.item.component;
// if (comp) {
// const ref_ids = comp.ref_ids;
// if (ref_ids) {
// let ref_id = ref_ids[id];
// if (!ref_id) {
// ref_id = createId();
// ref_ids[id] = ref_id;
// }
// override_id = ref_id;
// }
// }
// }
// }
// let item = arg.item;
// if (override_id) {
// item.id = override_id;
// }
// const item_comp = item.type === "item" ? item.component : null;
// if (item_comp && item_comp.id && parent_item.id !== "root") {
// const comp_ref = p.comps[item_comp.id];
// if (!comp_ref) {
// console.error("Component failed to load: ", item_comp.id);
// return;
// }
// const mcomp = comp_ref.item;
// if (mcomp) {
// let ref_ids: Record<string, string> = item_comp.ref_ids;
// if (!ref_ids) {
// ref_ids = {};
// item_comp.ref_ids = ref_ids;
// }
// const original_id = item.id;
// item = deepClone(mcomp);
// item.id = original_id;
// const meta: IMeta = {
// item,
// parent_item,
// idexed_scope: {},
// is_layout: arg.isLayout,
// };
// if (item.name.startsWith("⬅")) {
// arg.portal.in[item.name] = meta;
// }
// if (item.name.startsWith("⮕")) {
// arg.portal.out[item.name] = meta;
// }
// if (arg.each) arg.each(meta);
// p.meta[item.id] = meta;
// if (item_comp.props) {
// for (const [k, mprop] of Object.entries(item_comp.props)) {
// if (mprop.meta?.type === "content-element" && mprop.content) {
// walkMap(p, {
// isLayout: arg.isLayout,
// item: mprop.content,
// parent_item: { id: item.id },
// portal: arg.portal,
// parent_comp: { id: item.id, comp_id: item_comp.id },
// each: arg.each,
// });
// }
// }
// }
// for (const c of mcomp.childs) {
// walkMap(p, {
// isLayout: arg.isLayout,
// item: c,
// parent_item: { id: item.id },
// portal: arg.portal,
// parent_comp: { id: item.id, comp_id: item_comp.id },
// each: arg.each,
// });
// }
// }
// return;
// }
// const meta: IMeta = {
// item,
// parent_item,
// idexed_scope: {},
// parent_comp,
// is_layout: arg.isLayout,
// };
// if (item.name.startsWith("⬅")) {
// arg.portal.in[item.name] = meta;
// }
// if (item.name.startsWith("⮕")) {
// arg.portal.out[item.name] = meta;
// }
// if (arg.each) arg.each(meta);
// p.meta[item.id] = meta;
// if (item.type !== "text") {
// for (const c of item.childs) {
// if (c) {
// walkMap(p, {
// isLayout: arg.isLayout,
// item: c,
// parent_item: { id: item.id },
// portal: arg.portal,
// parent_comp,
// each: arg.each,
// });
// }
// }
// }
// };

View File

@ -1,122 +0,0 @@
import { NodeModel } from "@minoru/react-dnd-treeview";
import { compress, decompress } from "wasm-gzip";
import { MItem } from "../../../../utils/types/item";
import { DComp } from "../../../../utils/types/root";
import { IMeta, IScope, PG, active } from "../ed-global";
import { treeRebuild } from "./build";
import {
loadComponent,
loadcomp,
syncWalkLoad,
syncWalkMap,
} from "./sync-walk";
import { waitUntil } from "web-utils";
export const loadCompSnapshot = async (
p: PG,
id_comp: string,
snapshot: Uint8Array
) => {
const doc = new Y.Doc() as DComp;
Y.applyUpdate(doc as any, decompress(snapshot));
const mitem = doc.getMap("map").get("root");
if (mitem) {
if (typeof p.comp.list[id_comp]?.on_update === "function") {
doc.off("update", p.comp.list[id_comp].on_update);
}
p.comp.list[id_comp] = {
comp: { id: id_comp, snapshot },
doc,
} as any;
const { tree, meta } = await walkCompTree(p, mitem, id_comp);
p.comp.list[id_comp] = {
...p.comp.list[id_comp],
meta,
tree,
async on_update(bin, origin) {
if (origin === "sv_remote" || origin === "local") {
return;
}
const res = await p.sync.yjs.sv_local(
"comp",
id_comp,
Buffer.from(compress(bin))
);
if (res) {
const diff_local = Y.encodeStateAsUpdate(
doc as any,
decompress(res.sv)
);
Y.applyUpdate(doc as any, decompress(res.diff), "local");
const mitem = doc.getMap("map").get("root");
if (mitem) {
const { tree, meta } = await walkCompTree(p, mitem, id_comp);
p.comp.list[id_comp].tree = tree;
p.comp.list[id_comp].meta = meta;
await treeRebuild(p);
if (active.comp_id === id_comp) {
p.comp.tree = tree;
}
}
await p.sync.yjs.diff_local(
"comp",
id_comp,
Buffer.from(compress(diff_local))
);
p.render();
}
},
};
doc.on("update", p.comp.list[id_comp].on_update);
}
};
const walkCompTree = async (p: PG, mitem: MItem, comp_id: string) => {
const tree: NodeModel<IMeta>[] = [];
const meta = {};
const portal = {
in: {} as Record<string, IMeta>,
out: {} as Record<string, IMeta>,
};
syncWalkLoad(p, mitem, (id) => loadComponent(p, id));
mitem.doc?.transact(() => {
syncWalkMap(
{
note: "walk-comp",
comps: p.comp.list,
item_loading: p.ui.tree.item_loading,
meta,
tree,
component_not_found(id) {
setTimeout(() => {
if (loadcomp.pending.has(id) || p.comp.list[id]) {
waitUntil(() => !loadcomp.pending.has(id)).then(async () => {
walkCompTree(p, mitem, comp_id);
const { tree, meta } = await walkCompTree(p, mitem, comp_id);
p.comp.list[comp_id].tree = tree;
p.comp.list[comp_id].meta = meta;
p.render();
});
}
}, 100);
},
},
{
mitem,
is_layout: false,
parent_item: { id: "root" },
portal,
tree_root_id: "root",
}
);
});
return { tree, meta };
};

View File

@ -1,59 +0,0 @@
import { createId } from "@paralleldrive/cuid2";
import { TypedMap } from "yjs-types";
import { MItem } from "../../../../utils/types/item";
import {
FMCompDef,
FMComponent,
FNCompDef,
FNComponent,
} 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;
};
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<Record<string, FMCompDef>>,
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;
};

View File

@ -1,389 +0,0 @@
import { NodeModel } from "@minoru/react-dnd-treeview";
import { createId } from "@paralleldrive/cuid2";
import { TypedArray } from "yjs-types";
import { MContent } from "../../../../utils/types/general";
import { IItem, MItem } from "../../../../utils/types/item";
import { FNCompDef, FNComponent } from "../../../../utils/types/meta-fn";
import { MSection } from "../../../../utils/types/section";
import { IMeta, IScope, PG } from "../ed-global";
import { loadCompSnapshot } from "./sync-walk-comp";
import {
ensureMItemProps,
ensureMProp,
ensurePropContent,
} from "./sync-walk-utils";
const comp_added = new Set<string>();
export const syncWalkLoad = async (
p: PG,
mitem: MItem,
loadComponent: (id: string) => Promise<boolean>
) => {
const mcomp = mitem.get("component");
if (mcomp) {
const id = mcomp.get("id");
if (id && !comp_added.has(id)) {
comp_added.add(id);
const comp = mcomp.toJSON() as FNComponent;
if (!p.comp.list[id]) {
loadComponent(comp.id);
}
const pcomp = p.comp.list[id];
if (pcomp) {
const pitem = pcomp.doc.getMap("map").get("root");
if (pitem) {
await syncWalkLoad(p, pitem, loadComponent);
}
}
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 syncWalkLoad(p, mcontent, loadComponent);
}
}
}
}
}
}
for (const e of mitem.get("childs")?.map((e) => e) || []) {
await syncWalkLoad(p, e, loadComponent);
}
};
export const syncWalkMap = (
p: {
note?: string;
item_loading: PG["ui"]["tree"]["item_loading"];
tree?: NodeModel<IMeta>[];
comps: PG["comp"]["list"];
meta: Record<string, IMeta>;
component_not_found?: (comp_id: string) => void;
scope?: null | IScope;
},
arg: {
is_layout: boolean;
mitem: MItem | MSection;
portal: {
in: Record<string, IMeta>;
out: Record<string, IMeta>;
};
parent_item: IMeta["parent_item"];
parent_mcomp?: IMeta["parent_mcomp"];
jsx_prop_name?: string;
jsx_prop_root?: boolean;
skip_add_tree?: boolean;
tree_root_id: string;
each?: (meta: IMeta) => void;
}
) => {
const { mitem, parent_item } = arg;
if (typeof mitem.get !== "function") {
return;
}
const item = {} as unknown as IItem;
let override_id = "";
const id = mitem.get("id");
let skip_tree = arg.skip_add_tree;
let skip_tree_child = skip_tree;
if (id && p.item_loading.includes(id)) {
skip_tree_child = true;
}
let mapped = false;
if (arg.parent_mcomp && id) {
const fcomp = arg.parent_mcomp.minstance.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, ref_ids.toJSON());
mapped = true;
}
}
}
if (!mapped) {
mapItem(mitem, item);
}
if (typeof item.name !== "string") return;
if (override_id) {
if (!item.originalId) item.originalId = item.id;
item.id = override_id;
}
if (arg.jsx_prop_name) {
const pitem = p.meta[arg.parent_item.id].item;
if (pitem.type === "item" && pitem.component) {
const pprop = pitem.component.props[arg.jsx_prop_name];
if (pprop.content) {
pprop.content.id = item.id;
}
}
}
const item_comp = item.component;
const mitem_comp = mitem.get("component");
const metaNotFound = () => {
if (!skip_tree && p.tree) {
p.tree.push({
id: item.id,
parent: arg.tree_root_id === parent_item.id ? "root" : parent_item.id,
text: item.name,
});
}
};
if (item_comp && item_comp.id && parent_item.id !== "root") {
if (!p.comps[item_comp.id]) {
if (p.component_not_found) {
p.component_not_found(item_comp.id);
}
}
let ref_comp = p.comps[item_comp.id];
if (ref_comp && mitem_comp) {
const mcomp = ref_comp.doc.getMap("map").get("root");
const minstance = arg.parent_mcomp
? arg.parent_mcomp.minstance
: (mitem as MItem);
let mref_ids = minstance.get("component")?.get("ref_ids");
if (!mref_ids) {
minstance.get("component")?.set("ref_ids", new Y.Map() as any);
mref_ids = minstance.get("component")?.get("ref_ids");
}
if (mcomp) {
const old_id = item.id;
const ref_ids = mref_ids?.toJSON() || {};
mapItem(mcomp, item, ref_ids);
item.id = old_id;
const meta: IMeta = {
item,
mitem: mitem as MItem,
parent_item,
parent_mcomp: arg.parent_mcomp,
indexed_scope: {},
is_layout: arg.is_layout,
};
if (item.name.startsWith("⬅")) {
arg.portal.in[item.name] = meta;
}
if (item.name.startsWith("⮕")) {
arg.portal.out[item.name] = meta;
}
if (arg.each) arg.each(meta);
p.meta[item.id] = meta;
if (!skip_tree && p.tree) {
p.tree.push({
id: item.id,
parent:
arg.tree_root_id === parent_item.id ? "root" : parent_item.id,
text: item.name,
data: meta,
});
}
const mprops = mcomp.get("component")?.get("props")?.toJSON() as Record<
string,
FNCompDef
>;
const propvis = {};
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);
if (mprop) {
item_comp.props[k] = mprop.toJSON() as FNCompDef;
if (meta.item.type === "item" && meta.item.component) {
meta.item.component.props[k] = item_comp.props[k];
}
if (mprop && v.meta?.type === "content-element") {
const mcontent = ensurePropContent(mprop, k);
item_comp.props[k].content = mcontent?.toJSON() as IItem;
if (meta.item.type === "item" && meta.item.component) {
meta.item.component.props[k].content =
item_comp.props[k].content;
}
if (mcontent) {
syncWalkMap(p, {
is_layout: arg.is_layout,
tree_root_id: arg.tree_root_id,
mitem: mcontent,
jsx_prop_name: k,
jsx_prop_root: true,
parent_mcomp: { minstance, meta, mcomp },
parent_item: { id: item.id, mitem: mitem as MItem },
portal: arg.portal,
skip_add_tree: skip_tree_child,
each: arg.each,
});
}
}
}
}
}
}
}
const childs = mcomp.get("childs")?.map((e) => e) || [];
for (const e of childs) {
syncWalkMap(p, {
is_layout: arg.is_layout,
tree_root_id: arg.tree_root_id,
mitem: e,
parent_item: { id: item.id, mitem: mitem as MItem },
parent_mcomp: { minstance, meta, mcomp },
skip_add_tree: true,
portal: arg.portal,
each: arg.each,
});
}
return;
}
}
metaNotFound();
return;
}
const meta: IMeta = {
is_layout: arg.is_layout,
item,
jsx_prop_name: arg.jsx_prop_name,
jsx_prop_root: arg.jsx_prop_root,
mitem: mitem as MItem,
parent_item,
parent_mcomp: arg.parent_mcomp,
indexed_scope: {},
};
if (item.name.startsWith("⬅")) {
arg.portal.in[item.name] = meta;
}
if (item.name.startsWith("⮕")) {
arg.portal.out[item.name] = meta;
}
if (arg.each) arg.each(meta);
p.meta[item.id] = meta;
if (!skip_tree && p.tree) {
p.tree.push({
id: item.id,
parent: arg.tree_root_id === parent_item.id ? "root" : parent_item.id,
text: item.name,
data: meta,
});
}
const childs = mitem.get("childs")?.map((e) => e) || [];
for (const e of childs) {
syncWalkMap(p, {
is_layout: arg.is_layout,
tree_root_id: arg.tree_root_id,
mitem: e,
jsx_prop_name: arg.jsx_prop_name,
parent_item: { id: item.id, mitem: mitem as MItem },
parent_mcomp: arg.parent_mcomp,
portal: arg.portal,
skip_add_tree: skip_tree_child,
each: arg.each,
});
}
};
export const loadcomp = {
timeout: 0 as any,
pending: new Set<string>(),
};
export const loadComponent = async (p: PG, id_comp: string) => {
return new Promise<boolean>((resolve) => {
if (p.comp.list[id_comp]) {
resolve(true);
return;
}
loadcomp.pending.add(id_comp);
clearTimeout(loadcomp.timeout);
loadcomp.timeout = setTimeout(async () => {
const comps = await p.sync.comp.load([...loadcomp.pending]);
let result = Object.entries(comps);
for (const [id_comp, comp] of result) {
for (const cur of Object.values(comp)) {
if (cur && cur.snapshot) {
await loadCompSnapshot(p, id_comp, cur.snapshot, cur.scope);
}
}
}
loadcomp.pending.clear();
resolve(result.length > 0);
}, 150);
});
};
const mapItem = (
mitem: MContent,
item: any,
ref_ids?: Record<string, string>
) => {
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;
}
}
if (k !== "originalId") item[k] = val;
} else {
item[k] = [];
const childs = e as unknown as TypedArray<{}>;
childs.forEach((c) => {
if (typeof c.get === "function") {
if (ref_ids) {
const id = ref_ids[c.get("id")];
if (id) {
item[k].push({ id });
}
} else {
item[k].push({ id: c.get("id") });
}
}
});
}
});
};

View File

@ -7,7 +7,6 @@ import { ISection, MSection } from "../../../../../utils/types/section";
import { EDGlobal, active } from "../../../logic/ed-global";
import { getMetaById } from "../../../logic/tree/build";
import { fillID } from "../../../logic/tree/fill-id";
import { loadComponent } from "../../../logic/tree/sync-walk";
import { TopBtn } from "../top-btn";
export const EdCompPicker = () => {
@ -19,7 +18,7 @@ export const EdCompPicker = () => {
p.ui.popup.comp.open = async (comp_id) => {
let comp_ref = p.comp.list[comp_id];
if (!comp_ref) {
await loadComponent(p, comp_id);
// await loadComponent(p, comp_id);
comp_ref = p.comp.list[comp_id];
}

View File

@ -4,7 +4,7 @@ import { produceCSS } from "../../../../../utils/css/gen";
import { IItem } from "../../../../../utils/types/item";
import { IText } from "../../../../../utils/types/text";
import { EDGlobal, PG, active } from "../../../logic/ed-global";
import { loadComponent } from "../../../logic/tree/sync-walk";
// import { loadComponent } from "../../../logic/tree/sync-walk";
import { EdCompPreviewTree } from "./comp-preview-tree";
import { compPicker, reloadCompPicker } from "./comp-reload";
@ -19,9 +19,9 @@ export const EdCompPreview = () => {
useEffect(() => {
if (!p.comp.list[comp_id] && !!comp_id) {
loadComponent(p, comp_id).then(() => {
p.render();
});
// loadComponent(p, comp_id).then(() => {
// p.render();
// });
}
}, [comp_id]);