11"use client"
22
3- import { useWebSocket } from "@/hooks/useWebSocket" ;
43import { Game } from "@/draw/Game" ;
5- import { BgFill , canvasBgLight , Shape , StrokeEdge , StrokeFill , StrokeStyle , StrokeWidth , ToolType } from "@/types/canvas" ;
6- import { useCallback , useEffect , useRef , useState } from "react" ;
4+ import { BgFill , canvasBgLight , StrokeEdge , StrokeFill , StrokeStyle , StrokeWidth , ToolType } from "@/types/canvas" ;
5+ import React , { useCallback , useEffect , useRef , useState } from "react" ;
76import { Scale } from "../Scale" ;
87import { MobileNavbar } from "../mobile-navbar" ;
98import { useTheme } from "next-themes" ;
@@ -15,8 +14,11 @@ import Toolbar from "../Toolbar";
1514import ScreenLoading from "../ScreenLoading" ;
1615import CollaborationStart from "../CollaborationStartBtn" ;
1716import { cn } from "@/lib/utils" ;
17+ import { RoomParticipants , WebSocketMessage , WS_DATA_TYPE } from "@repo/common/types" ;
1818
19- export function CanvasSheet ( { roomName, roomId, userId, userName, token } : { roomName : string ; roomId : string ; userId : string ; userName : string ; token : string } ) {
19+ const WS_URL = process . env . NEXT_PUBLIC_WS_URL || 'ws://localhost:8080' ;
20+
21+ export const CanvasSheet = React . memo ( function CanvasSheet ( { roomName, roomId, userId, userName, token } : { roomName : string ; roomId : string ; userId : string ; userName : string ; token : string } ) {
2022 const { theme } = useTheme ( )
2123 const canvasRef = useRef < HTMLCanvasElement > ( null ) ;
2224 const [ game , setGame ] = useState < Game > ( ) ;
@@ -28,7 +30,6 @@ export function CanvasSheet({ roomName, roomId, userId, userName, token }: { roo
2830 const [ strokeEdge , setStrokeEdge ] = useState < StrokeEdge > ( "round" ) ;
2931 const [ strokeStyle , setStrokeStyle ] = useState < StrokeStyle > ( "solid" ) ;
3032 const [ grabbing , setGrabbing ] = useState ( false ) ;
31- const [ existingShapes , setExistingShapes ] = useState < Shape [ ] > ( [ ] ) ;
3233 const paramsRef = useRef ( { roomId, roomName, userId, userName } ) ;
3334 const activeToolRef = useRef ( activeTool ) ;
3435 const strokeFillRef = useRef ( strokeFill ) ;
@@ -39,22 +40,73 @@ export function CanvasSheet({ roomName, roomId, userId, userName, token }: { roo
3940 const [ sidebarOpen , setSidebarOpen ] = useState ( false ) ;
4041 const [ canvasColor , setCanvasColor ] = useState < string > ( canvasBgLight [ 0 ] ) ;
4142 const canvasColorRef = useRef ( canvasColor ) ;
43+ const { matches, isLoading } = useMediaQuery ( 'md' ) ;
44+ const [ socket , setSocket ] = useState < WebSocket | null > ( null ) ;
45+ const [ participants , setParticipants ] = useState < RoomParticipants [ ] > ( [ ] ) ;
46+ const gameRef = useRef < Game | null > ( null ) ;
47+ const socketConnected = useRef ( false ) ;
4248
43- const { isConnected, messages, participants, sendDrawingData } = useWebSocket (
44- roomId ,
45- roomName ,
46- userId ,
47- userName ,
48- token
49- ) ;
49+ useEffect ( ( ) => {
50+ console . log ( 'E1' )
51+ if ( ! roomId || ! roomName || ! userId || ! userName || ! token ) return ;
52+ if ( socket || socketConnected . current ) return ;
53+ const wsUrl = `${ WS_URL } ?token=${ encodeURIComponent ( token ) } ` ;
54+ const ws = new WebSocket ( wsUrl ) ;
55+ socketConnected . current = true ;
56+
57+ ws . onopen = ( ) => {
58+ ws . send ( JSON . stringify ( {
59+ type : WS_DATA_TYPE . JOIN ,
60+ roomId,
61+ roomName,
62+ userId,
63+ userName
64+ } ) ) ;
65+ setSocket ( ws ) ;
66+ } ;
5067
51- const { matches, isLoading } = useMediaQuery ( 'md' ) ;
68+ ws . onmessage = ( event ) => {
69+ const data : WebSocketMessage = JSON . parse ( event . data ) ;
70+
71+ if ( data . participants ) {
72+ setParticipants ( data . participants ) ;
73+ } else if ( data . type === WS_DATA_TYPE . USER_JOINED ) {
74+ setParticipants ( prev => {
75+ const exists = prev . some ( p => p . userId === data . userId ) ;
76+ if ( ! exists ) {
77+ return [ ...prev , { userId : data . userId ! , userName : data . userName ! } ] ;
78+ }
79+ return prev ;
80+ } ) ;
81+ } else if ( data . type === WS_DATA_TYPE . USER_LEFT ) {
82+ setParticipants ( prev => prev . filter ( user => user . userId !== data . userId ) ) ;
83+ }
84+
85+ if ( [ WS_DATA_TYPE . DRAW , WS_DATA_TYPE . ERASER , WS_DATA_TYPE . UPDATE ] . includes ( data . type ) ) {
86+ gameRef . current ?. handleWebSocketMessage ( data ) ;
87+ }
88+ } ;
89+
90+ ws . onerror = ( error ) => console . error ( 'WebSocket error:' , error ) ;
91+
92+ return ( ) => {
93+ ws . close ( ) ;
94+ socketConnected . current = false ;
95+ } ;
96+ } , [ roomId , roomName , userId , userName , token ] ) ;
5297
5398 useEffect ( ( ) => {
99+ console . log ( 'E2' )
100+ paramsRef . current = { roomId, roomName, userId, userName } ;
101+ } , [ roomId , roomName , userId , userName ] ) ;
102+
103+ useEffect ( ( ) => {
104+ console . log ( 'E3' )
54105 setCanvasColor ( canvasBgLight [ 0 ] ) ;
55106 } , [ theme ] )
56107
57108 useEffect ( ( ) => {
109+ console . log ( 'E4' )
58110 const handleResize = ( ) => {
59111 if ( canvasRef . current && game ) {
60112 const canvas = canvasRef . current ;
@@ -68,95 +120,69 @@ export function CanvasSheet({ roomName, roomId, userId, userName, token }: { roo
68120 return ( ) => window . removeEventListener ( 'resize' , handleResize ) ;
69121 } , [ game ] ) ;
70122
71- useEffect ( ( ) => {
72- paramsRef . current = { roomId, roomName, userId, userName } ;
73- } , [ roomId , roomName , userId , userName ] ) ;
74-
75- useEffect ( ( ) => {
76- if ( messages . length > 0 ) {
77- try {
78- messages . forEach ( ( message ) => {
79- try {
80- const data = JSON . parse ( message . message ) ;
81- console . log ( 'ws msg data = ' , data )
82- if ( data . type === "draw" ) {
83- const shape = JSON . parse ( data . data ) . shape ;
84- setExistingShapes ( ( prevShapes ) => [ ...prevShapes , shape ] ) ;
85- } else if ( data . type === "eraser" ) {
86- const shape = JSON . parse ( data . data ) . shape ;
87- setExistingShapes ( ( prevShapes ) =>
88- prevShapes . filter ( ( s ) => JSON . stringify ( s ) !== JSON . stringify ( shape ) )
89- ) ;
90- }
91- } catch ( e ) {
92- console . error ( "Error processing message:" , e ) ;
93- }
94- } ) ;
95- } catch ( e ) {
96- console . error ( "Error processing messages:" , e ) ;
97- }
98- }
99- } , [ messages ] ) ;
100-
101- useEffect ( ( ) => {
102- game ?. setTool ( activeTool )
103- game ?. setStrokeWidth ( strokeWidth )
104- game ?. setStrokeFill ( strokeFill )
105- game ?. setBgFill ( bgFill )
106- game ?. setCanvasBgColor ( canvasColor )
107- game ?. setStrokeEdge ( strokeEdge )
108- } ) ;
123+ // useEffect(() => {
124+ // console.log('E5')
125+ // game?.setTool(activeTool)
126+ // game?.setStrokeWidth(strokeWidth)
127+ // game?.setStrokeFill(strokeFill)
128+ // game?.setBgFill(bgFill)
129+ // game?.setCanvasBgColor(canvasColor)
130+ // game?.setStrokeEdge(strokeEdge)
131+ // });
109132
110133 useEffect ( ( ) => {
134+ console . log ( 'E6' )
111135 strokeEdgeRef . current = strokeEdge ;
112136 game ?. setStrokeEdge ( strokeEdge ) ;
113137 } , [ strokeEdge , game ] ) ;
114138
115139 useEffect ( ( ) => {
140+ console . log ( 'E7' )
116141 strokeStyleRef . current = strokeStyle ;
117142 game ?. setStrokeStyle ( strokeStyle ) ;
118143 } , [ strokeStyle , game ] ) ;
119144
120145 useEffect ( ( ) => {
146+ console . log ( 'E8' )
121147 activeToolRef . current = activeTool ;
122148 game ?. setTool ( activeTool ) ;
123149 } , [ activeTool , game ] ) ;
124150
125151 useEffect ( ( ) => {
152+ console . log ( 'E9' )
126153 strokeWidthRef . current = strokeWidth ;
127154 game ?. setStrokeWidth ( strokeWidth ) ;
128155 } , [ strokeWidth , game ] ) ;
129156
130157 useEffect ( ( ) => {
158+ console . log ( 'E10' )
131159 strokeFillRef . current = strokeFill ;
132160 game ?. setStrokeFill ( strokeFill ) ;
133161 } , [ strokeFill , game ] ) ;
134162
135163 useEffect ( ( ) => {
164+ console . log ( 'E11' )
136165 bgFillRef . current = bgFill ;
137166 game ?. setBgFill ( bgFill ) ;
138167 } , [ bgFill , game ] ) ;
139168
140169 useEffect ( ( ) => {
141- if ( game && existingShapes . length >= 0 ) {
142- game . updateShapes ( existingShapes ) ;
143- }
144- } , [ game , existingShapes ] ) ;
145-
146- useEffect ( ( ) => {
170+ console . log ( 'E12' )
147171 if ( game && canvasColorRef . current !== canvasColor ) {
148172 canvasColorRef . current = canvasColor ;
149173 game . setCanvasBgColor ( canvasColor ) ;
150174 }
151175 } , [ canvasColor , game ] ) ;
152176
153177 useEffect ( ( ) => {
178+ console . log ( 'E13' )
154179 if ( game ) {
155180 game . setScale ( scale ) ;
156181 }
157182 } , [ scale , game ] ) ;
158183
159184 useEffect ( ( ) => {
185+ console . log ( 'E14' )
160186 const handleKeyDown = ( e : KeyboardEvent ) => {
161187 switch ( e . key ) {
162188 case "1" :
@@ -188,60 +214,46 @@ export function CanvasSheet({ roomName, roomId, userId, userName, token }: { roo
188214 return ( ) => {
189215 document . removeEventListener ( "keydown" , handleKeyDown ) ;
190216 } ;
191- } , [ setActiveTool ] ) ;
192-
193- const handleSendDrawing = useCallback ( ( drawingData : string ) => {
194- if ( isConnected ) {
195- sendDrawingData ( JSON . stringify ( drawingData ) ) ;
196-
197- }
198- } , [ isConnected , sendDrawingData ] ) ;
199-
200- // const handleEraserComplete = useCallback((eraserData: string) => {
201- // if (isConnected) {
202- // sendEraserData(JSON.stringify(eraserData));
217+ } , [ ] ) ;
203218
219+ // useEffect(() => {
220+ // console.log('E15')
221+ // try {
222+ // console.log('participants = ', participants)
223+ // } catch (e) {
224+ // console.error("Error processing messages:", e);
204225 // }
205- // }, [isConnected, sendEraserData]);
206-
207- useEffect ( ( ) => {
208- try {
209- console . log ( 'participants = ' , participants )
210- } catch ( e ) {
211- console . error ( "Error processing messages:" , e ) ;
212- }
213- } , [ participants ] ) ;
226+ // }, [participants]);
214227
215228 useEffect ( ( ) => {
216- if ( canvasRef . current ) {
217- const game = new Game (
218- canvasRef . current ,
219- paramsRef . current . roomId ,
220- canvasColorRef . current ,
221- handleSendDrawing ,
222- paramsRef . current . roomName ,
223- ( newScale ) => setScale ( newScale ) ,
224- [ ]
225- )
226- setGame ( game ) ;
227-
228- game . setTool ( activeToolRef . current ) ;
229- game . setStrokeWidth ( strokeWidthRef . current ) ;
230- game . setStrokeFill ( strokeFillRef . current ) ;
231- game . setBgFill ( bgFillRef . current ) ;
232- game . setStrokeEdge ( strokeEdgeRef . current ) ;
233-
234- canvasRef . current . width = window . innerWidth ;
235- canvasRef . current . height = window . innerHeight ;
229+ console . log ( 'E16' )
230+ if ( ! canvasRef . current || ! socket || gameRef . current ) return ;
231+
232+ const game = new Game (
233+ canvasRef . current ,
234+ paramsRef . current . roomId ,
235+ canvasColorRef . current ,
236+ paramsRef . current . roomName ,
237+ ( newScale ) => setScale ( newScale ) ,
238+ [ ] ,
239+ false ,
240+ socket
241+ ) ;
242+
243+ gameRef . current = game ;
244+ setGame ( game ) ;
245+
246+ canvasRef . current . width = window . innerWidth ;
247+ canvasRef . current . height = window . innerHeight ;
236248
237- return ( ) => {
238- game . destroy ( ) ;
239- }
240- }
241-
242- } , [ canvasRef , handleSendDrawing ] ) ;
249+ return ( ) => {
250+ gameRef . current ?. destroy ( ) ;
251+ gameRef . current = null ;
252+ } ;
253+ } , [ socket ] ) ;
243254
244255 useEffect ( ( ) => {
256+ console . log ( 'E17' )
245257 if ( activeTool === "grab" ) {
246258 const handleGrab = ( ) => {
247259 setGrabbing ( ( prev ) => ! prev )
@@ -257,20 +269,24 @@ export function CanvasSheet({ roomName, roomId, userId, userName, token }: { roo
257269 }
258270 } , [ activeTool ] ) ;
259271
260- useEffect ( ( ) => {
261- if ( game ?. outputScale ) {
262- setScale ( game . outputScale ) ;
263- }
264- } , [ game ?. outputScale ] ) ;
272+ // useEffect(() => {
273+ // console.log('E18')
274+ // if (game?.outputScale) {
275+ // setScale(game.outputScale);
276+ // }
277+ // }, [game?.outputScale]);
265278
266279 const toggleSidebar = useCallback ( ( ) => {
280+ console . log ( 'E19' )
267281 setSidebarOpen ( prev => ! prev ) ;
268282 } , [ ] ) ;
269283
270284 if ( isLoading ) {
271- return (
272- < ScreenLoading />
273- )
285+ return < ScreenLoading />
286+ }
287+
288+ if ( ! socket ) {
289+ return < ScreenLoading content = "Connecting ..." />
274290 }
275291
276292 return (
@@ -352,4 +368,4 @@ export function CanvasSheet({ roomName, roomId, userId, userName, token }: { roo
352368 < canvas className = { cn ( "collabydraw collabydraw-canvas" , theme === 'dark' ? 'collabydraw-canvas-dark' : '' ) } ref = { canvasRef } />
353369 </ div >
354370 )
355- }
371+ } ) ;
0 commit comments