wip fix time

This commit is contained in:
Rizky 2024-01-26 22:01:52 +07:00
parent 1d6ed73f2b
commit b52975ebfd
14 changed files with 275 additions and 25 deletions

View File

@ -13,21 +13,22 @@ export const SyncActionDefinition = {
},
"page": {
"list": "8",
"load": "9"
"load": "9",
"cache": "10"
},
"yjs": {
"um": "10",
"sv_local": "11",
"diff_local": "12",
"sv_remote": "13"
"um": "11",
"sv_local": "12",
"diff_local": "13",
"sv_remote": "14"
},
"client": {
"info": "14"
"info": "15"
},
"code": {
"load": "15",
"edit": "16",
"parse": "17"
"load": "16",
"edit": "17",
"parse": "18"
}
};
export const SyncActionPaths = {
@ -41,12 +42,13 @@ export const SyncActionPaths = {
"7": "comp.load",
"8": "page.list",
"9": "page.load",
"10": "yjs.um",
"11": "yjs.sv_local",
"12": "yjs.diff_local",
"13": "yjs.sv_remote",
"14": "client.info",
"15": "code.load",
"16": "code.edit",
"17": "code.parse"
"10": "page.cache",
"11": "yjs.um",
"12": "yjs.sv_local",
"13": "yjs.diff_local",
"14": "yjs.sv_remote",
"15": "client.info",
"16": "code.load",
"17": "code.edit",
"18": "code.parse"
};

View File

@ -52,6 +52,8 @@ export const SyncActions = {
list: async (id_site: string) =>
({}) as Record<string, Exclude<page, "content_tree">>,
load: async (id: string) => ({}) as EPage | void,
cache: async (site_id: string, urls: string[], exclude_page_id: string[]) =>
({}) as { gzip: Uint8Array } | null,
},
yjs: {
um: async (

View File

@ -8,6 +8,7 @@ export * from "./comp_group";
export * from "./comp_load";
export * from "./page_list";
export * from "./page_load";
export * from "./page_cache";
export * from "./yjs_um";
export * from "./yjs_sv_local";
export * from "./yjs_diff_local";

View File

@ -0,0 +1,58 @@
import { RadixRouter, createRouter } from "radix3";
import { SAction } from "../actions";
import { SyncConnection } from "../type";
import { gzipAsync } from "../entity/zlib";
const cache = {} as Record<
string,
{ ts: number; router: RadixRouter<{ url: string; id: string }> }
>;
const encoder = new TextEncoder();
export const page_cache: SAction["page"]["cache"] = async function (
this: SyncConnection,
site_id,
urls,
exclude_page_id
) {
let result = null as unknown as Awaited<ReturnType<SAction["page"]["cache"]>>;
if (
!cache[site_id] ||
(cache[site_id] && Date.now() - cache[site_id].ts > 5000)
) {
const pages = await db.page.findMany({
where: { id_site: site_id, is_deleted: false },
select: { id: true, url: true },
});
const router = createRouter<{ url: string; id: string }>();
for (const page of pages) {
router.insert(page.url, page);
}
cache[site_id] = {
router,
ts: Date.now(),
};
}
const router = cache[site_id]?.router;
if (router) {
const result: Record<string, any> = {};
for (const url of urls) {
const found = router.lookup(url);
if (found && !exclude_page_id.includes(found.id)) {
const row = await db.page.findFirst({
where: { id: found.id },
select: { content_tree: true },
});
if (row) {
result[found.id] = row.content_tree;
}
}
}
const gzip = await gzipAsync(encoder.encode(JSON.stringify(result)));
return { gzip };
}
return null;
};

View File

@ -25,7 +25,7 @@ export const loadApiProxyDef = async (_url: string, with_types: boolean) => {
const ts = localStorage.getItem("api-ts-" + url);
if (with_types) {
if (with_types) {
script.src = `${base}/_prasi/load.js?url=${url}&v3&dev=1&ts=${ts}`;
} else {
script.src = `${base}/_prasi/load.js?url=${url}&v3&ts=${ts}`;

View File

@ -5,7 +5,7 @@ import { SAction } from "../../../../../srv/ws/sync/actions";
import { parseJs } from "../../../../../srv/ws/sync/editor/parser/parse-js";
import { clientStartSync } from "../../../utils/sync/ws-client";
import { IItem } from "../../../utils/types/item";
import { DCode, DComp, DPage } from "../../../utils/types/root";
import { DCode, DComp, DPage, IRoot } from "../../../utils/types/root";
import { GenMetaP, IMeta as LogicMeta } from "../../vi/utils/types";
export type IMeta = LogicMeta;
@ -147,6 +147,12 @@ export const EDGlobal = {
| "page-not-found"
| "ready",
preview: {
url_cache: new Set<string>(),
page_cache: {} as Record<string, IRoot>,
meta_cache: {} as Record<
string,
{ entry: string[]; meta: Record<string, IMeta> }
>,
show_loading: false,
},
sync: null as unknown as Awaited<ReturnType<typeof clientStartSync>>,

View File

@ -1,10 +1,32 @@
import { createId } from "@paralleldrive/cuid2";
import { IContent } from "../../../../utils/types/general";
import { IItem, MItem } from "../../../../utils/types/item";
import { genMeta } from "../../../vi/meta/meta";
import { IMeta, PG, active } from "../ed-global";
import { assignMitem } from "./assign-mitem";
import { pushTreeNode } from "./build/push-tree";
export const treeCacheBuild = async (p: PG, page_id: string) => {
const root = p.preview.page_cache[page_id];
const meta_cache = {
meta: {} as Record<string, IMeta>,
entry: [] as string[],
};
for (const item of root.childs) {
meta_cache.entry.push(item.id);
genMeta(
{
note: "tree-rebuild",
comps: p.comp.loaded,
meta: meta_cache.meta,
mode: "page",
},
{ item: item as IContent }
);
}
p.preview.meta_cache[page_id] = meta_cache;
};
export const treeRebuild = async (p: PG, arg?: { note?: string }) => {
if (document.activeElement) {
const a = document.activeElement;

View File

@ -4,9 +4,12 @@ import { EDGlobal, PG, active } from "../ed/logic/ed-global";
import { reloadPage } from "../ed/logic/ed-route";
import { loadSite } from "../ed/logic/ed-site";
import { Vi } from "./vi";
import init from "wasm-gzip";
import init, { decompress } from "wasm-gzip";
import { w } from "../../utils/types/general";
import { IRoot } from "../../utils/types/root";
import { treeCacheBuild } from "../ed/logic/tree/build";
const decoder = new TextDecoder();
export const ViPreview = (arg: { pathname: string }) => {
const p = useGlobal(EDGlobal, "EDITOR");
@ -49,6 +52,13 @@ export const ViPreview = (arg: { pathname: string }) => {
const mode = p.mode;
if (!w.isEditor) {
p.preview.meta_cache[params.page_id] = {
meta: p.page.meta,
entry: p.page.entry,
};
}
return (
<div className={cx("relative flex flex-1 items-center justify-center")}>
<div
@ -91,6 +101,36 @@ export const ViPreview = (arg: { pathname: string }) => {
db={p.script.db}
render_stat="disabled"
script={{ init_local_effect: p.script.init_local_effect }}
on_nav_loaded={async ({ urls }) => {
const load_urls: string[] = [];
if (p.preview.url_cache) {
for (const url of urls) {
if (!p.preview.url_cache.has(url)) {
load_urls.push(url);
p.preview.url_cache.add(url);
}
}
}
if (load_urls.length > 0) {
console.log(load_urls);
const res = await p.sync.page.cache(
p.site.id,
load_urls,
Object.keys(p.preview.page_cache)
);
if (res) {
const pages = JSON.parse(
decoder.decode(decompress(res.gzip)) || "{}"
);
for (const [id, page] of Object.entries(pages)) {
p.preview.page_cache[id] = page as IRoot;
treeCacheBuild(p, params.page_id);
}
}
}
}}
/>
</div>
</div>
@ -130,6 +170,23 @@ const viRoute = async (p: PG) => {
}
p.script.init_local_effect = {};
if (!w.isEditor) {
const page_cache = p.preview.meta_cache[params.page_id];
if (page_cache) {
p.page.meta = page_cache.meta;
p.page.entry = page_cache.entry;
if (p.page.cur.id !== params.page_id) {
p.page.cur = { id: params.page_id } as any;
}
p.status = "ready";
p.render();
return;
}
}
await reloadPage(p, params.page_id, "load-route");
}
}

View File

@ -1,4 +1,3 @@
import { IItem } from "../../../utils/types/item";
import { IMeta } from "../../ed/logic/ed-global";
import { viParts } from "./parts";
@ -25,6 +24,13 @@ export const ViGlobal = {
| undefined
| ((meta: IMeta, parts: ReturnType<typeof viParts>) => void),
on_status_changes: undefined as void | ((status: ViStatus) => void),
page: {
cur: { id: "" },
navs: {} as Record<string, Set<string>>,
},
on_nav_loaded: undefined as
| undefined
| ((arg: { urls: string[] }) => Promise<void>),
};
export type VG = typeof ViGlobal & { render: () => void };

View File

@ -3,9 +3,16 @@ import { VG } from "../global";
import { ViRender } from "../render";
import { viScriptArg } from "./arg";
import { replaceWithObject, replacement } from "./eval-script";
import { extractNavigate } from "./extract-nav";
export const viEvalProps = (
vi: { meta: VG["meta"]; site: { db: any; api: any } },
vi: {
mode: VG["mode"];
meta: VG["meta"];
site: { db: any; api: any };
page: VG["page"];
on_nav_loaded?: VG["on_nav_loaded"];
},
meta: IMeta,
passprop: any
) => {
@ -85,6 +92,10 @@ export const viEvalProps = (
continue;
}
if (prop.value) {
extractNavigate(vi, prop.value);
}
const js = prop.valueBuilt || "";
const src = replaceWithObject(js, replacement) || "";
const fn = new Function(

View File

@ -8,13 +8,18 @@ import { viScriptArg } from "./arg";
import { updatePropScope } from "./eval-prop";
import { createViLocal } from "./local";
import { createViPassProp } from "./passprop";
import { extractNavigate } from "./extract-nav";
import { w } from "../../../../utils/types/general";
export const viEvalScript = (
vi: {
page: VG["page"];
mode: VG["mode"];
site: { db: any; api: any };
meta: VG["meta"];
visit?: VG["visit"];
script?: { init_local_effect: any };
on_nav_loaded?: VG["on_nav_loaded"];
},
meta: IMeta,
passprop: any
@ -66,6 +71,10 @@ export const viEvalScript = (
}
}
if (!w.isEditor && meta.item.adv?.js) {
extractNavigate(vi, meta.item.adv.js);
}
const js = meta.item.adv?.jsBuilt || "";
const src = replaceWithObject(js, replacement) || "";
const fn = new Function(

View File

@ -0,0 +1,58 @@
import { VG } from "../global";
const nav = { timeout: null as any };
export const extractNavigate = (
vi: { page: VG["page"]; on_nav_loaded?: VG["on_nav_loaded"] },
str: string
) => {
const found_nav = [
...findBetween(str, `navigate(`, `)`),
...findBetween(str, `href = `, `;`),
];
const page_id = vi.page.cur.id;
if (!vi.page.navs[page_id]) {
vi.page.navs[page_id] = new Set();
}
for (const url of found_nav) {
vi.page.navs[page_id].add(url);
}
clearTimeout(nav.timeout);
nav.timeout = setTimeout(() => {
if (vi.on_nav_loaded) {
vi.on_nav_loaded({
urls: Array.from(vi.page.navs[page_id]),
});
}
}, 100);
};
const findBetween = (text: string, opener: string, closer: string) => {
let i = 0;
let last = 0;
const founds: string[] = [];
while (true) {
const startIndex = text.indexOf(opener, i);
last = i;
if (startIndex >= 0) {
const char = text[startIndex + opener.length];
if (char === '"' || char === "'" || char === "`") {
const end = text.indexOf(
`${char}${closer}`,
startIndex + opener.length + 1
);
const found = text.substring(startIndex + opener.length + 1, end);
i = end + 2 + closer.length;
founds.push(found);
}
}
if (last === i) {
break;
}
}
return founds;
};

View File

@ -1,4 +1,4 @@
import { FC, Suspense, useState } from "react";
import { FC, Suspense, useEffect, useState } from "react";
import { useGlobal } from "web-utils";
import { IMeta } from "../ed/logic/ed-global";
import { viLoad } from "./load/load";
@ -6,6 +6,7 @@ import { VG, ViGlobal } from "./render/global";
import { ViRoot } from "./root";
import { ErrorBox } from "./utils/error-box";
import { render_stat } from "./render/render";
import { IRoot } from "../../utils/types/root";
const w = window as any;
export const Vi: FC<{
@ -22,6 +23,7 @@ export const Vi: FC<{
visit?: VG["visit"];
render_stat?: "enabled" | "disabled";
on_status_changed?: (status: VG["status"]) => void;
on_nav_loaded?: (arg: { urls: string[] }) => Promise<void>;
}> = ({
meta,
entry,
@ -32,15 +34,18 @@ export const Vi: FC<{
db,
visit,
script,
page_id,
render_stat: rs,
on_status_changed,
on_nav_loaded,
}) => {
const vi = useGlobal(ViGlobal, "VI");
vi.mode = mode;
vi.on_nav_loaded = on_nav_loaded;
w.isMobile = mode === "mobile";
w.isDesktop = mode === "desktop";
vi.page.cur.id = page_id;
vi.on_status_changes = on_status_changed;
if (rs === "disabled") {
@ -61,6 +66,19 @@ export const Vi: FC<{
viLoad(vi, { api_url, site_id });
}
if (on_nav_loaded) {
useEffect(() => {
setTimeout(() => {
const nav = vi.page.navs[vi.page.cur.id];
if (nav) {
on_nav_loaded({
urls: Array.from(nav),
});
}
}, 500);
}, [vi.page.cur.id]);
}
return (
<ErrorBox>
<Suspense>

BIN
dockerzip

Binary file not shown.