wip fix layout live change

This commit is contained in:
Rizky 2023-11-24 06:30:55 +07:00
parent 7eada6fde4
commit a296b35eff
8 changed files with 126 additions and 59 deletions

View File

@ -1,5 +1,4 @@
import { IScopeComp } from "../../../../web/src/nova/ed/logic/ed-global"; import { IScopeComp } from "../../../../web/src/nova/ed/logic/ed-global";
import { MItem } from "../../../../web/src/utils/types/item";
import { DComp } from "../../../../web/src/utils/types/root"; import { DComp } from "../../../../web/src/utils/types/root";
import { SAction } from "../actions"; import { SAction } from "../actions";
import { loadComponent } from "../editor/load-component"; import { loadComponent } from "../editor/load-component";

View File

@ -21,15 +21,14 @@ export const site_load: SAction["site"]["load"] = async function (
activity.site.room(site.id).join({ ws: this.ws }); activity.site.room(site.id).join({ ws: this.ws });
let layout = undefined; const layout = await db.page.findFirst({
const _layout = await db.page.findFirst({
where: { where: {
id_site: id, id_site: id,
is_deleted: false, is_deleted: false,
is_default_layout: true, is_default_layout: true,
}, },
select: { id: true },
}); });
if (_layout) layout = _layout.content_tree as IRoot;
return { return {
id: site.id, id: site.id,
@ -38,7 +37,7 @@ export const site_load: SAction["site"]["load"] = async function (
domain: site.domain, domain: site.domain,
js: site.js || "", js: site.js || "",
js_compiled: site.js_compiled || "", js_compiled: site.js_compiled || "",
layout, layout: { id: layout?.id || "" },
}; };
} }
} }

View File

