diff --git a/app/srv/ws/sync/actions.ts b/app/srv/ws/sync/actions.ts index d9071d68..9a563332 100644 --- a/app/srv/ws/sync/actions.ts +++ b/app/srv/ws/sync/actions.ts @@ -1,5 +1,6 @@ import { component, page } from "dbgen"; import { + EComp, EPage, ESite, IScopeComp, @@ -45,7 +46,8 @@ export const SyncActions = { ({}) as Record>, group: async (id_site: string) => ({}) as Record, - load: async (ids: string[]) => ({}) as Record, + load: async (ids: string[], sync?: boolean) => + ({}) as Record, }, page: { list: async (id_site: string) => diff --git a/app/srv/ws/sync/actions/comp_load.ts b/app/srv/ws/sync/actions/comp_load.ts index 3967f13c..9339e90f 100644 --- a/app/srv/ws/sync/actions/comp_load.ts +++ b/app/srv/ws/sync/actions/comp_load.ts @@ -1,17 +1,42 @@ -import { IScopeComp } from "../../../../web/src/nova/ed/logic/ed-global"; +import { EComp } from "../../../../web/src/nova/ed/logic/ed-global"; import { DComp } from "../../../../web/src/utils/types/root"; import { SAction } from "../actions"; -import { loadComponent } from "../editor/load-component"; +import { loadComponent, userSyncComponent } from "../editor/load-component"; import { docs } from "../entity/docs"; +import { snapshot } from "../entity/snapshot"; import { gzipAsync } from "../entity/zlib"; import { SyncConnection } from "../type"; export const comp_load: SAction["comp"]["load"] = async function ( this: SyncConnection, - ids: string[] + comp_ids: string[], + sync ) { - const result: Record = {}; - for (const id of ids) { + const result: Record = {}; + const loading = {} as Record>; + + for (const id of comp_ids) { + if (!docs.comp[id]) { + if (typeof loading[id] === "undefined") { + loading[id] = new Promise(async (resolve) => { + await loadComponent(id, sync ? this : undefined); + resolve(); + }); + } + await loading[id]; + } else { + if (sync) { + userSyncComponent(this, id); + } + } + + const snap = snapshot.get("comp", id); + if (snap) { + result[id] = { + id, + snapshot: await gzipAsync(snap.bin), + }; + } } return result; }; diff --git a/app/srv/ws/sync/editor/load-component.ts b/app/srv/ws/sync/editor/load-component.ts index 74baefbc..0e25e356 100644 --- a/app/srv/ws/sync/editor/load-component.ts +++ b/app/srv/ws/sync/editor/load-component.ts @@ -6,12 +6,10 @@ import { gzipAsync } from "../entity/zlib"; import { sendWS } from "../sync-handler"; import { SyncConnection, SyncType } from "../type"; -export const loadComponent = async (comp_id: string, sync: SyncConnection) => { +export const loadComponent = async (comp_id: string, sync?: SyncConnection) => { let snap = snapshot.get("comp", comp_id); let ydoc = docs.comp[comp_id]; - const conf = sync.conf; - - if (!conf) return undefined; + const conf = sync?.conf; const createUndoManager = async (root: Y.Map) => { const um = new Y.UndoManager(root, { @@ -80,14 +78,16 @@ export const loadComponent = async (comp_id: string, sync: SyncConnection) => { id_doc: doc.clientID, }); - user.active.add({ - ...defaultActive, - client_id: sync.client_id, - user_id: sync.user_id, - site_id: conf.site_id, - page_id: conf.page_id, - comp_id: comp.id, - }); + if (sync && sync.conf) { + user.active.add({ + ...defaultActive, + client_id: sync.client_id, + user_id: sync.user_id, + site_id: sync.conf.site_id, + page_id: sync.conf.page_id, + comp_id: comp.id, + }); + } return { id: comp_id, @@ -110,14 +110,16 @@ export const loadComponent = async (comp_id: string, sync: SyncConnection) => { um, }; - user.active.add({ - ...defaultActive, - client_id: sync.client_id, - user_id: sync.user_id, - site_id: conf.site_id, - page_id: conf.page_id, - comp_id: comp_id, - }); + if (sync && sync.conf) { + user.active.add({ + ...defaultActive, + client_id: sync.client_id, + user_id: sync.user_id, + site_id: sync.conf.site_id, + page_id: sync.conf.page_id, + comp_id: comp_id, + }); + } return { id: comp_id, @@ -125,14 +127,16 @@ export const loadComponent = async (comp_id: string, sync: SyncConnection) => { snapshot: await gzipAsync(snap.bin), }; } else if (snap && ydoc) { - user.active.add({ - ...defaultActive, - client_id: sync.client_id, - user_id: sync.user_id, - site_id: conf.site_id, - page_id: conf.page_id, - comp_id: comp_id, - }); + if (sync && sync.conf) { + user.active.add({ + ...defaultActive, + client_id: sync.client_id, + user_id: sync.user_id, + site_id: sync.conf.site_id, + page_id: sync.conf.page_id, + comp_id: comp_id, + }); + } return { id: snap.id, diff --git a/app/web/src/nova/ed/logic/comp/load.tsx b/app/web/src/nova/ed/logic/comp/load.tsx index ed0505e0..5e5e093f 100644 --- a/app/web/src/nova/ed/logic/comp/load.tsx +++ b/app/web/src/nova/ed/logic/comp/load.tsx @@ -12,7 +12,7 @@ export const loadcomp = { pending: new Set(), }; -export const loadComponent = async (p: PG, id_comp: string) => { +export const loadComponent = async (p: PG, id_comp: string, sync?: boolean) => { return new Promise((resolve) => { if (p.comp.list[id_comp]) { resolve(true); @@ -22,14 +22,12 @@ export const loadComponent = async (p: PG, id_comp: string) => { loadcomp.pending.add(id_comp); clearTimeout(loadcomp.timeout); loadcomp.timeout = setTimeout(async () => { - const comps = await p.sync.comp.load([...loadcomp.pending]); + const comps = await p.sync.comp.load([...loadcomp.pending], sync); 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); - } + if (comp && comp.snapshot) { + await loadCompSnapshot(p, id_comp, comp.snapshot); } } loadcomp.pending.clear(); diff --git a/app/web/src/nova/ed/panel/header/mid/comp-picker.tsx b/app/web/src/nova/ed/panel/header/mid/comp-picker.tsx index 8197776a..baed09ff 100644 --- a/app/web/src/nova/ed/panel/header/mid/comp-picker.tsx +++ b/app/web/src/nova/ed/panel/header/mid/comp-picker.tsx @@ -8,6 +8,7 @@ import { EDGlobal, active } from "../../../logic/ed-global"; import { getMetaById } from "../../../logic/tree/build"; import { fillID } from "../../../logic/tree/fill-id"; import { TopBtn } from "../top-btn"; +import { loadComponent } from "../../../logic/comp/load"; export const EdCompPicker = () => { const p = useGlobal(EDGlobal, "EDITOR"); @@ -18,13 +19,13 @@ 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]; } if (!comp_ref) { alert("Cannot load component!"); - return; + return; } const comp = comp_ref.doc diff --git a/app/web/src/nova/ed/panel/popup/comp/comp-preview.tsx b/app/web/src/nova/ed/panel/popup/comp/comp-preview.tsx index 8631ae32..d19b1ffa 100644 --- a/app/web/src/nova/ed/panel/popup/comp/comp-preview.tsx +++ b/app/web/src/nova/ed/panel/popup/comp/comp-preview.tsx @@ -19,7 +19,7 @@ export const EdCompPreview = () => { useEffect(() => { if (!p.comp.list[comp_id] && !!comp_id) { - loadComponent(p, comp_id).then(() => { + loadComponent(p, comp_id, false).then(() => { p.render(); }); }