This commit is contained in:
Rizky 2023-11-02 10:16:20 +07:00
parent e2a6835d7f
commit d8a1de1bef
8 changed files with 30 additions and 149 deletions

View File

@ -1,41 +1,9 @@
import { validate } from "uuid";
import { SAction } from "../actions"; import { SAction } from "../actions";
import { actstore, broadcastActivity } from "../entity/actstore"; import { SyncConnection } from "../type";
import { Activity, SyncConnection } from "../type";
export const activity: SAction["activity"] = async function ( export const activity: SAction["activity"] = async function (
this: SyncConnection, this: SyncConnection,
target, target,
kind, kind,
act act
) { ) {};
const key = (target.page_id ? "page_id" : "comp_id") as "page_id" | "comp_id";
const type = (target.page_id ? "page" : "comp") as "page" | "comp";
const tkey = target[key];
if (!tkey) return;
if (validate(tkey)) {
if (!actstore[type][tkey]) actstore[type][tkey] = {};
if (!actstore[type][tkey][target.item_id])
actstore[type][tkey][target.item_id] = {};
if (!actstore[type][tkey][target.item_id][kind])
actstore[type][tkey][target.item_id][kind] = {};
const obj = actstore[type][tkey][target.item_id][kind];
if (obj) {
if (act === Activity.Null) {
delete obj[this.client_id];
if (Object.keys(obj).length === 0) {
delete actstore[type][tkey][target.item_id][kind];
if (Object.keys(actstore[type][tkey][target.item_id]).length === 0) {
delete actstore[type][tkey][target.item_id];
}
}
} else obj[this.client_id] = act;
}
broadcastActivity({ [key]: tkey });
}
};

View File