@ -5,7 +5,7 @@ import { SAction } from "../../../../../srv/ws/sync/actions";
import { parseJs } from "../../../../../srv/ws/sync/editor/parser/parse-js"; import { parseJs } from "../../../../../srv/ws/sync/editor/parser/parse-js";
import { clientStartSync } from "../../../utils/sync/ws-client"; import { clientStartSync } from "../../../utils/sync/ws-client";
import { IItem, MItem } from "../../../utils/types/item"; import { IItem, MItem } from "../../../utils/types/item";
import { DComp, DPage, IRoot } from "../../../utils/types/root"; import { DComp, DPage } from "../../../utils/types/root";
import { ISection } from "../../../utils/types/section"; import { ISection } from "../../../utils/types/section";
import { IText, MText } from "../../../utils/types/text"; import { IText, MText } from "../../../utils/types/text";
@ -16,7 +16,7 @@ export const EmptySite = {
config: { api_url: "" }, config: { api_url: "" },
js: "", js: "",
js_compiled: "", js_compiled: "",
layout: undefined as undefined | IRoot, layout: { snapshot: null as null | Uint8Array, id: "" },
}; };
export type ESite = typeof EmptySite; export type ESite = typeof EmptySite;
@ -114,8 +114,14 @@ export const EDGlobal = {
page: { page: {
cur: EmptyPage, cur: EmptyPage,
doc: null as null | DPage, doc: null as null | DPage,
doc_on_update: async (bin: Uint8Array, origin: any) => {}, list: {} as Record<
list: {} as Record<string, { page: EPage; doc: DPage }>, string,
{
page: EPage;
doc: DPage;
on_update?: (bin: Uint8Array, origin: any) => Promise<void>;
}
>,
building: false, building: false,
meta: {} as Record<string, EdMeta>, meta: {} as Record<string, EdMeta>,
entry: [] as string[], entry: [] as string[],

View File

@ -3,6 +3,7 @@ import { IItem } from "../../../utils/types/item";
import { DComp } from "../../../utils/types/root"; import { DComp } from "../../../utils/types/root";
import { PG } from "./ed-global"; import { PG } from "./ed-global";
import { treeRebuild } from "./tree/build"; import { treeRebuild } from "./tree/build";
import { loadSite } from "./ed-site";
export const edRoute = async (p: PG) => { export const edRoute = async (p: PG) => {
if (p.status === "ready" || p.status === "init") { if (p.status === "ready" || p.status === "init") {
@ -15,7 +16,7 @@ export const edRoute = async (p: PG) => {
return; return;
} }
p.site = site; await loadSite(p, site);
} }
if ( if (
@ -23,22 +24,23 @@ export const edRoute = async (p: PG) => {
!p.page.cur.snapshot || !p.page.cur.snapshot ||
!p.page.list[p.page.cur.id] !p.page.list[p.page.cur.id]
) { ) {
if (p.page.list[params.page_id] && p.page.doc) { const page = p.page.list[params.page_id];
p.page.doc.off("update", p.page.doc_on_update); if (page && p.page.doc && page.on_update) {
p.page.doc.off("update", page.on_update);
const cur = p.page.list[params.page_id]; const cur = p.page.list[params.page_id];
p.page.cur = cur.page; p.page.cur = cur.page;
p.page.doc = cur.doc; p.page.doc = cur.doc;
} }
await reloadPage(p); await reloadPage(p, params.page_id);
} }
} }
}; };
export const reloadPage = async (p: PG) => { export const reloadPage = async (p: PG, page_id: string) => {
p.status = "loading"; p.status = "loading";
const remotePage = await p.sync.page.load(params.page_id); const remotePage = await p.sync.page.load(page_id);
if (!remotePage) { if (!remotePage) {
p.status = "page-not-found"; p.status = "page-not-found";
@ -66,7 +68,17 @@ export const reloadPage = async (p: PG) => {
const doc = new Y.Doc(); const doc = new Y.Doc();
Y.applyUpdate(doc, decompress(remotePage.snapshot)); Y.applyUpdate(doc, decompress(remotePage.snapshot));
p.page.doc_on_update = async (bin: Uint8Array, origin: any) => { let page = p.page.list[remotePage.id];
if (!page) {
p.page.list[remotePage.id] = {} as any;
page = p.page.list[remotePage.id];
}
if (page.on_update && page.doc) {
page.doc.off("update", page.on_update);
}
page.on_update = async (bin: Uint8Array, origin: any) => {
if (origin === "sv_remote" || origin === "local") return; if (origin === "sv_remote" || origin === "local") return;
const res = await p.sync.yjs.sv_local( const res = await p.sync.yjs.sv_local(
@ -93,14 +105,12 @@ export const reloadPage = async (p: PG) => {
} }
}; };
doc.on("update", p.page.doc_on_update); doc.on("update", page.on_update);
p.page.doc = doc as any; p.page.doc = doc as any;
if (p.page.doc) { if (p.page.doc) {
p.page.list[remotePage.id] = { page.page = p.page.cur;
page: p.page.cur, page.doc = p.page.doc;
doc: p.page.doc,
};
} }
if (p.page.doc) { if (p.page.doc) {

View File

@ -0,0 +1,19 @@
import { ESite, PG } from "./ed-global";
import { reloadPage } from "./ed-route";
export const loadSite = async (p: PG, site: ESite) => {
const old_layout_id = p.site.layout.id;
const layout_changed = p.site.layout.id !== site.layout.id;
p.site = site;
if (layout_changed) {
const old_layout = p.page.list[old_layout_id];
if (old_layout && old_layout.on_update) {
old_layout.doc.off("update", old_layout.on_update);
}
if (site.layout.id) {
await reloadPage(p, site.layout.id);
}
}
};

View File

@ -8,6 +8,7 @@ import { EmptySite, PG } from "./ed-global";
import { treeRebuild } from "./tree/build"; import { treeRebuild } from "./tree/build";
import { evalCJS } from "../../view/logic/load-code"; import { evalCJS } from "../../view/logic/load-code";
import { reloadPage } from "./ed-route"; import { reloadPage } from "./ed-route";
import { loadSite } from "./ed-site";
const decoder = new TextDecoder(); const decoder = new TextDecoder();
@ -28,9 +29,9 @@ export const edInitSync = (p: PG) => {
p.site = deepClone(EmptySite); p.site = deepClone(EmptySite);
p.site.id = "--loading--"; p.site.id = "--loading--";
p.ui.popup.code.init = false; p.ui.popup.code.init = false;
p.sync.site.load(params.site_id).then((site) => { p.sync.site.load(params.site_id).then(async (site) => {
if (site) { if (site) {
p.site = site; await loadSite(p, site);
p.render(); p.render();
} else { } else {
alert("Site not found. redirecting..."); alert("Site not found. redirecting...");
@ -124,7 +125,7 @@ export const edInitSync = (p: PG) => {
}, },
async editor_start(e) { async editor_start(e) {
if (p.ui.syncing) { if (p.ui.syncing) {
await reloadPage(p); await reloadPage(p, params.page_id);
if (p.page.doc) { if (p.page.doc) {
p.page.doc.transact(() => { p.page.doc.transact(() => {
p.page.doc?.getMap("map").set("ts", Date.now()); p.page.doc?.getMap("map").set("ts", Date.now());

View File

@ -20,7 +20,9 @@ export const treeRebuild = async (p: PG, arg?: { note?: string }) => {
const loaded = new Set<string>(); const loaded = new Set<string>();
await Promise.all( await Promise.all(
sections.map((e) => { sections.map((e) => {
return syncWalkLoad(p, e, loaded); return syncWalkLoad(p, e, loaded, (id) => {
return loadComponent(p, id);
});
}) })
); );
} }
@ -32,29 +34,52 @@ export const treeRebuild = async (p: PG, arg?: { note?: string }) => {
let root_id = "root"; let root_id = "root";
if (p.site.layout) { if (p.site.layout) {
const ldoc = p.page.list[p.site.layout.id];
if (ldoc) {
const lroot = ldoc.doc.getMap("map").get("root");
if (lroot) {
const sections = lroot.get("childs");
if (sections) {
const loaded = new Set<string>(); const loaded = new Set<string>();
await Promise.all( await Promise.all(
p.site.layout.childs.map((e) => sections.map((e) => {
walkLoad(p.comp, e, loaded, (id) => loadComponent(p, id)) return syncWalkLoad(p, e, loaded, (id) => {
) return loadComponent(p, id);
});
})
); );
p.site.layout.childs.map((e) => {
p.page.entry.push(e.id); sections.map((e) => {
walkMap( if (root_id === "root") {
{ meta: p.page.meta, comps: p.comp.map }, p.page.entry.push(e.get("id"));
{ }
isLayout: true, syncWalkMap(p, {
item: e, isLayout: false,
parent_item: { id: "root" }, mitem: e,
parent_item: { id: root_id },
tree_root_id: root_id,
portal, portal,
each(meta) { each(meta) {
if (meta.item.name === "content") { if (meta.item.name === "content") {
root_id = meta.item.id; root_id = meta.item.id;
} }
}, },
}
);
}); });
});
for (const [k, portal_out] of Object.entries(portal.out)) {
const name = k.replace(/⮕/gi, "").trim();
const portal_in = portal.in[`${name}`];
if (portal_in) {
for (const key of Object.keys(portal_in)) {
delete (portal_in as any)[key];
}
for (const [k, v] of Object.entries(portal_out)) {
(portal_in as any)[k] = v;
}
}
}
}
// if root_id is root, it means content is not found. // if root_id is root, it means content is not found.
// if content is not found, do not use layout. // if content is not found, do not use layout.
@ -64,6 +89,8 @@ export const treeRebuild = async (p: PG, arg?: { note?: string }) => {
p.page.meta = {}; p.page.meta = {};
} }
} }
}
}
doc.transact(async () => { doc.transact(async () => {
const sections = root.get("childs"); const sections = root.get("childs");

View File

@ -16,7 +16,8 @@ import {
export const syncWalkLoad = async ( export const syncWalkLoad = async (
p: PG, p: PG,
mitem: MItem, mitem: MItem,
loaded: Set<string> loaded: Set<string>,
loadComponent: (id: string) => Promise<boolean>
) => { ) => {
const mcomp = mitem.get("component"); const mcomp = mitem.get("component");
if (mcomp) { if (mcomp) {
@ -26,14 +27,14 @@ export const syncWalkLoad = async (
const isFirstLoaded = !loaded.has(id); const isFirstLoaded = !loaded.has(id);
loaded.add(id); loaded.add(id);
if (!p.comp.list[id]) { if (!p.comp.list[id]) {
await loadComponent(p, comp.id); await loadComponent(comp.id);
} }
const pcomp = p.comp.list[id]; const pcomp = p.comp.list[id];
if (pcomp) { if (pcomp) {
const pitem = pcomp.doc.getMap("map").get("root"); const pitem = pcomp.doc.getMap("map").get("root");
if (pitem && isFirstLoaded) { if (pitem && isFirstLoaded) {
await syncWalkLoad(p, pitem, loaded); await syncWalkLoad(p, pitem, loaded, loadComponent);
} }
} }
} }
@ -44,7 +45,7 @@ export const syncWalkLoad = async (
if (mprop) { if (mprop) {
const mcontent = ensurePropContent(mprop, propName); const mcontent = ensurePropContent(mprop, propName);
if (mcontent) { if (mcontent) {
await syncWalkLoad(p, mcontent, loaded); await syncWalkLoad(p, mcontent, loaded, loadComponent);
} }
} }
} }
@ -52,7 +53,7 @@ export const syncWalkLoad = async (
} }
for (const e of mitem.get("childs")?.map((e) => e) || []) { for (const e of mitem.get("childs")?.map((e) => e) || []) {
await syncWalkLoad(p, e, loaded); await syncWalkLoad(p, e, loaded, loadComponent);
} }
}; };
@ -69,6 +70,7 @@ export const syncWalkMap = (
parent_mcomp?: EdMeta["parent_mcomp"]; parent_mcomp?: EdMeta["parent_mcomp"];
skip_add_tree?: boolean; skip_add_tree?: boolean;
tree_root_id: string; tree_root_id: string;
each?: (meta: EdMeta) => void;
} }
) => { ) => {
const { mitem, parent_item, parent_mcomp } = arg; const { mitem, parent_item, parent_mcomp } = arg;
@ -153,6 +155,8 @@ export const syncWalkMap = (
if (item.name.startsWith("⮕")) { if (item.name.startsWith("⮕")) {
arg.portal.out[item.name] = meta; arg.portal.out[item.name] = meta;
} }
if (arg.each) arg.each(meta);
p.page.meta[item.id] = meta; p.page.meta[item.id] = meta;
if (!skip_tree) { if (!skip_tree) {
@ -231,6 +235,8 @@ export const syncWalkMap = (
if (item.name.startsWith("⮕")) { if (item.name.startsWith("⮕")) {
arg.portal.out[item.name] = meta; arg.portal.out[item.name] = meta;
} }
if (arg.each) arg.each(meta);
p.page.meta[item.id] = meta; p.page.meta[item.id] = meta;
if (!skip_tree) { if (!skip_tree) {