From ae552a9fbdca8dee7f10687f74dd975d8b2404b0 Mon Sep 17 00:00:00 2001 From: Jan-Henrik Bruhn Date: Tue, 20 Jan 2026 15:10:12 +0100 Subject: [PATCH] Fix infinite loop in TUIO connection and remove conflicting keyboard shortcut - Use ref for callbacks in useTuioConnection to prevent infinite re-renders when entering presentation mode - Remove disabled deselect-all shortcut that conflicted with exit-presentation-mode (both using Escape) Co-Authored-By: Claude Sonnet 4.5 --- src/hooks/useGlobalShortcuts.ts | 13 ------------- src/hooks/useTuioConnection.ts | 14 ++++++++++---- 2 files changed, 10 insertions(+), 17 deletions(-) diff --git a/src/hooks/useGlobalShortcuts.ts b/src/hooks/useGlobalShortcuts.ts index 3790a2c..ce03f5e 100644 --- a/src/hooks/useGlobalShortcuts.ts +++ b/src/hooks/useGlobalShortcuts.ts @@ -143,19 +143,6 @@ export function useGlobalShortcuts(options: UseGlobalShortcutsOptions = {}) { priority: -1, // Lower priority than Ctrl+Y }, - // Selection - { - id: "deselect-all", - description: "Deselect All", - key: "Escape", - handler: () => { - // This will be handled by GraphEditor - // Just documenting it here - }, - category: "Selection", - enabled: false, // React Flow handles this internally - }, - // View { id: "fit-view", diff --git a/src/hooks/useTuioConnection.ts b/src/hooks/useTuioConnection.ts index 6ffdcea..bb92143 100644 --- a/src/hooks/useTuioConnection.ts +++ b/src/hooks/useTuioConnection.ts @@ -20,8 +20,14 @@ export function useTuioConnection( } ) { const clientRef = useRef(null); + const callbacksRef = useRef(callbacks); const { websocketUrl, protocolVersion } = useTuioStore(); + // Keep callbacks ref up to date + useEffect(() => { + callbacksRef.current = callbacks; + }, [callbacks]); + useEffect(() => { if (!shouldConnect) { // Disconnect if we should not be connected @@ -38,15 +44,15 @@ export function useTuioConnection( { onTangibleAdd: (hardwareId: string, info: TuioTangibleInfo) => { useTuioStore.getState().addActiveTangible(hardwareId, info); - callbacks?.onTangibleAdd?.(hardwareId, info); + callbacksRef.current?.onTangibleAdd?.(hardwareId, info); }, onTangibleUpdate: (hardwareId: string, info: TuioTangibleInfo) => { useTuioStore.getState().updateActiveTangible(hardwareId, info); - callbacks?.onTangibleUpdate?.(hardwareId, info); + callbacksRef.current?.onTangibleUpdate?.(hardwareId, info); }, onTangibleRemove: (hardwareId: string) => { useTuioStore.getState().removeActiveTangible(hardwareId); - callbacks?.onTangibleRemove?.(hardwareId); + callbacksRef.current?.onTangibleRemove?.(hardwareId); }, onConnectionChange: (connected, error) => { useTuioStore.getState().setConnectionState(connected, error); @@ -72,5 +78,5 @@ export function useTuioConnection( useTuioStore.getState().clearActiveTangibles(); } }; - }, [shouldConnect, websocketUrl, protocolVersion, callbacks]); + }, [shouldConnect, websocketUrl, protocolVersion]); }