@ -7,7 +7,6 @@ import { user } from "../entity/user";
import { gzipAsync } from "../entity/zlib"; import { gzipAsync } from "../entity/zlib";
import { sendWS } from "../sync-handler"; import { sendWS } from "../sync-handler";
import { Activity, SyncConnection, SyncType } from "../type"; import { Activity, SyncConnection, SyncType } from "../type";
import { actstore, broadcastActivity } from "../entity/actstore";
export const page_load: SAction["page"]["load"] = async function ( export const page_load: SAction["page"]["load"] = async function (
this: SyncConnection, this: SyncConnection,
@ -19,34 +18,6 @@ export const page_load: SAction["page"]["load"] = async function (
const conf = this.conf; const conf = this.conf;
if (!conf) return undefined; if (!conf) return undefined;
if (!actstore.page[id]) {
actstore.page[id] = {
load: {
root: {
[this.client_id]: Activity.Open,
},
},
};
} else {
const load = actstore.page[id]["load"];
if (load && load.root) {
load.root[this.client_id] = Activity.Open;
}
}
if (conf.page_id !== id && actstore.page[conf.page_id]) {
const load = actstore.page[conf.page_id]["load"];
if (load && load.root) {
delete load.root[this.client_id];
}
broadcastActivity(
{
page_id: conf.page_id,
},
[this.client_id]
);
}
conf.page_id = id; conf.page_id = id;
const createUndoManager = async (root: Y.Map<any>) => { const createUndoManager = async (root: Y.Map<any>) => {
@ -120,10 +91,6 @@ export const page_load: SAction["page"]["load"] = async function (
page_id: page.id, page_id: page.id,
}); });
broadcastActivity({
page_id: id,
});
return { return {
id: id, id: id,
url: page.url, url: page.url,
@ -154,10 +121,6 @@ export const page_load: SAction["page"]["load"] = async function (
page_id: snap.id, page_id: snap.id,
}); });
broadcastActivity({
page_id: id,
});
return { return {
id: id, id: id,
url: snap.url, url: snap.url,
@ -173,10 +136,6 @@ export const page_load: SAction["page"]["load"] = async function (
page_id: snap.id, page_id: snap.id,
}); });
broadcastActivity({
page_id: id,
});
return { return {
id: snap.id, id: snap.id,
url: snap.url, url: snap.url,

View File

@ -1,5 +1,5 @@
import { Room } from "./room"; import { Room, RoomList } from "./room";
export const activity = { export const activity = {
site: {} as Record<string, Room<{ code: { name: string } }>>, site: new RoomList<{ code: { name: string } }>(),
}; };

View File

@ -1,46 +0,0 @@
import { ServerWebSocket } from "bun";
import { WSData } from "../../../../../pkgs/core/server/create";
import { sendWS } from "../sync-handler";
import { ActivityList, CLIENT_ID, COMP_ID, PAGE_ID, SyncType } from "../type";
import { conns } from "./conn";
import { user } from "./user";
export const actstore = {
page: {} as Record<PAGE_ID, ActivityList>,
comp: {} as Record<COMP_ID, ActivityList>,
};
export const broadcastActivity = (
arg: { page_id?: string; comp_id?: string },
exclude?: CLIENT_ID[]
) => {
const wss = new Set<ServerWebSocket<WSData>>();
const data = {} as any;
if (arg.page_id) {
data.page = actstore.page[arg.page_id] || {};
user.active.findAll({ page_id: arg.page_id }).forEach((u) => {
if (u.client_id && (!exclude || !exclude.includes(u.client_id))) {
const ws = conns.get(u.client_id)?.ws;
if (ws) wss.add(ws);
}
});
}
if (arg.comp_id) {
data.comp = actstore.page[arg.comp_id] || {};
user.active.findAll({ comp_id: arg.comp_id }).forEach((u) => {
if (u.client_id && (!exclude || !exclude.includes(u.client_id))) {
const ws = conns.get(u.client_id)?.ws;
if (ws) {
wss.add(ws);
}
}
});
}
wss.forEach((ws) => {
sendWS(ws, {
type: SyncType.Event,
event: "activity",
data,
});
});
};

View File

@ -2,6 +2,13 @@ import { ServerWebSocket } from "bun";
import { WSData } from "../../../../../pkgs/core/server/create"; import { WSData } from "../../../../../pkgs/core/server/create";
import { conns } from "./conn"; import { conns } from "./conn";
export const RoomList = class<
T extends Record<string, true | Record<string, any>>,
> {
rooms = new Map<string, Room<T>>();
constructor() {}
};
export class Room<T extends Record<string, true | Record<string, any>>> { export class Room<T extends Record<string, true | Record<string, any>>> {
name = ""; name = "";
clients = new Map<ServerWebSocket<WSData>, Partial<T>>(); clients = new Map<ServerWebSocket<WSData>, Partial<T>>();
@ -30,12 +37,17 @@ export class Room<T extends Record<string, true | Record<string, any>>> {
return clients; return clients;
} }
do( set(
where: Partial<T>, client: { ws?: ServerWebSocket<WSData>; id?: string },
action: (ws: ServerWebSocket<WSData>, data: Partial<T>) => void action: (ws: ServerWebSocket<WSData>, data: Partial<T>) => Partial<T>
) { ) {
for (const [ws, data] of this.findAll(where)) { const ws = this.identify(client);
action(ws, data); if (ws) {
const data = this.clients.get(ws);
if (data) {
const newdata = action(ws, data);
this.clients.set(ws, newdata);
}
} }
} }

View File

@ -10,7 +10,6 @@ import { loadSitePage } from "./editor/load-sitepage";
import { conns, wconns } from "./entity/conn"; import { conns, wconns } from "./entity/conn";
import { UserConf, user } from "./entity/user"; import { UserConf, user } from "./entity/user";
import { SyncType } from "./type"; import { SyncType } from "./type";
import { actstore, broadcastActivity } from "./entity/actstore";
const packr = new Packr({ structuredClone: true }); const packr = new Packr({ structuredClone: true });
export const sendWS = (ws: ServerWebSocket<WSData>, msg: any) => { export const sendWS = (ws: ServerWebSocket<WSData>, msg: any) => {
@ -34,21 +33,6 @@ export const syncHandler: WebSocketHandler<WSData> = {
if (client_id) { if (client_id) {
conns.delete(client_id); conns.delete(client_id);
wconns.delete(ws); wconns.delete(ws);
for (const p of Object.values(actstore)) {
for (const q of Object.values(p)) {
for (const r of Object.values(q)) {
for (const s of Object.values(r)) {
delete s[client_id];
}
}
}
}
const u = user.active.find(client_id);
if (u) {
user.active.del(client_id);
broadcastActivity({ page_id: u.page_id, comp_id: u.comp_id });
}
} }
}, },
async message(ws, raw) { async message(ws, raw) {
@ -94,9 +78,7 @@ export const syncHandler: WebSocketHandler<WSData> = {
if (actionName) { if (actionName) {
const baseAction = (actions as any)[actionName]; const baseAction = (actions as any)[actionName];
if (!baseAction) { if (!baseAction) {
console.log( console.log(`app/srv/ws/sync/actions/${actionName}.ts not found`);
`app/srv/ws/sync/actions/${actionName}.ts not found`
);
} }
if (baseAction) { if (baseAction) {
const action = baseAction.bind(conn); const action = baseAction.bind(conn);

View File

@ -5,6 +5,7 @@ import { LPage } from "./elements/l-page";
import { LiveGlobal, Loader } from "./logic/global"; import { LiveGlobal, Loader } from "./logic/global";
import { initLive, w } from "./logic/init"; import { initLive, w } from "./logic/init";
import { preload, routeLive } from "./logic/route"; import { preload, routeLive } from "./logic/route";
import { Loading } from "../../utils/ui/loading";
export const Live: FC<{ export const Live: FC<{
domain_or_siteid: string; domain_or_siteid: string;
@ -34,6 +35,7 @@ export const Live: FC<{
} }
} }
} }
const onResize = useCallback(() => { const onResize = useCallback(() => {
let newmode = p.mode; let newmode = p.mode;
if (window.innerWidth < 600) newmode = "mobile"; if (window.innerWidth < 600) newmode = "mobile";
@ -63,6 +65,12 @@ export const Live: FC<{
routeLive(p, pathname); routeLive(p, pathname);
} }
if (!p.mode) return <Loading note="init mode" />;
else {
w.isMobile = p.mode === "mobile";
w.isDesktop = p.mode === "desktop";
}
if (p.status === "not-found") if (p.status === "not-found")
return ( return (
<div className="absolute inset-0 flex items-center justify-center flex-col"> <div className="absolute inset-0 flex items-center justify-center flex-col">

View File

@ -37,8 +37,6 @@ export const initLive = async (p: PG, domain_or_siteid: string) => {
w.isEditor = false; w.isEditor = false;
w.isLayout = true; w.isLayout = true;
w.isMobile = p.mode === "mobile";
w.isDesktop = p.mode === "desktop";
w.apiHeaders = {}; w.apiHeaders = {};
w.navigateOverride = (_href) => { w.navigateOverride = (_href) => {