diff --git a/modules/home/components/Home.tsx b/modules/home/components/Home.tsx index 06a9cd0..9e1fc29 100644 --- a/modules/home/components/Home.tsx +++ b/modules/home/components/Home.tsx @@ -43,6 +43,11 @@ const Home = () => { }; }, [openModal, roomId, router, setAtomRoomId]); + useEffect(()=> { + socket.emit("leave_room"); + setAtomRoomId(""); + },[setAtomRoomId]); + const handleCreateRoom = () => { socket.emit("create_room", username); }; diff --git a/modules/room/components/Room.tsx b/modules/room/components/Room.tsx index 06a5ebf..9767893 100644 --- a/modules/room/components/Room.tsx +++ b/modules/room/components/Room.tsx @@ -15,15 +15,14 @@ import Chat from "./chat/Chat"; const Room = () => { const room = useRoom(); - const undoRef= useRef(null); if(!room.id) return ; return (
- - + + diff --git a/modules/room/components/board/Background.tsx b/modules/room/components/board/Background.tsx index 7cf8949..cf00d97 100644 --- a/modules/room/components/board/Background.tsx +++ b/modules/room/components/board/Background.tsx @@ -1,14 +1,13 @@ -import { useEffect, useRef } from "react"; +import { RefObject, useEffect } from "react"; import { useBoardPosition } from "../../hooks/useBoardPosition"; import {motion} from "framer-motion"; import { CANVAS_SIZE } from "@/common/constants/canvasSize"; -const Background = () => { +const Background = ({bgRef}: {bgRef: RefObject}) => { const {x,y} = useBoardPosition(); - const ref= useRef(null); - + useEffect(()=> { - const ctx= ref.current?.getContext("2d"); + const ctx=bgRef.current?.getContext("2d"); if(ctx){ ctx.fillStyle="#fff"; @@ -30,10 +29,10 @@ const Background = () => { ctx.stroke(); } } - },[]); + },[bgRef]); return ( }) => { - const room= useRoom(); - const options= useOptionsValue(); - const canvasRef = useRef(null); +const Canvas = () => { + const room = useRoom(); + const options = useOptionsValue(); + const { canvasRef, bgRef, undoRef } = useRefs(); // Call the hook as a function const smallCanvasRef = useRef(null); const [ctx, setCtx] = useState(); @@ -25,21 +25,20 @@ const Canvas = ({undoRef}: {undoRef: RefObject}) => { const [, setMovedMiniMap] = useState(false); const { width, height } = useViewportSize(); - const {x,y} = useBoardPosition(); + const { x, y } = useBoardPosition(); useKeyPressEvent("Control", (e) => { if (e.ctrlKey && !dragging) { setDragging(true); } }); - - const copyCanvasToSmall = () => { + const copyCanvasToSmall = useCallback(() => { if (canvasRef.current && smallCanvasRef.current) { const smallCtx = smallCanvasRef.current.getContext("2d"); - if (smallCtx){ + if (smallCtx) { smallCtx.clearRect(0, 0, CANVAS_SIZE.width, CANVAS_SIZE.height); - smallCtx.drawImage( + smallCtx.drawImage( canvasRef.current, 0, 0, @@ -47,16 +46,12 @@ const Canvas = ({undoRef}: {undoRef: RefObject}) => { CANVAS_SIZE.height ); } - } - }; + }, [canvasRef, smallCanvasRef]); - const { handleEndDrawing, handleDraw, handleStartDrawing, drawing, handleUndo } = useDraw( - ctx, - dragging - ); + const { handleEndDrawing, handleDraw, handleStartDrawing, drawing, handleUndo } = useDraw(ctx, dragging); - useSocketDraw(ctx,drawing); + useSocketDraw(ctx, drawing); useEffect(() => { const newCtx = canvasRef.current?.getContext("2d"); @@ -69,27 +64,26 @@ const Canvas = ({undoRef}: {undoRef: RefObject}) => { } window.addEventListener("keyup", handleKeyUp); - const undoBtn= undoRef.current; + const undoBtn = undoRef.current; undoBtn?.addEventListener("click", handleUndo); return () => { window.removeEventListener("keyup", handleKeyUp); undoBtn?.removeEventListener("click", handleUndo); } - }, [dragging, handleUndo, undoRef]); + }, [dragging, handleUndo, undoRef, canvasRef]); - useEffect(()=> { - if(ctx) socket.emit("joined_room"); - },[ctx]); + useEffect(() => { + if (ctx) socket.emit("joined_room"); + }, [ctx]); - useEffect(()=> { - if(ctx){ + useEffect(() => { + if (ctx) { drawAllMoves(ctx, room, options); copyCanvasToSmall(); - }; + } }, [ctx, room, options]); - return (
}) => { ); }} /> - + }) => { }; export default Canvas; -function copyCanvasToSmall() { - throw new Error("Function not implemented."); -} - diff --git a/modules/room/components/toolbar/ToolBar.tsx b/modules/room/components/toolbar/ToolBar.tsx index db134f3..854f914 100644 --- a/modules/room/components/toolbar/ToolBar.tsx +++ b/modules/room/components/toolbar/ToolBar.tsx @@ -6,8 +6,29 @@ import { BsFillChatFill, BsFillImageFill, BsThreeDots } from "react-icons/bs"; import { HiOutlineDownload } from "react-icons/hi"; import { FaUndo } from "react-icons/fa"; import ShapeSelector from "./ShapeSelector"; +import { useRefs } from "../../hooks/useRefs"; +import { CANVAS_SIZE } from "@/common/constants/canvasSize"; -export const ToolBar = ({undoRef}: {undoRef: RefObject}) => { +export const ToolBar = ( ) => { + const {canvasRef, bgRef, undoRef}= useRefs(); + const handleDownload= ()=> { + const canvas= document.createElement('canvas'); + canvas.width= CANVAS_SIZE.width; + canvas.height= CANVAS_SIZE.height; + + const tempCtx= canvas.getContext('2d'); + + if(tempCtx && canvasRef.current && bgRef.current){ + tempCtx.drawImage(bgRef.current, 0, 0); + tempCtx.drawImage(canvasRef.current, 0, 0); + } + + const link= document.createElement('a'); + link.href= canvas.toDataURL("image/png"); + link.download="canvas.png"; + link.click(); + + }; return (
}) => { + diff --git a/modules/room/context/Room.context.tsx b/modules/room/context/Room.context.tsx index 27c6a5e..585ba95 100644 --- a/modules/room/context/Room.context.tsx +++ b/modules/room/context/Room.context.tsx @@ -3,7 +3,7 @@ import { socket } from "@/common/lib/socket"; import { useSetRoom, useSetUsers } from "@/common/recoil/room/room.hooks"; import usersAtom, { useUserIds } from "@/common/recoil/users"; import { MotionValue, useMotionValue } from "framer-motion"; -import { createContext, ReactChild, useEffect } from "react"; +import { createContext, ReactChild, RefObject, useEffect, useRef } from "react"; import { useSet } from "react-use"; import { useSetRecoilState } from "recoil"; @@ -11,6 +11,9 @@ import { useSetRecoilState } from "recoil"; export const roomContext = createContext<{ x: MotionValue; y: MotionValue; + undoRef: RefObject; + canvasRef: RefObject; + bgRef: RefObject; }>(null!); const RoomContextProvider = ({ children }: { children: ReactChild }) => { @@ -19,6 +22,9 @@ const RoomContextProvider = ({ children }: { children: ReactChild }) => { const {handleAddUser, handleRemoveUser} = useSetUsers(); const x = useMotionValue(0); const y = useMotionValue(0); + const undoRef = useRef(null); + const canvasRef = useRef(null); + const bgRef = useRef(null); // socket events for user join/leave and clean up listeners useEffect(()=> { @@ -64,7 +70,7 @@ const RoomContextProvider = ({ children }: { children: ReactChild }) => { }, [handleAddUser, handleRemoveUser, setRoom]); //motion values to context consumers return ( - + {children} ); diff --git a/modules/room/hooks/useRefs.ts b/modules/room/hooks/useRefs.ts new file mode 100644 index 0000000..4794b81 --- /dev/null +++ b/modules/room/hooks/useRefs.ts @@ -0,0 +1,12 @@ +import { useContext } from "react"; +import { roomContext } from "../context/Room.context"; + +export const useRefs= ()=> { + const {undoRef, bgRef, canvasRef} = useContext(roomContext); + + return{ + undoRef, + bgRef, + canvasRef, + }; +} \ No newline at end of file diff --git a/server/index.ts b/server/index.ts index ccd6fad..fc91e1e 100644 --- a/server/index.ts +++ b/server/index.ts @@ -3,6 +3,7 @@ import express from "express"; import next from "next"; import { Server } from "socket.io"; import {} from "@/common/types/global"; +import { socket } from "@/common/lib/socket"; const port = parseInt(process.env.PORT || "3000", 10); const dev = process.env.NODE_ENV !== "production"; @@ -35,17 +36,6 @@ nextApp.prepare().then(async () => { room?.usersMoves.get(socketId)?.pop(); }; - const leaveRoom = (roomId: string, socketId: string) => { - const room= rooms.get(roomId); - - if(!room) return; - - const userMoves= room?.usersMoves.get(socketId)!; - room?.drawed.push(...userMoves); - room?.users.delete(socketId); - - console.log("user left room"); - }; io.on("connection", (socket) => { //get the room id the socket is currently in, excluding its own id @@ -54,6 +44,22 @@ nextApp.prepare().then(async () => { if(!joinedRoom) return socket.id; return joinedRoom; } + const leaveRoom = (roomId: string, socketId: string) => { + const room= rooms.get(roomId); + + if(!room) return; + + const userMoves= room.usersMoves.get(socketId)!; + + if(userMoves) room.drawed.push(...userMoves); + + room.users.delete(socketId); + socket.leave(roomId); + + console.log("user left room"); + }; + + console.log("connection"); socket.on("create_room", (username) => {