Loading packages/client/src/lib/alerts.tsx 0 → 100644 +44 −0 Original line number Diff line number Diff line /** * Handle alerts sent by the server (moderation or internal) */ import { IAlert } from "@sc07-canvas/lib/src/net"; import { toast } from "react-toastify"; /** * Handles IAlert outside of react * @param alert */ export const handleAlert = (alert: IAlert) => { switch (alert.is) { case "toast": handleToast(alert); break; case "modal": handleModal(alert); break; } }; export const handleDismiss = (id: string) => { toast.dismiss(id); }; const handleToast = (alert: IAlert<"toast">) => { const Body = ( <> <b>{alert.title}</b> {alert.body && <> {alert.body}</>} </> ); toast(Body, { toastId: alert.id, type: alert.severity, autoClose: alert.autoDismiss ? 5000 : false, }); }; const handleModal = (alert: IAlert<"modal">) => { window.alert("alerts#handleModal triggered, but no implementation exists"); }; packages/client/src/lib/network.ts +4 −0 Original line number Diff line number Diff line Loading @@ -9,6 +9,7 @@ import { Subscription, } from "@sc07-canvas/lib/src/net"; import { toast } from "react-toastify"; import { handleAlert, handleDismiss } from "./alerts"; export interface INetworkEvents { connected: () => void; Loading Loading @@ -121,6 +122,9 @@ class Network extends EventEmitter<INetworkEvents> { this.socket.on("heatmap", (heatmap) => { this.emit("heatmap", heatmap); }); this.socket.on("alert", handleAlert); this.socket.on("alert_dismiss", handleDismiss); } subscribe(subscription: Subscription) { Loading packages/lib/src/net.ts +21 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,9 @@ export interface ServerToClientEvents { color: number ) => void; alert: (alert: IAlert) => void; alert_dismiss: (id: string) => void; /* --- subscribe events --- */ /** Loading Loading @@ -57,6 +60,24 @@ export interface IPosition { y: number; } export type IAlert<Is extends "toast" | "modal" = "toast" | "modal"> = { is: Is; action: "system" | "moderation"; id?: string; title: string; body?: string; } & ( | { is: "toast"; severity: "info" | "success" | "warning" | "error" | "default"; autoDismiss: boolean; } | { is: "modal"; dismissable: boolean; } ); // other export type Pixel = { Loading packages/server/src/lib/Canvas.ts +13 −0 Original line number Diff line number Diff line Loading @@ -166,6 +166,8 @@ class Canvas { * @returns 1D array of pixel values */ async canvasToRedis() { const now = Date.now(); Logger.info("Starting canvasToRedis..."); const redis = await Redis.getClient(); const dbpixels = await prisma.pixel.findMany({ Loading Loading @@ -198,6 +200,11 @@ class Canvas { await redis.set(Redis.key("canvas"), pixels.join(","), { EX: 60 * 5 }); Logger.info( "Finished canvasToRedis in " + ((Date.now() - now) / 1000).toFixed(2) + "s" ); return pixels; } Loading Loading @@ -234,6 +241,12 @@ class Canvas { await redis.set(Redis.key("canvas"), pixels.join(","), { EX: 60 * 5 }); } async isPixelArrayCached() { const redis = await Redis.getClient(); return await redis.exists(Redis.key("canvas")); } async getPixelsArray() { const redis = await Redis.getClient(); Loading packages/server/src/lib/SocketServer.ts +28 −3 Original line number Diff line number Diff line Loading @@ -181,9 +181,34 @@ export class SocketServer { } socket.emit("config", getClientConfig()); { let _clientNotifiedAboutCache = false; Canvas.isPixelArrayCached().then((cached) => { if (!cached) { _clientNotifiedAboutCache = true; socket.emit("alert", { id: "canvas_cache_pending", is: "toast", action: "system", severity: "info", title: "Canvas loading", body: "Canvas not cached, this may take a couple seconds", autoDismiss: true, }); } }); Canvas.getPixelsArray().then((pixels) => { socket.emit("canvas", pixels); socket.emit("alert_dismiss", "canvas_cache_pending"); socket.emit("alert", { is: "toast", action: "system", severity: "success", title: "Canvas loaded!", autoDismiss: true, }); }); } socket.on("disconnect", () => { Logger.debug(`Socket ${socket.id} disconnected`); Loading Loading
packages/client/src/lib/alerts.tsx 0 → 100644 +44 −0 Original line number Diff line number Diff line /** * Handle alerts sent by the server (moderation or internal) */ import { IAlert } from "@sc07-canvas/lib/src/net"; import { toast } from "react-toastify"; /** * Handles IAlert outside of react * @param alert */ export const handleAlert = (alert: IAlert) => { switch (alert.is) { case "toast": handleToast(alert); break; case "modal": handleModal(alert); break; } }; export const handleDismiss = (id: string) => { toast.dismiss(id); }; const handleToast = (alert: IAlert<"toast">) => { const Body = ( <> <b>{alert.title}</b> {alert.body && <> {alert.body}</>} </> ); toast(Body, { toastId: alert.id, type: alert.severity, autoClose: alert.autoDismiss ? 5000 : false, }); }; const handleModal = (alert: IAlert<"modal">) => { window.alert("alerts#handleModal triggered, but no implementation exists"); };
packages/client/src/lib/network.ts +4 −0 Original line number Diff line number Diff line Loading @@ -9,6 +9,7 @@ import { Subscription, } from "@sc07-canvas/lib/src/net"; import { toast } from "react-toastify"; import { handleAlert, handleDismiss } from "./alerts"; export interface INetworkEvents { connected: () => void; Loading Loading @@ -121,6 +122,9 @@ class Network extends EventEmitter<INetworkEvents> { this.socket.on("heatmap", (heatmap) => { this.emit("heatmap", heatmap); }); this.socket.on("alert", handleAlert); this.socket.on("alert_dismiss", handleDismiss); } subscribe(subscription: Subscription) { Loading
packages/lib/src/net.ts +21 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,9 @@ export interface ServerToClientEvents { color: number ) => void; alert: (alert: IAlert) => void; alert_dismiss: (id: string) => void; /* --- subscribe events --- */ /** Loading Loading @@ -57,6 +60,24 @@ export interface IPosition { y: number; } export type IAlert<Is extends "toast" | "modal" = "toast" | "modal"> = { is: Is; action: "system" | "moderation"; id?: string; title: string; body?: string; } & ( | { is: "toast"; severity: "info" | "success" | "warning" | "error" | "default"; autoDismiss: boolean; } | { is: "modal"; dismissable: boolean; } ); // other export type Pixel = { Loading
packages/server/src/lib/Canvas.ts +13 −0 Original line number Diff line number Diff line Loading @@ -166,6 +166,8 @@ class Canvas { * @returns 1D array of pixel values */ async canvasToRedis() { const now = Date.now(); Logger.info("Starting canvasToRedis..."); const redis = await Redis.getClient(); const dbpixels = await prisma.pixel.findMany({ Loading Loading @@ -198,6 +200,11 @@ class Canvas { await redis.set(Redis.key("canvas"), pixels.join(","), { EX: 60 * 5 }); Logger.info( "Finished canvasToRedis in " + ((Date.now() - now) / 1000).toFixed(2) + "s" ); return pixels; } Loading Loading @@ -234,6 +241,12 @@ class Canvas { await redis.set(Redis.key("canvas"), pixels.join(","), { EX: 60 * 5 }); } async isPixelArrayCached() { const redis = await Redis.getClient(); return await redis.exists(Redis.key("canvas")); } async getPixelsArray() { const redis = await Redis.getClient(); Loading
packages/server/src/lib/SocketServer.ts +28 −3 Original line number Diff line number Diff line Loading @@ -181,9 +181,34 @@ export class SocketServer { } socket.emit("config", getClientConfig()); { let _clientNotifiedAboutCache = false; Canvas.isPixelArrayCached().then((cached) => { if (!cached) { _clientNotifiedAboutCache = true; socket.emit("alert", { id: "canvas_cache_pending", is: "toast", action: "system", severity: "info", title: "Canvas loading", body: "Canvas not cached, this may take a couple seconds", autoDismiss: true, }); } }); Canvas.getPixelsArray().then((pixels) => { socket.emit("canvas", pixels); socket.emit("alert_dismiss", "canvas_cache_pending"); socket.emit("alert", { is: "toast", action: "system", severity: "success", title: "Canvas loaded!", autoDismiss: true, }); }); } socket.on("disconnect", () => { Logger.debug(`Socket ${socket.id} disconnected`); Loading