prasi-bun/app/web/src/nova/ed/logic/ed-global.ts

324 lines
8.7 KiB
TypeScript

import { NodeModel } from "@minoru/react-dnd-treeview";
import { page } from "dbgen";
import { deepClone } from "web-utils";
import type { SAction } from "../../../../../srv/ws/sync/actions";
import type { 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, IRoot } from "../../../utils/types/root";
import { GenMetaP, IMeta as LogicMeta } from "../../vi/utils/types";
import { createRouter } from "radix3";
import { FEntry } from "../panel/file/type";
export type IMeta = LogicMeta;
export const EmptySite = {
id: "",
name: "",
domain: "",
config: { api_url: "" },
js: "",
js_compiled: "",
responsive: "" as "desktop-only" | "mobile-only" | "responsive",
layout: {
id: "--",
meta: undefined as void | Record<string, IMeta>,
entry: [] as string[],
},
};
export type ESite = typeof EmptySite;
export type EPage = typeof EmptyPage;
export type EComp = typeof EmptyComp;
export type PropFieldKind = "visible" | "gen" | "value" | "option" | "typings";
export type ISingleScope = {
p: string[];
n: string;
s: null | Exclude<ReturnType<typeof parseJs>, undefined>;
};
export type IScope = Record<string, ISingleScope>;
export type IScopeComp = Record<
string,
{
id: string;
name: string;
snapshot: Uint8Array;
scope: IScope;
}
>;
export const EmptyPage = {
id: "",
name: "",
url: "",
snapshot: null as null | Uint8Array,
comps: {} as Record<string, EComp>,
};
const EmptyComp = {
id: "",
snapshot: null as null | Uint8Array,
};
const target = {
active_id: false as any,
comp_id: false as any,
instance_comp_id: false as any,
instance_item_id: false as any,
};
export const active = {
should_render_main: true,
hover: { id: "" },
scope: {} as any,
script_nav: {
list: [] as {
item_id: string;
comp_id?: string;
instance?: { item_id: string; comp_id?: string };
}[],
idx: -1,
},
text: { id: "", content: "", timeout: null as any, el: null as any },
get item_id() {
if (target.active_id === false) {
target.active_id = localStorage.getItem("prasi-active-id") || "";
}
return target.active_id || "";
},
set item_id(val: string) {
localStorage.setItem("prasi-active-id", val || "");
target.active_id = val || "";
},
get comp_id() {
if (target.comp_id === false) {
target.comp_id = localStorage.getItem("prasi-comp-id") || "";
}
return target.comp_id || "";
},
set comp_id(val: string) {
localStorage.setItem("prasi-comp-id", val || "");
target.comp_id = val || "";
},
instance: {
get comp_id() {
if (target.instance_comp_id === false) {
target.instance_comp_id =
localStorage.getItem("prasi-instance-comp-id") || "";
}
return target.instance_comp_id || "";
},
set comp_id(val: string) {
localStorage.setItem("prasi-instance-comp-id", val || "");
target.instance_comp_id = val || "";
},
get item_id() {
if (target.instance_item_id === false) {
target.instance_item_id =
localStorage.getItem("prasi-instance-item-id") || "";
}
return target.instance_item_id || "";
},
set item_id(val: string) {
localStorage.setItem("prasi-instance-item-id", val || "");
target.instance_item_id = val || "";
},
},
};
export const EDGlobal = {
mode: "" as "desktop" | "mobile",
user: { id: "", username: "", client_id: "" },
clients: {} as Record<string, { id: string; username: string }>,
status: "init" as
| "init"
| "load-site"
| "reload"
| "site-not-found"
| "page-not-found"
| "ready"
| "no-site",
preview: {
url_cache: new Set<string>(),
route_cache: createRouter<{ url: string; id: string }>(),
page_cache: {} as Record<string, { root: IRoot; url: string }>,
meta_cache: {} as Record<
string,
{ entry: string[]; meta: Record<string, IMeta>; url: string }
>,
},
sync: null as null | Awaited<ReturnType<typeof clientStartSync>>,
sync_assigned: false,
site: deepClone(EmptySite),
site_tstamp: Date.now(),
site_exports: {} as Record<string, any>,
site_dts: "",
site_dts_entry: {} as any,
script: {
site_types: {} as Record<string, string>,
loaded: false,
do_edit: async (newval: string, all?: boolean) => {},
db: null as any,
api: null as any,
init_local_effect: {} as Record<string, boolean>,
},
page: {
history: {
id: "",
show: false,
},
root_id: "root",
cur: EmptyPage,
doc: null as null | DPage,
list: {} as Record<
string,
{
page: EPage;
doc: DPage;
on_update?: (bin: Uint8Array, origin: any) => Promise<void>;
}
>,
building: false,
meta: {} as Record<string, IMeta>,
entry: [] as string[],
tree: [] as NodeModel<IMeta>[],
render: () => {},
},
comp: {
doc: null as null | DComp,
item: null as null | IItem,
loaded: {} as GenMetaP["comps"],
list: {} as Record<
string,
{
comp: EComp;
doc: DComp;
tree: NodeModel<IMeta>[];
meta: Record<string, IMeta>;
on_update: (bin: Uint8Array, origin: any) => Promise<void>;
}
>,
group: {} as Record<string, Awaited<ReturnType<SAction["comp"]["group"]>>>,
},
code: {} as Record<string, { doc: null | DCode }>,
global_prop: [] as string[],
ui: {
monaco: null as any,
comp_editable: localStorage.getItem("prasi-comp-editable") === "yes",
zoom: localStorage.zoom || "100%",
side: { prop: true },
layout: {
left: parseInt(localStorage.getItem("prasi-layout-left") || "250"),
right: parseInt(localStorage.getItem("prasi-layout-right") || "250"),
},
prevent_indent_hook: false,
syncing: false,
tree: {
item_loading: [] as string[],
search: "",
search_ref: null as null | HTMLInputElement,
search_mode: {
Name: true,
JS: false,
HTML: false,
CSS: false,
},
rename_id: "",
open: {} as Record<string, string[]>,
},
popup: {
file: {
enabled: false,
open: false,
picker: {
value: "",
on_pick: false as boolean | ((file: string) => void | Promise<void>),
multi: false,
},
path: "/",
expanded: JSON.parse(
localStorage.getItem("panel-file-expanded") || "{}"
) as Record<string, string[]>,
entry: {} as Record<string, FEntry[]>,
selected: new Set<string>(),
action: null as null | {
label: string;
submit: () => void | Promise<void>;
},
file_renaming: "",
file_ctx_menu_event: null as null | React.MouseEvent<
HTMLElement,
MouseEvent
>,
tree: [] as NodeModel<FEntry>[],
tree_renaming: "",
tree_ctx_path: "",
tree_ctx_menu_event: null as null | React.MouseEvent<
HTMLElement,
MouseEvent
>,
preview: true,
upload: {
started: false,
progress: {} as Record<string, number>,
},
},
code: {
init: false,
open: false,
name: "site",
log: "",
loading: false,
startup_status: "init" as
| "init"
| "loading"
| "disabled"
| "stopped"
| "running",
error: false,
show_log: false,
list: {} as Record<string, string>,
},
page: {
open: null as null | ((page_id: string) => void),
form: null as null | Partial<page>,
},
script: {
open: false,
mode: "js" as "js" | "css" | "html",
lastMode: "js" as "js" | "css" | "html",
type: "item" as "item" | "prop-master" | "prop-instance" | "comp-types",
prop_kind: "" as PropFieldKind,
prop_name: "",
on_close: () => {},
typings: { status: "ok" as "ok" | "loading" | "error", err_msg: "" },
wb_render: () => {},
},
site: null as null | ((site_id: string) => void | Promise<void>),
site_form: null as null | {
group_id: string;
id: string;
name?: string;
domain?: string;
responsive?: string;
},
comp: {
preview_id: "",
open: null as null | ((comp_id: string) => void | Promise<void>),
import: false,
},
comp_group: null as null | {
mouse_event: React.MouseEvent<HTMLElement, MouseEvent>;
on_pick?: (group_id: string) => void | Promise<void>;
on_close?: () => void | Promise<void>;
},
api: { open: false },
},
},
};
export type PG = typeof EDGlobal & { render: () => void };