@@ -22,6 +22,8 @@ const getRandomName = (): string => {
2222  return  `${ adjective }   ${ animal }  ` ; 
2323} ; 
2424
25+ 
26+ 
2527const  handleUsersAdded  =  ( 
2628  added : number [ ] , 
2729  currentUserId : number , 
@@ -54,7 +56,8 @@ const handleUsersRemoved = (
5456  removed : number [ ] , 
5557  currentUserId : number , 
5658  userNamesMap : Map < number ,  string > , 
57-   recentlyRemovedSet : Set < number > 
59+   recentlyRemovedSet : Set < number > , 
60+   timeoutRefsMap : Map < number ,  NodeJS . Timeout > 
5861) : void   =>  { 
5962  removed . forEach ( ( clientId )  =>  { 
6063    if  ( clientId  ===  currentUserId )  { 
@@ -74,10 +77,18 @@ const handleUsersRemoved = (
7477      icon : '👋' , 
7578    } ) ; 
7679
80+     // Clears any existing timeout for this client (prevents duplicates) 
81+     if  ( timeoutRefsMap . has ( clientId ) )  { 
82+       clearTimeout ( timeoutRefsMap . get ( clientId ) ) ; 
83+     } 
84+     
7785    // Clears debounce flag after timeout to allow future notifications 
78-     setTimeout ( ( )  =>  { 
86+     const   timeoutId   =   setTimeout ( ( )  =>  { 
7987      recentlyRemovedSet . delete ( clientId ) ; 
88+       timeoutRefsMap . delete ( clientId ) ; 
8089    } ,  USER_CONFIG . DUPLICATE_TOAST_DEBOUNCE_MS ) ; 
90+     
91+     timeoutRefsMap . set ( clientId ,  timeoutId ) ; 
8192  } ) ; 
8293} ; 
8394
@@ -90,7 +101,7 @@ export default function useCollabEditor({roomId}: {roomId: string}) {
90101  const  isFirstChangeRef  =  useRef < boolean > ( true ) ; 
91102  const  userNamesRef  =  useRef < Map < number ,  string > > ( new  Map ( ) ) ; 
92103  const  recentlyRemovedRef  =  useRef < Set < number > > ( new  Set ( ) ) ; 
93-   
104+   const   timeoutRefs   =   useRef ( new   Map < number ,   NodeJS . Timeout > ( ) ) ; 
94105
95106  useEffect ( ( )  =>  { 
96107    console . log ( 'useEffect RUNNING for room:' ,  roomId ) ; 
@@ -157,7 +168,10 @@ export default function useCollabEditor({roomId}: {roomId: string}) {
157168      console . log ( 'Processing awareness change (not initial sync), added:' ,  added ,  'removed:' ,  removed ) ; 
158169
159170      handleUsersAdded ( added ,  currUserId ,  provider . awareness ,  userNamesRef . current ) ; 
160-       handleUsersRemoved ( removed ,  currUserId ,  userNamesRef . current ,  recentlyRemovedRef . current ) ; 
171+       console . log ( timeoutRefs . current ) ; 
172+       handleUsersRemoved ( removed ,  currUserId ,  userNamesRef . current ,  recentlyRemovedRef . current ,  timeoutRefs . current ) ; 
173+       console . log ( timeoutRefs . current ) ; 
174+ 
161175    } ; 
162176
163177    provider . awareness . on ( 'change' ,  awarenessChangeHandler ) ; 
@@ -170,6 +184,11 @@ export default function useCollabEditor({roomId}: {roomId: string}) {
170184      userNamesRef . current . clear ( ) ; 
171185      recentlyRemovedRef . current . clear ( ) ; 
172186
187+       timeoutRefs . current . forEach ( ( timeoutId )  =>  { 
188+         clearTimeout ( timeoutId ) ; 
189+       } ) ; 
190+       timeoutRefs . current . clear ( ) ; 
191+ 
173192      setIsReady ( false ) ; 
174193      if  ( provider . awareness )  { 
175194        provider . awareness . setLocalState ( null ) ; 
0 commit comments