@@ -15,7 +15,7 @@ import { RootState } from '../../redux/store';
15
15
import { combineStyles } from '../../helperFunctions/combineStyles' ;
16
16
import renderChildren from '../../helperFunctions/renderChildren' ;
17
17
import { emitEvent , getSocket } from '../../helperFunctions/socket' ;
18
- import { GiBoba } from " react-icons/gi" ;
18
+ import { GiBoba } from ' react-icons/gi' ;
19
19
20
20
function Canvas ( props : { } ) : JSX . Element {
21
21
const state = useSelector ( ( store : RootState ) => store . appState ) ;
@@ -24,44 +24,62 @@ function Canvas(props: {}): JSX.Element {
24
24
const userName = useSelector ( ( store : RootState ) => store . roomSlice . userName ) ;
25
25
const userList = useSelector ( ( store : RootState ) => store . roomSlice . userList ) ;
26
26
27
- //-------mouse tracking-------
27
+ //-------cursors tracking-------
28
28
console . log ( 'canvas is rendered' ) ;
29
29
30
- //remote cursor data
31
- const [ remoteCursor , setRemoteCursor ] = useState ( {
32
- x : 0 ,
33
- y : 0 ,
34
- remoteUserName : '' ,
35
- isVisible : false
36
- } ) ;
30
+ const [ remoteCursors , setRemoteCursors ] = useState ( [ ] ) ;
37
31
38
32
const debounceSetPosition = debounce ( ( newX , newY ) => {
39
33
//emit socket event every 500ms when cursor moves
40
34
if ( userList . length > 1 )
41
35
emitEvent ( 'cursorData' , roomCode , { x : newX , y : newY , userName } ) ;
42
- } , 100 ) ;
36
+ } , 300 ) ;
43
37
44
38
const handleMouseMove = ( e ) => {
45
39
debounceSetPosition ( e . clientX , e . clientY ) ;
46
40
} ;
47
41
48
42
const socket = getSocket ( ) ;
49
43
if ( socket ) {
50
- // console.log('setting up socket listener');
51
44
socket . on ( 'remote cursor data from server' , ( remoteData ) => {
52
- setRemoteCursor ( ( prevState ) => {
53
- // check if the received data is different from the current state
54
- if ( prevState . x !== remoteData . x || prevState . y !== remoteData . y ) {
55
- return {
45
+ setRemoteCursors ( ( prevState ) => {
46
+ //check if received cursor data is from an existing user in the room
47
+ const cursorIdx = prevState . findIndex (
48
+ ( cursor ) => cursor . remoteUserName === remoteData . userName
49
+ ) ;
50
+
51
+ //[{x,y,remoteUserName, isVisible}, {...}, {...}]
52
+ //existing user
53
+ if ( cursorIdx >= 0 ) {
54
+ //check if cursor position has changed
55
+ if (
56
+ prevState [ cursorIdx ] . x !== remoteData . x ||
57
+ prevState [ cursorIdx ] . y !== remoteData . y
58
+ ) {
59
+ //update existing user's cursor position
60
+ const updatedCursors = [ ...prevState ] ;
61
+ updatedCursors [ cursorIdx ] = {
62
+ ...prevState [ cursorIdx ] ,
63
+ x : remoteData . x ,
64
+ y : remoteData . y
65
+ } ;
66
+ return updatedCursors ;
67
+ } else {
68
+ //return previous state if no change
69
+ return prevState ;
70
+ }
71
+ } else {
72
+ //new user: add new user's cursor
73
+ return [
56
74
...prevState ,
57
- x : remoteData . x ,
58
- y : remoteData . y ,
59
- remoteUserName : remoteData . userName ,
60
- isVisible : true
61
- } ;
75
+ {
76
+ x : remoteData . x ,
77
+ y : remoteData . y ,
78
+ remoteUserName : remoteData . userName ,
79
+ isVisible : true
80
+ }
81
+ ] ;
62
82
}
63
- // if data is the same, return the previous state to prevent re-render
64
- return prevState ;
65
83
} ) ;
66
84
} ) ;
67
85
}
@@ -235,21 +253,25 @@ function Canvas(props: {}): JSX.Element {
235
253
>
236
254
{ renderChildren ( currentComponent . children ) }
237
255
238
- { remoteCursor . isVisible && (
239
- < div
240
- className = "remote-cursor"
241
- style = { {
242
- position : 'absolute' ,
243
- left : remoteCursor . x + 'px' ,
244
- top : remoteCursor . y - 68 + 'px' ,
245
- //cursor style
246
- fontSize : '2em' ,
247
- color : userColors [ userList . indexOf ( remoteCursor . remoteUserName ) ]
248
- } }
249
- >
250
- { < GiBoba /> }
251
- { remoteCursor . remoteUserName }
252
- </ div >
256
+ { remoteCursors . map (
257
+ ( cursor , idx ) =>
258
+ cursor . isVisible && (
259
+ < div
260
+ key = { idx }
261
+ className = "remote-cursor"
262
+ style = { {
263
+ position : 'absolute' ,
264
+ left : cursor . x + 'px' ,
265
+ top : cursor . y - 68 + 'px' ,
266
+ //cursor style
267
+ fontSize : '2em' ,
268
+ color : userColors [ userList . indexOf ( cursor . remoteUserName ) ]
269
+ } }
270
+ >
271
+ { < GiBoba /> }
272
+ { cursor . remoteUserName }
273
+ </ div >
274
+ )
253
275
) }
254
276
</ div >
255
277
) ;
0 commit comments