prasi-bun/app/web/src/nova/vi/vi.tsx

194 lines
4.5 KiB
TypeScript

import { FC, Suspense, useEffect } from "react";
import { useGlobal } from "web-utils";
import { IMeta } from "../ed/logic/ed-global";
import { viLoad } from "./load/load";
import { VG, ViGlobal } from "./render/global";
import { render_stat } from "./render/render";
import { nav } from "./render/script/extract-nav";
import { ViRoot } from "./root";
import { ErrorBox } from "./utils/error-box";
import { IItem } from "../../utils/types/item";
type PRELOAD = Exclude<VG["on_preload"], undefined>;
type PRELOAD_ARGS = Parameters<PRELOAD>[0];
const w = window as any;
if (!w.prasi_internal) {
w.prasi_internal = { page: { id: "" } };
}
export const Vi: FC<{
meta: Record<string, IMeta>;
mode: "mobile" | "desktop";
comp_load: (comp_id: string) => Promise<IItem>;
entry: string[];
preloaded?: (url: string) => boolean;
api_url: string;
site_id: string;
page_id: string;
api?: any;
db?: any;
layout?: VG["layout"];
script: { init_local_effect: Record<string, boolean> };
visit?: VG["visit"];
render_stat?: "enabled" | "disabled";
on_status_changed?: (status: VG["status"]) => void;
on_preload?: VG["on_preload"];
}> = ({
meta,
entry,
api_url,
site_id,
api,
mode,
db,
visit,
script,
preloaded,
page_id,
render_stat: rs,
on_status_changed,
on_preload,
layout,
comp_load,
}) => {
const vi = useGlobal(ViGlobal, "VI");
vi.mode = mode;
vi.entry = entry;
vi.on_preload = on_preload;
vi.comp.load = comp_load;
if (page_id) w.prasi_internal.page.id = page_id;
w.siteurl = (pathname: string, forceOriginal?: boolean) => {
if (pathname.startsWith("http://") || pathname.startsWith("https://"))
return pathname;
try {
if (
["prasi.avolut.com"].includes(location.hostname) ||
location.port === "4550"
) {
if (vi.site.api_url) {
if (!vi.site_url) {
vi.site_url = new URL(vi.site.api_url);
}
}
} else {
if (!vi.site_url) {
if (forceOriginal && vi.site.api_url) {
vi.site_url = new URL(vi.site.api_url);
} else {
vi.site_url = new URL(location.href);
}
vi.site_url.pathname = "";
}
}
} catch (e) {}
if (vi.site_url) {
const u = vi.site_url;
let path = pathname;
if (!path.startsWith("/")) {
path = "/" + path;
}
if (w.prasiContext.siteUrl) {
path = w.prasiContext.siteUrl(path);
}
return `${u.protocol}//${u.host}${path}`;
}
return pathname;
};
w.isMobile = mode === "mobile";
w.isDesktop = mode === "desktop";
w.preloaded =
preloaded ||
((url: string) => {
false;
});
w.preload = (_urls: PRELOAD_ARGS["urls"], opt: PRELOAD_ARGS["opt"]) => {
if (vi.on_preload) {
return new Promise<void>((done) => {
if (!vi.page.navs[page_id]) vi.page.navs[page_id] = new Set();
const navs = vi.page.navs[page_id];
const urls = typeof _urls === "string" ? [_urls] : _urls;
let all_done = true;
for (const url of urls) {
if (!navs.has(url)) {
navs.add(url);
all_done = false;
}
}
if (!all_done) {
vi.page.preload.push(done);
vi.on_preload?.({
urls: Array.from(vi.page.navs[page_id]),
opt: {
on_load: (...arg) => {
opt?.on_load?.(...arg);
for (const done of vi.page.preload) {
done();
}
vi.page.preload = [];
vi.render();
},
},
});
} else {
done();
}
});
}
};
vi.layout = layout;
vi.page.cur.id = page_id;
vi.on_status_changes = on_status_changed;
if (rs === "disabled") {
render_stat.enabled = false;
}
if (vi.meta !== meta) {
vi.meta = meta;
}
if (script) {
vi.script.init_local_effect = script.init_local_effect;
}
vi.visit = visit;
if (vi.status === "init") {
vi.site.db = db;
vi.site.api = api;
viLoad(vi, { api_url, site_id });
}
if (on_preload) {
useEffect(() => {
setTimeout(() => {
const nav = vi.page.navs[vi.page.cur.id];
if (nav) {
on_preload({
urls: Array.from(nav),
opt: {
on_load(pages) {},
},
});
}
}, 500);
}, [vi.page.cur.id]);
}
return (
<ErrorBox>
<Suspense>
<ViRoot />
</Suspense>
</ErrorBox>
);
};