From db070f47ee6253ed5235bf314f52620c09046233 Mon Sep 17 00:00:00 2001 From: Jeff Emmett Date: Fri, 19 Dec 2025 15:08:55 -0500 Subject: [PATCH] fix: resolve Three.js Text component error and modal close issues MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Downgrade three.js from 0.182 to 0.168 to fix customDepthMaterial getter-only property breaking change (drei issue #2403) - Add stable useCallback for modal close handler to prevent reference instability - Improve ESC key handler with ref pattern and capture phase to ensure reliable modal closing 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- package-lock.json | 8 ++++---- package.json | 2 +- .../networking/NetworkGraphMinimap.tsx | 7 ++++++- src/components/networking/UserSearchModal.tsx | 19 ++++++++++++------- 4 files changed, 23 insertions(+), 13 deletions(-) diff --git a/package-lock.json b/package-lock.json index bcec892..91c8e57 100644 --- a/package-lock.json +++ b/package-lock.json @@ -60,7 +60,7 @@ "react-router-dom": "^7.0.2", "recoil": "^0.7.7", "sharp": "^0.33.5", - "three": "^0.182.0", + "three": "^0.168.0", "tldraw": "^3.15.4", "use-whisper": "^0.0.1", "webcola": "^3.4.0" @@ -20865,9 +20865,9 @@ } }, "node_modules/three": { - "version": "0.182.0", - "resolved": "https://registry.npmjs.org/three/-/three-0.182.0.tgz", - "integrity": "sha512-GbHabT+Irv+ihI1/f5kIIsZ+Ef9Sl5A1Y7imvS5RQjWgtTPfPnZ43JmlYI7NtCRDK9zir20lQpfg8/9Yd02OvQ==", + "version": "0.168.0", + "resolved": "https://registry.npmjs.org/three/-/three-0.168.0.tgz", + "integrity": "sha512-6m6jXtDwMJEK/GGMbAOTSAmxNdzKvvBzgd7q8bE/7Tr6m7PaBh5kKLrN7faWtlglXbzj7sVba48Idwx+NRsZXw==", "license": "MIT" }, "node_modules/three-mesh-bvh": { diff --git a/package.json b/package.json index ec66afd..7d9a218 100644 --- a/package.json +++ b/package.json @@ -86,7 +86,7 @@ "react-router-dom": "^7.0.2", "recoil": "^0.7.7", "sharp": "^0.33.5", - "three": "^0.182.0", + "three": "^0.168.0", "tldraw": "^3.15.4", "use-whisper": "^0.0.1", "webcola": "^3.4.0" diff --git a/src/components/networking/NetworkGraphMinimap.tsx b/src/components/networking/NetworkGraphMinimap.tsx index 8404874..8c2afbb 100644 --- a/src/components/networking/NetworkGraphMinimap.tsx +++ b/src/components/networking/NetworkGraphMinimap.tsx @@ -249,6 +249,11 @@ export function NetworkGraphMinimap({ const [selectedNode, setSelectedNode] = useState<{ node: GraphNode; x: number; y: number } | null>(null); const [isConnecting, setIsConnecting] = useState(false); + // Stable callback for closing search modal (prevents ESC handler issues) + const handleCloseSearch = useCallback(() => { + setIsSearchOpen(false); + }, []); + // Three-state display mode: minimized, normal, maximized const [displayMode, setDisplayMode] = useState(isCollapsed ? 'minimized' : 'normal'); @@ -963,7 +968,7 @@ export function NetworkGraphMinimap({ setIsSearchOpen(false)} + onClose={handleCloseSearch} onConnect={onConnect} onDisconnect={onDisconnect ? (userId) => { // Find the connection ID for this user diff --git a/src/components/networking/UserSearchModal.tsx b/src/components/networking/UserSearchModal.tsx index 71ae50a..0552fa4 100644 --- a/src/components/networking/UserSearchModal.tsx +++ b/src/components/networking/UserSearchModal.tsx @@ -256,19 +256,24 @@ export function UserSearchModal({ } }, [onConnect, onDisconnect]); - // Handle escape key + // Handle escape key - use a ref to avoid stale closure issues + const onCloseRef = useRef(onClose); + onCloseRef.current = onClose; + useEffect(() => { + if (!isOpen) return; + const handleKeyDown = (e: KeyboardEvent) => { if (e.key === 'Escape') { - onClose(); + e.preventDefault(); + e.stopPropagation(); + onCloseRef.current(); } }; - if (isOpen) { - window.addEventListener('keydown', handleKeyDown); - return () => window.removeEventListener('keydown', handleKeyDown); - } - }, [isOpen, onClose]); + window.addEventListener('keydown', handleKeyDown, true); // Use capture phase + return () => window.removeEventListener('keydown', handleKeyDown, true); + }, [isOpen]); if (!isOpen) return null;