diff --git a/app/srv/ws/sync/editor/load.ts b/app/srv/ws/sync/editor/load.ts index 5dfd0494..c5105b00 100644 --- a/app/srv/ws/sync/editor/load.ts +++ b/app/srv/ws/sync/editor/load.ts @@ -1,7 +1,7 @@ import { user } from "../user"; -export const syncEditorLoad = async (user_id: string) => { - const conf = user.conf.get(user_id); +export const loadUserConf = async (user_id: string) => { + const conf = user.conf.getOrCreate(user_id); if (conf) { if (!conf.site_id) { const site = await db.site.findFirst({ @@ -11,7 +11,10 @@ export const syncEditorLoad = async (user_id: string) => { }, select: { id: true }, }); - if (site) conf.site_id = site.id; + if (site) { + conf.site_id = site.id; + user.conf.set(user_id, "site_id", site.id); + } } if (conf.site_id && !conf.page_id) { @@ -25,7 +28,9 @@ export const syncEditorLoad = async (user_id: string) => { if (page) { conf.page_id = page.id; + user.conf.set(user_id, "page_id", page.id); } } } + return conf; }; diff --git a/app/srv/ws/sync/sync-handler.ts b/app/srv/ws/sync/sync-handler.ts index fb237e3e..6d3b626c 100644 --- a/app/srv/ws/sync/sync-handler.ts +++ b/app/srv/ws/sync/sync-handler.ts @@ -2,6 +2,8 @@ import { createId } from "@paralleldrive/cuid2"; import { ServerWebSocket, WebSocketHandler } from "bun"; import { Packr } from "msgpackr"; import { WSData } from "../../../../pkgs/core/server/create"; +import { ClientEvent } from "../../../web/src/utils/sync/client"; +import { loadUserConf } from "./editor/load"; import { SyncType } from "./type"; const packr = new Packr({ structuredClone: true }); @@ -17,6 +19,9 @@ const conns = new Map< } >(); const wconns = new WeakMap, string>(); +const send = (ws: ServerWebSocket, msg: any) => { + ws.sendBinary(packr.pack(msg)); +}; export const syncHandler: WebSocketHandler = { open(ws) { const client_id = createId(); @@ -26,7 +31,7 @@ export const syncHandler: WebSocketHandler = { msg: { pending: {}, resolve: {} }, }); wconns.set(ws, client_id); - ws.sendBinary(packr.pack({ type: SyncType.ClientID, client_id })); + send(ws, { type: SyncType.ClientID, client_id }); }, close(ws, code, reason) { const conn_id = wconns.get(ws); @@ -35,7 +40,7 @@ export const syncHandler: WebSocketHandler = { wconns.delete(ws); } }, - message(ws, raw) { + async message(ws, raw) { const conn_id = wconns.get(ws); if (conn_id) { const conn = conns.get(conn_id); @@ -44,6 +49,12 @@ export const syncHandler: WebSocketHandler = { if (msg.type === SyncType.UserID) { const { user_id } = msg; conn.user_id = user_id; + const conf = await loadUserConf(user_id); + send(ws, { + type: SyncType.Event, + event: "editor_start" as ClientEvent, + data: conf, + }); } } } diff --git a/app/srv/ws/sync/type.ts b/app/srv/ws/sync/type.ts index e3b97518..74c80749 100644 --- a/app/srv/ws/sync/type.ts +++ b/app/srv/ws/sync/type.ts @@ -1,5 +1,5 @@ export enum SyncType { ClientID, UserID, - Event + Event, } \ No newline at end of file diff --git a/app/srv/ws/sync/user.ts b/app/srv/ws/sync/user.ts index eebb8522..b50aa450 100644 --- a/app/srv/ws/sync/user.ts +++ b/app/srv/ws/sync/user.ts @@ -15,6 +15,14 @@ const db = open({ export const user = { conf: { + getOrCreate(user_id: string) { + const res = db.get(user_id); + if (!res) { + db.put(user_id, structuredClone(defaultConf)); + return db.get(user_id); + } + return res; + }, get(user_id: string) { return db.get(user_id); }, diff --git a/app/web/src/base/page/all.tsx b/app/web/src/base/page/all.tsx index 2844b768..4f5797f9 100644 --- a/app/web/src/base/page/all.tsx +++ b/app/web/src/base/page/all.tsx @@ -7,7 +7,10 @@ export default page({ component: ({}) => { useEffect(() => { if (localStorage.getItem("prasi-session")) { - if (location.pathname.startsWith("/ed/")) { + if ( + location.pathname === "/ed" || + location.pathname.startsWith("/ed/") + ) { navigate("/ed/_/_"); } else { navigate("/editor/_/_"); diff --git a/app/web/src/base/page/ned.tsx b/app/web/src/base/page/ed.tsx similarity index 79% rename from app/web/src/base/page/ned.tsx rename to app/web/src/base/page/ed.tsx index d7c8f1f5..cf88e154 100644 --- a/app/web/src/base/page/ned.tsx +++ b/app/web/src/base/page/ed.tsx @@ -1,8 +1,7 @@ import { page, useGlobal } from "web-utils"; -import { EditorGlobal } from "../../render/editor/logic/global"; -import { Loading } from "../../utils/ui/loading"; -import { clientStartSync } from "../../utils/sync/client"; import { EDGlobal } from "../../render/ed/logic/global"; +import { clientStartSync } from "../../utils/sync/client"; +import { Loading } from "../../utils/ui/loading"; export default page({ url: "/ed/:site_id/:page_id", @@ -20,9 +19,14 @@ export default page({ if (!p.sync) { p.sync = clientStartSync({ user_id: session.data.user.id, - events: { editor_start() {} }, + events: { + editor_start(e) { + if (e.site_id && e.page_id) { + navigate(`/ed/${e.site_id}/${e.page_id}`); + } + }, + }, }); - return ; } diff --git a/app/web/src/base/pages.ts b/app/web/src/base/pages.ts index b4c6873a..9cd8f8e1 100644 --- a/app/web/src/base/pages.ts +++ b/app/web/src/base/pages.ts @@ -14,6 +14,10 @@ export const all = { url: "**", page: () => import("./page/all"), }; +export const ed = { + url: "/ed/:site_id/:page_id", + page: () => import("./page/ed"), +}; export const editor = { url: "/editor/:site_id/:page_id", page: () => import("./page/editor"), @@ -22,7 +26,3 @@ export const live = { url: "/live/:domain/**", page: () => import("./page/live"), }; -export const ned = { - url: "/ed/:site_id/:page_id", - page: () => import("./page/ned"), -}; diff --git a/app/web/src/utils/sync/client.ts b/app/web/src/utils/sync/client.ts index 6fc274fe..9f8336dd 100644 --- a/app/web/src/utils/sync/client.ts +++ b/app/web/src/utils/sync/client.ts @@ -19,6 +19,9 @@ type User = { name: string; }; +export type ClientEventObject = Parameters[0]["events"]; +export type ClientEvent = keyof ClientEventObject; + export const clientStartSync = async (arg: { user_id: string; events: { @@ -31,7 +34,7 @@ export const clientStartSync = async (arg: { }) => { const { user_id, events } = arg; conf.idb = initIDB(user_id); - await connect(user_id); + await connect(user_id, events); const path: any[] = []; return new DeepProxy( SyncActionDefinition, @@ -64,7 +67,7 @@ export const clientStartSync = async (arg: { ) as unknown as typeof SyncActions; }; -const connect = (user_id: string) => { +const connect = (user_id: string, event: ClientEventObject) => { return new Promise((resolve) => { if (!conf.ws) { const url = new URL(location.href); @@ -83,7 +86,11 @@ const connect = (user_id: string) => { if (msg.type === SyncType.ClientID) { conf.client_id = msg.client_id; resolve(ws); - } else if (msg.type === "event") { + } else if (msg.type === SyncType.Event) { + const eventName = msg.event as keyof ClientEventObject; + if (event[eventName]) { + event[eventName](msg.data); + } } }; } diff --git a/undefined/lmdb/user-conf.lmdb b/undefined/lmdb/user-conf.lmdb new file mode 100644 index 00000000..69dfee7a Binary files /dev/null and b/undefined/lmdb/user-conf.lmdb differ diff --git a/undefined/lmdb/user-conf.lmdb-lock b/undefined/lmdb/user-conf.lmdb-lock new file mode 100644 index 00000000..aaf8fc45 Binary files /dev/null and b/undefined/lmdb/user-conf.lmdb-lock differ