wip fix load component

This commit is contained in:
Rizky 2023-11-24 18:41:56 +07:00
parent da1bc214a1
commit b5b018084b
7 changed files with 97 additions and 60 deletions

View File

@ -2,7 +2,7 @@ import { component, page } from "dbgen";
import { import {
EPage, EPage,
ESite, ESite,
IScopeComp IScopeComp,
} from "../../../web/src/nova/ed/logic/ed-global"; } from "../../../web/src/nova/ed/logic/ed-global";
import { IItem } from "../../../web/src/utils/types/item"; import { IItem } from "../../../web/src/utils/types/item";
import { site_group } from "./actions/site_group"; import { site_group } from "./actions/site_group";
@ -44,7 +44,7 @@ export const SyncActions = {
({}) as Record<string, Exclude<component, "content_tree">>, ({}) as Record<string, Exclude<component, "content_tree">>,
group: async (id_site: string) => group: async (id_site: string) =>
({}) as Record<string, { id: string; name: string; comps: string[] }>, ({}) as Record<string, { id: string; name: string; comps: string[] }>,
load: async (id: string) => ({}) as IScopeComp | void, load: async (ids: string[]) => ({}) as Record<string, IScopeComp>,
}, },
page: { page: {
list: async (id_site: string) => list: async (id_site: string) =>

View File

@ -9,14 +9,18 @@ import { SyncConnection } from "../type";
export const comp_load: SAction["comp"]["load"] = async function ( export const comp_load: SAction["comp"]["load"] = async function (
this: SyncConnection, this: SyncConnection,
id: string ids: string[]
) { ) {
const root = await loadComponent(id, this); const result: Record<string, IScopeComp> = {};
for (const id of ids) {
const root = await loadComponent(id, this);
let ref = docs.comp[id]; let ref = docs.comp[id];
if (ref) { if (ref) {
return scanMeta(id, ref.doc, this); result[id] = await scanMeta(id, ref.doc, this);
}
} }
return result;
}; };
const scanMeta = async (id: string, doc: DComp, sync: SyncConnection) => { const scanMeta = async (id: string, doc: DComp, sync: SyncConnection) => {

View File

@ -32,12 +32,12 @@ export const edRoute = async (p: PG) => {
p.page.doc = cur.doc; p.page.doc = cur.doc;
} }
await reloadPage(p, params.page_id); await reloadPage(p, params.page_id, "load-route");
} }
} }
}; };
export const reloadPage = async (p: PG, page_id: string) => { export const reloadPage = async (p: PG, page_id: string, note: string) => {
p.status = "loading"; p.status = "loading";
const remotePage = await p.sync.page.load(page_id); const remotePage = await p.sync.page.load(page_id);
@ -51,7 +51,6 @@ export const reloadPage = async (p: PG, page_id: string) => {
if (remotePage.scope_comps) { if (remotePage.scope_comps) {
for (const [id_comp, c] of Object.entries(remotePage.scope_comps)) { for (const [id_comp, c] of Object.entries(remotePage.scope_comps)) {
if (c && c.snapshot) { if (c && c.snapshot) {
await loadCompSnapshot( await loadCompSnapshot(
p, p,
id_comp, id_comp,
@ -93,7 +92,7 @@ export const reloadPage = async (p: PG, page_id: string) => {
decompress(res.sv) decompress(res.sv)
); );
Y.applyUpdate(doc as any, decompress(res.diff), "local"); Y.applyUpdate(doc as any, decompress(res.diff), "local");
await treeRebuild(p); await treeRebuild(p, { note: "page-on-update" });
await p.sync.yjs.diff_local( await p.sync.yjs.diff_local(
"page", "page",
@ -114,7 +113,7 @@ export const reloadPage = async (p: PG, page_id: string) => {
} }
if (p.page.doc) { if (p.page.doc) {
await treeRebuild(p); await treeRebuild(p, { note: "reload-page-init" });
} }
} }
p.status = "ready"; p.status = "ready";

View File

@ -13,7 +13,7 @@ export const loadSite = async (p: PG, site: ESite) => {
} }
if (site.layout.id) { if (site.layout.id) {
await reloadPage(p, site.layout.id); await reloadPage(p, site.layout.id, "load-layout");
} }
} }
}; };

View File

@ -125,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, params.page_id); await reloadPage(p, params.page_id, "editor-start");
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());
@ -154,28 +154,31 @@ export const edInitSync = (p: PG) => {
p.render(); p.render();
}, },
async remote_svlocal(data) { async remote_svlocal(data) {
if (p[data.type].cur.id === data.id) { let doc = null as any;
const doc = p[data.type].doc as Y.Doc; if (data.type === "page" && p.page.cur.id === data.id) {
doc = p.page.doc as Y.Doc;
} else if (data.type === "comp" && p.comp.list[data.id]) {
doc = p.comp.list[data.id].doc;
}
if (doc) { if (doc) {
const diff_remote = Y.encodeStateAsUpdate( const diff_remote = Y.encodeStateAsUpdate(
doc, doc,
decompress(data.sv_local) decompress(data.sv_local)
); );
const sv_remote = Y.encodeStateVector(doc); const sv_remote = Y.encodeStateVector(doc);
const sv = Buffer.from(compress(sv_remote)); const sv = Buffer.from(compress(sv_remote));
const diff = Buffer.from(compress(diff_remote)); const diff = Buffer.from(compress(diff_remote));
const res = await p.sync.yjs.sv_remote( const res = await p.sync.yjs.sv_remote(
data.type, data.type,
data.id, data.id,
sv, sv,
diff diff
); );
if (res) { if (res) {
Y.applyUpdate(doc, decompress(res.diff), "sv_remote"); Y.applyUpdate(doc, decompress(res.diff), "sv_remote");
await treeRebuild(p, { note: "sv_remote" }); await treeRebuild(p, { note: "sv_remote" });
}
} }
} }
}, },

View File

@ -1,5 +1,10 @@
import { EdMeta, PG } from "../ed-global"; import { EdMeta, PG } from "../ed-global";
import { loadComponent, syncWalkLoad, syncWalkMap } from "./sync-walk"; import {
component,
loadComponent,
syncWalkLoad,
syncWalkMap,
} from "./sync-walk";
export const compLoaded = new Set<string>(); export const compLoaded = new Set<string>();
@ -16,24 +21,13 @@ export const treeRebuild = async (p: PG, arg?: { note?: string }) => {
p.page.tree = []; p.page.tree = [];
p.page.meta = {}; p.page.meta = {};
const sections = root.get("childs");
if (sections) {
await Promise.all(
sections.map((e) => {
return syncWalkLoad(p, e, compLoaded, (id) => {
return loadComponent(p, id, compLoaded);
});
})
);
}
const portal = { const portal = {
in: {} as Record<string, EdMeta>, in: {} as Record<string, EdMeta>,
out: {} as Record<string, EdMeta>, out: {} as Record<string, EdMeta>,
}; };
let root_id = "root"; let root_id = "root";
if (p.site.layout) { if (p.site.layout && p.site.layout.id !== p.page.cur.id) {
const ldoc = p.page.list[p.site.layout.id]; const ldoc = p.page.list[p.site.layout.id];
if (ldoc) { if (ldoc) {
const lroot = ldoc.doc.getMap("map").get("root"); const lroot = ldoc.doc.getMap("map").get("root");
@ -49,6 +43,8 @@ export const treeRebuild = async (p: PG, arg?: { note?: string }) => {
}) })
); );
if (component.pending) await component.pending;
sections.map((e) => { sections.map((e) => {
if (root_id === "root") { if (root_id === "root") {
p.page.entry.push(e.get("id")); p.page.entry.push(e.get("id"));
@ -100,6 +96,19 @@ export const treeRebuild = async (p: PG, arg?: { note?: string }) => {
} }
} }
const sections = root.get("childs");
if (sections) {
await Promise.all(
sections.map((e) => {
return syncWalkLoad(p, e, compLoaded, (id) => {
return loadComponent(p, id, compLoaded);
});
})
);
if (component.pending) await component.pending;
}
doc.transact(async () => { doc.transact(async () => {
const sections = root.get("childs"); const sections = root.get("childs");
if (sections) { if (sections) {

View File

@ -13,7 +13,6 @@ import {
ensureMProp, ensureMProp,
ensurePropContent, ensurePropContent,
} from "./sync-walk-utils"; } from "./sync-walk-utils";
import { waitUntil } from "web-utils";
export const syncWalkLoad = async ( export const syncWalkLoad = async (
p: PG, p: PG,
@ -28,8 +27,8 @@ export const syncWalkLoad = async (
if (id) { if (id) {
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] && isFirstLoaded) {
await loadComponent(comp.id); loadComponent(comp.id);
} }
const pcomp = p.comp.list[id]; const pcomp = p.comp.list[id];
@ -320,22 +319,45 @@ export const loadCompSnapshot = async (
} }
}; };
const loadcomp = { timeout: 0 as any, pending: new Set<string>() };
export const component = {
pending: null as null | Promise<void>,
resolve: null as null | (() => void),
};
export const loadComponent = async ( export const loadComponent = async (
p: PG, p: PG,
id_comp: string, id_comp: string,
loaded: Set<string> loaded: Set<string>
) => { ) => {
const comps = await p.sync.comp.load(id_comp); if (!component.pending) {
component.pending = new Promise((resolve) => {
if (comps) { component.resolve = resolve;
for (const cur of Object.values(comps)) { });
if (cur && cur.snapshot) {
await loadCompSnapshot(p, id_comp, loaded, cur.snapshot, cur.scope);
}
}
return true;
} }
return false;
return new Promise<boolean>((resolve) => {
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);
loadcomp.pending.clear();
for (const [id_comp, comp] of result) {
for (const cur of Object.values(comp)) {
if (cur && cur.snapshot) {
await loadCompSnapshot(p, id_comp, loaded, cur.snapshot, cur.scope);
}
}
}
resolve(result.length > 0);
if (component.resolve) {
component.resolve();
component.pending = null;
component.resolve = null;
}
}, 150);
});
}; };
const mapItem = (mitem: MContent, item: any) => { const mapItem = (mitem: MContent, item: any) => {