UNPKG

vzcode

Version:
86 lines (72 loc) 2.48 kB
import { useEffect, useRef } from 'react'; import { Presence, PresenceId } from '../types'; import { VizFileId } from '@vizhub/viz-types'; const DEBUG = false; /** * Custom hook that handles auto-following users by opening tabs when presence * is received on files that are not currently open. This logic is independent * of CodeMirror extensions and works regardless of editor cache state. */ export const usePresenceAutoFollow = ({ docPresence, enableAutoFollow, openTab, activePane, }) => { // Track enableAutoFollow on a ref for use in event handlers const enableAutoFollowRef = useRef(enableAutoFollow); useEffect(() => { enableAutoFollowRef.current = enableAutoFollow; }, [enableAutoFollow]); // Track active file for comparison const activeFileIdRef = useRef(activePane?.activeFileId); useEffect(() => { activeFileIdRef.current = activePane?.activeFileId; }, [activePane?.activeFileId]); useEffect(() => { if (!docPresence) return; const handlePresenceReceive = ( id: PresenceId, presence: Presence, ) => { if (DEBUG) { console.log( `[usePresenceAutoFollow] Received presence for id ${id}`, presence, ); } // If presence is null, the user has disconnected if (!presence) { return; } // If auto-follow is not enabled, do nothing if (!enableAutoFollowRef.current) { return; } // Extract the file ID from the presence path // Presence path structure: [path, to, file, fileId, position] // We want the fileId which should be at index 1 for files const presenceFileId = presence.start[1] as VizFileId; // If the presence is for the currently active file, do nothing // (the CodeMirror extension will handle displaying the cursor) if (presenceFileId === activeFileIdRef.current) { return; } // If the presence is for a different file, open that tab DEBUG && console.log( `[usePresenceAutoFollow] Auto-opening tab for ${presence.username} in file ${presenceFileId}`, ); openTab({ fileId: presenceFileId, isTransient: true, }); }; // Subscribe to presence changes docPresence.on('receive', handlePresenceReceive); // Cleanup subscription on unmount return () => { docPresence.off('receive', handlePresenceReceive); }; }, [docPresence, openTab]); };