This commit is contained in:
Rizky 2023-10-14 23:08:09 +07:00
parent 415f42cefc
commit 3cb7c393ec
10 changed files with 179 additions and 247 deletions

View File

@ -1,15 +1,19 @@
import { Websocket } from "hyper-express";
import { ServerWebSocket } from "bun";
import { compress } from "lz-string";
import { syncronize } from "y-pojo";
import * as Y from "yjs";
import { WSData } from "../../../../../pkgs/core/server/create";
import { SingleComp, eg } from "../edit-global";
import {
WS_MSG_GET_COMP,
WS_MSG_SET_COMP,
WS_MSG_SV_LOCAL,
} from "../../../web/src/utils/types/ws";
import { SingleComp, eg } from "../edit-global";
} from "../../../../web/src/utils/types/ws";
export const getComp = async (ws: Websocket, msg: WS_MSG_GET_COMP) => {
export const getComp = async (
ws: ServerWebSocket<WSData>,
msg: WS_MSG_GET_COMP
) => {
const comp_id = msg.comp_id;
if (!eg.edit.comp[comp_id]) {
@ -17,6 +21,15 @@ export const getComp = async (ws: Websocket, msg: WS_MSG_GET_COMP) => {
where: {
id: comp_id,
},
select: {
component_group: true,
content_tree: true,
id: true,
id_component_group: true,
name: true,
props: true,
type: true,
},
});
if (!rawComp) {
@ -34,7 +47,7 @@ export const getComp = async (ws: Websocket, msg: WS_MSG_GET_COMP) => {
const map = ydoc.getMap("map");
syncronize(map as any, rawComp);
const ws = new Set<Websocket>();
const ws = new Set<ServerWebSocket<WSData>>();
const um = new Y.UndoManager(map, { ignoreRemoteMapChanges: true });
const broadcast = () => {
const sv_local = compress(Y.encodeStateVector(ydoc as any).toString());

View File

@ -1,54 +0,0 @@
import { Websocket } from "hyper-express";
import { syncronize } from "y-pojo";
import * as Y from "yjs";
import { fillID } from "../../../web/src/utils/page/tools/fill-id";
import { IContent, MContent } from "../../../web/src/utils/types/general";
import { IItem } from "../../../web/src/utils/types/item";
import { IRoot } from "../../../web/src/utils/types/root";
import { getComp } from "../action/get-comp";
import { eg } from "../edit-global";
const MAX_STRING_LENGTH = 15000;
export const validateTreeMap = async (
ws: Websocket,
item: MContent,
changed?: boolean
) => {
let _changed = changed;
const type = item.get("type") as IContent["type"] | "root";
if (type !== "root") {
item.forEach((val, key, map) => {
if (typeof val === "string") {
if (val.length > MAX_STRING_LENGTH) {
map.set(key, "");
_changed = true;
}
} else {
if (typeof val === "object" && val instanceof Y.Map) {
val._map.forEach((ival, ikey, imap) => {
if (typeof ival === "string") {
if ((ival as string).length > MAX_STRING_LENGTH) {
imap.set(ikey, "" as any);
_changed = true;
}
}
});
}
}
});
}
if (item) {
if (type !== "text") {
const childs = item.get("childs");
if (childs) {
for (const c of childs) {
if (await validateTreeMap(ws, c)) {
_changed = true;
}
}
}
}
}
return !!_changed;
};

View File

@ -1,19 +1,19 @@
import { Suspense, lazy, useEffect } from "react";
import { page, useLocal } from "web-utils";
import { FC, useEffect } from "react";
import { page, useGlobal, useLocal } from "web-utils";
import { EditorGlobal } from "../../render/editor/logic/global";
import { Loading } from "../../utils/ui/loading";
const Editor = lazy(async () => ({
default: (await import("../../render/editor/editor")).Editor,
}));
export default page({
url: "/editor/:site_id/:page_id",
component: ({}) => {
const p = useGlobal(EditorGlobal, "EDITOR");
const local = useLocal({
loading: true,
session: null as any,
notfound: false,
init: false,
Editor: null as null | FC<any>,
});
const site_id = params.site_id === "_" ? "" : params.site_id;
const page_id = params.page_id === "_" ? "" : params.page_id;
@ -21,6 +21,10 @@ export default page({
useEffect(() => {
if (!local.init) {
(async () => {
if (!local.Editor) {
local.Editor = (await import("../../render/editor/editor")).Editor;
}
let ses: any = null;
try {
ses = JSON.parse(localStorage.getItem("prasi-session") || "");
@ -129,12 +133,11 @@ export default page({
}
}, [local.init]);
if (local.loading) return <Loading note="base-page" />;
const Editor = local.Editor;
if (local.loading || !Editor) return <Loading note="base-page" />;
return (
<Suspense fallback={<Loading note="editor-init" />}>
<Editor session={local.session} site_id={site_id} page_id={page_id} />
</Suspense>
);
},
});

View File

@ -27,6 +27,7 @@ export const Root: FC<{}> = ({}) => {
);
prasiContext.render = local.render;
const Provider = GlobalContext.Provider as FC<{ value: any; children: any }>;
const found = local.router.lookup(location.pathname);

View File

@ -79,7 +79,7 @@ export const Editor: FC<{ site_id: string; page_id: string; session: any }> = ({
useEffect(() => {
if (p.status !== "init" && w.prasiApi) {
for (const [k, v] of Object.entries(deepClone(EditorGlobal))) {
if (k === "session" || k === "site") continue;
if (k === "session" || k === "site" || "status") continue;
(p as any)[k] = v;
}
@ -99,6 +99,7 @@ export const Editor: FC<{ site_id: string; page_id: string; session: any }> = ({
}
if (p.status === "init") {
(window as any).mok = ((window as any).mok || 0) + 1;
p.ui.loading = <Loading note="load-page" />;
p.ui.preload = <Loading note="preload-root" backdrop={false} />;
p.ui.notfound = (
@ -109,6 +110,7 @@ export const Editor: FC<{ site_id: string; page_id: string; session: any }> = ({
PREVIEW ERROR
</div>
);
p.status = "loading";
initEditor(p, site_id);
}

View File

@ -32,8 +32,6 @@ export const w = window as unknown as {
};
export const initEditor = async (p: PG, site_id: string) => {
if (p.status === "init") {
p.status = "loading";
w.isEditor = true;
if (typeof w.isLayout === "undefined") {
@ -50,8 +48,7 @@ export const initEditor = async (p: PG, site_id: string) => {
};
p.item.active = localStorage.getItem("prasi-item-active-id") || "";
p.item.activeOriginalId =
localStorage.getItem("prasi-item-active-oid") || "";
p.item.activeOriginalId = localStorage.getItem("prasi-item-active-oid") || "";
const comp: any = {
id: localStorage.getItem("prasi-comp-active-id"),
instance_id: localStorage.getItem("prasi-comp-instance-id"),
@ -75,6 +72,7 @@ export const initEditor = async (p: PG, site_id: string) => {
const querySite = async () => {
const site = await defaultLoader.site(p as any, { id: site_id });
localStorage.setItem(`prasi-site-${site_id}`, JSON.stringify(site));
return site;
};
@ -120,7 +118,7 @@ export const initEditor = async (p: PG, site_id: string) => {
}
w.apiurl = p.site.api_url;
api.site_dts(p.site.id).then((e) => {
api.site_dts(p.site.id).then((e: any) => {
p.site_dts = e || "";
p.render();
});
@ -131,9 +129,12 @@ export const initEditor = async (p: PG, site_id: string) => {
}
execSiteJS(p);
};
if (!site || (site && !site.id)) {
const site = await querySite();
if (site) {
await processSite(site);
}
} else {
await processSite(site);
querySite();
@ -145,7 +146,6 @@ export const initEditor = async (p: PG, site_id: string) => {
if (!jscript.build) {
jscript.init();
}
}
};
export const execSiteJS = (p: PG) => {

View File

@ -18,6 +18,10 @@ export const defaultLoader: Loader = {
},
})) as unknown as LSite;
if (!site) {
return null;
}
const cgroups = await db.site_use_comp.findMany({
where: { id_site: site.id },
select: { use_id_site: true },

View File

@ -83,9 +83,8 @@ export const liveWS = async (p: PG) => {
console.clear();
console.log(
`🔥 Page updated: ${
p.page?.url
} ${new Date().toLocaleString()}`
`🔥 Page updated: ${p.page
?.url} ${new Date().toLocaleString()}`
);
}
})
@ -179,49 +178,6 @@ export const liveWS = async (p: PG) => {
}
}
break;
case "sitejs_reload":
if (msg.js) {
p.site.js = msg.js;
const exec = (fn: string, scopes: any) => {
if (p) {
if (!p.script.api) p.script.api = createAPI(p.site.api_url);
if (!p.script.db) p.script.db = createDB(p.site.api_url);
scopes["db"] = p.script.db;
scopes["api"] = p.script.api;
const f = new Function(...Object.keys(scopes), fn);
const res = f(...Object.values(scopes));
return res;
}
return null;
};
const w = window as any;
const scope = {
types: {},
exports: w.exports,
load: importModule,
render: p.render,
module: {
exports: {} as any,
},
};
p.status = "init";
console.log(
`🔥 Site JS Reloaded: ${new Date().toLocaleString()}`
);
exec(p.site.js, scope);
if (scope.module.exports) {
for (const [k, v] of Object.entries(scope.module.exports)) {
w.exports[k] = v;
}
}
p.render();
}
break;
case "undo":
case "redo":
case "new_comp":

View File

@ -3,6 +3,7 @@ import { dir } from "./dir";
import { g } from "./global";
import { spawn } from "bun";
const decoder = new TextDecoder();
export const parcelBuild = async () => {
await dirAsync("app/static");
const args = [
@ -26,6 +27,7 @@ export const parcelBuild = async () => {
});
await parcel.exited;
} else {
await new Promise<void>((resolve) => {
const parcel = spawn({
cmd: args,
cwd: dir.path("app/web"),
@ -35,9 +37,14 @@ export const parcelBuild = async () => {
g.parcel = parcel;
let output = true;
let decoded = false;
(async () => {
if (parcel.stdout) {
for await (const chunk of parcel.stdout) {
if (!decoded && decoder.decode(chunk).includes("✨")) {
resolve();
decoded = true;
}
if (output) process.stdout.write(chunk);
}
}
@ -68,5 +75,6 @@ export const parcelBuild = async () => {
process.on("beforeExit", async () => {
await cleanup();
});
});
}
};

View File

@ -39,7 +39,6 @@ export const useGlobal = <T extends object>(
if (!_id) {
_id = "GLOBAL_DEFAULT";
}
const ctx = useContext(GlobalContext);
const { global, render } = ctx;