From cfdd222158a7ee9b2b7830028dd09b178d5062f9 Mon Sep 17 00:00:00 2001 From: Deveshi Dwivedi Date: Fri, 21 Jun 2024 12:57:40 +0530 Subject: [PATCH] refactor socket event handling --- common/recoil/options/options.hooks.ts | 9 ++- common/recoil/users/users.atoms.ts | 2 +- common/types/global.d.ts | 12 ++-- modules/room/helpers/Canvas.helpers.ts | 36 ++++------- modules/room/hooks/Canvas.hooks.ts | 87 +++++++++++++++----------- server/index.ts | 4 +- 6 files changed, 80 insertions(+), 70 deletions(-) diff --git a/common/recoil/options/options.hooks.ts b/common/recoil/options/options.hooks.ts index b151c15..dc71410 100644 --- a/common/recoil/options/options.hooks.ts +++ b/common/recoil/options/options.hooks.ts @@ -1,7 +1,12 @@ -import {useRecoilValue} from "recoil"; +import {useRecoilValue, useSetRecoilState} from "recoil"; import {optionsAtom} from "./options.atoms"; export const useOptions = () => { const options= useRecoilValue(optionsAtom); return options; -}; \ No newline at end of file +}; + +export const useSetOptions = () => { + const setOptions = useSetRecoilState(optionsAtom); + return setOptions; +} \ No newline at end of file diff --git a/common/recoil/users/users.atoms.ts b/common/recoil/users/users.atoms.ts index 87b1b26..147967a 100644 --- a/common/recoil/users/users.atoms.ts +++ b/common/recoil/users/users.atoms.ts @@ -1,6 +1,6 @@ import {atom,selector} from "recoil"; -export const usersAtom = atom<{ [key:string]: [number,number][][]}> ({ +export const usersAtom = atom<{ [key:string]: Move[]}> ({ key: "users", default: {}, }); diff --git a/common/types/global.d.ts b/common/types/global.d.ts index 9ea07bf..867df67 100644 --- a/common/types/global.d.ts +++ b/common/types/global.d.ts @@ -4,11 +4,13 @@ export declare global { lineColor: string; } + interface Move { + path: [number, number][]; + options: CtxOptions; + } + interface ServerToClientEvents { - user_draw: (newMoves: [number, number][], - options: CtxOptions, - userId: string - ) => void; + user_draw: (move: Move, userId: string) => void; user_undo(userId: string): void; mouse_moved: (x:number, y:number, socketId: string) => void; users_in_room: (socketIds: string[]) => void; @@ -16,7 +18,7 @@ export declare global { } interface ClientToServerEvents { - draw: (moves: [number, number][], options: CtxOptions) => void; + draw: (move: Move) => void; mouse_move: (x:number, y:number) => void; undo: () => void; } diff --git a/modules/room/helpers/Canvas.helpers.ts b/modules/room/helpers/Canvas.helpers.ts index 61ca91f..b6dc17a 100644 --- a/modules/room/helpers/Canvas.helpers.ts +++ b/modules/room/helpers/Canvas.helpers.ts @@ -1,50 +1,36 @@ -export const drawFromSocket = ( - socketMoves: [number, number][], - socketOptions: CtxOptions, +export const handleMove = ( + move: Move, ctx: CanvasRenderingContext2D, - afterDraw: ()=> void )=>{ + const {options, path} = move; const tempCtx = ctx; if(tempCtx){ - tempCtx.lineWidth= socketOptions.lineWidth; - tempCtx.strokeStyle= socketOptions.lineColor; + tempCtx.lineWidth= options.lineWidth; + tempCtx.strokeStyle= options.lineColor; tempCtx.beginPath(); - socketMoves.forEach(([x,y])=>{ + path.forEach(([x,y])=>{ tempCtx.lineTo(x,y); }); tempCtx.stroke(); tempCtx.closePath(); - afterDraw(); } }; export const drawOnUndo = ( ctx: CanvasRenderingContext2D, - savedMoves: [number, number][][], - users: {[key:string]: [number, number][][]} + savedMoves: Move[], + users: {[key: string]: Move[]} ) => { ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); Object.values(users).forEach((user)=>{ - user.forEach((userMove)=>{ - ctx.beginPath(); - userMove.forEach(([x,y])=>{ - ctx.lineTo(x,y); - }); - ctx.stroke(); - ctx.closePath(); - }); + user.forEach((move)=> handleMove(move,ctx)); }); - savedMoves.forEach((movesArr)=> { - ctx.beginPath(); - movesArr.forEach(([x,y])=>{ - ctx.lineTo(x,y); - }); - ctx.stroke(); - ctx.closePath(); + savedMoves.forEach((move)=> { + handleMove(move,ctx); }); diff --git a/modules/room/hooks/Canvas.hooks.ts b/modules/room/hooks/Canvas.hooks.ts index 8b92495..3d83040 100644 --- a/modules/room/hooks/Canvas.hooks.ts +++ b/modules/room/hooks/Canvas.hooks.ts @@ -1,13 +1,13 @@ import { useCallback, useEffect, useState } from "react"; import { socket } from "@/common/lib/socket"; import { useOptions } from "@/common/recoil/options"; -import { drawOnUndo } from "../helpers/Canvas.helpers"; +import { drawOnUndo, handleMove } from "../helpers/Canvas.helpers"; import usersAtom, { useUsers } from "@/common/recoil/users"; import { useBoardPosition } from "./useBoardPosition"; import { getPos } from "@/common/lib/getPos"; import { useSetRecoilState } from "recoil"; -const savedMoves: [number, number][][] = []; +const savedMoves: Move[] = []; let moves: [number, number][] = []; export const useDraw = ( @@ -68,12 +68,16 @@ export const useDraw = ( const handleEndDrawing = () => { if (!ctx || blocked) return; - setDrawing(false); ctx.closePath(); + setDrawing(false); - savedMoves.push(moves); + const move: Move= { + path: moves, options + } + + savedMoves.push(move); - socket.emit("draw", moves, options); + socket.emit("draw", move); moves = []; handleEnd(); }; @@ -98,52 +102,65 @@ export const useDraw = ( // Hook to listen for user draw & undo events export const useSocketDraw = ( ctx: CanvasRenderingContext2D | undefined, + drawing : boolean, handleEnd: () => void ) => { const setUsers = useSetRecoilState(usersAtom); useEffect(() => { - socket.on("user_draw", (newMoves, options, userId) => { - if (ctx) { - ctx.lineWidth = options.lineWidth; - ctx.strokeStyle = options.lineColor; - ctx.beginPath(); - - newMoves.forEach(([x, y]) => { - ctx.lineTo(x, y); - }); - ctx.stroke(); - ctx.closePath(); - handleEnd(); + let movesToDrawLater: Move | undefined; + let userIdLater= ""; + socket.on("user_draw", (move, userId) => { + if (ctx && !drawing) { + handleMove(move, ctx); + setUsers((prevUsers) => { const newUsers = { ...prevUsers }; - // newUsers[userId] is initialized as an array - if (!Array.isArray(newUsers[userId])) { - newUsers[userId] = []; - } - newUsers[userId] = [...newUsers[userId], newMoves]; + // error maybe here + if (newUsers[userId]) newUsers[userId] = [...newUsers[userId], move]; return newUsers; }); + }else { + movesToDrawLater = move; + userIdLater = userId; } }); - socket.on("user_undo", (userId) => { + + + return () => { + socket.off("user_draw"); + + if(movesToDrawLater && userIdLater && ctx){ + handleMove(movesToDrawLater, ctx); + handleEnd(); setUsers((prevUsers) => { const newUsers = { ...prevUsers }; - if (Array.isArray(newUsers[userId])) { - newUsers[userId] = newUsers[userId].slice(0, -1); - } - if (ctx) { - drawOnUndo(ctx, savedMoves, newUsers); - handleEnd(); - } - return newUsers; - }); + newUsers[userIdLater]= [ + ...newUsers[userIdLater], movesToDrawLater as Move]; + return newUsers; + }) + } + }; + }, [ctx, handleEnd, setUsers, drawing ]); + + useEffect(()=> { + socket.on("user_undo", (userId) => { + setUsers((prevUsers) => { + const newUsers = { ...prevUsers }; + if (Array.isArray(newUsers[userId])) { + newUsers[userId] = newUsers[userId].slice(0, -1); + } + if (ctx) { + drawOnUndo(ctx, savedMoves, newUsers); + handleEnd(); + } + return newUsers; }); - + }); return () => { - socket.off("user_draw"); socket.off("user_undo"); }; - }, [ctx, handleEnd, setUsers]); + },[ctx, handleEnd, setUsers]); + }; diff --git a/server/index.ts b/server/index.ts index b7c2e2c..e384dfe 100644 --- a/server/index.ts +++ b/server/index.ts @@ -25,9 +25,9 @@ io.on("connection", (socket)=>{ const allUsers= io.sockets.adapter.rooms.get("global"); if (allUsers) io.to("global").emit("users_in_room", [...allUsers]); - socket.on("draw", (moves, options)=>{ + socket.on("draw", (move)=>{ console.log("drawing"); - socket.broadcast.emit("user_draw", moves, options, socket.id); + socket.broadcast.emit("user_draw", move, socket.id); }); socket.on("mouse_move", (x,y) => {