From 713f09923d65b72906dcf9fb688a280ae8f3bbed Mon Sep 17 00:00:00 2001 From: Justin Jones Date: Sat, 21 Mar 2026 17:24:46 -0500 Subject: [PATCH 1/2] fix(dashboard): complete stale socket guards and cross-platform keyboard shortcut - Add `ws !== socket` guard to onmessage and onerror handlers in websocket.ts to prevent stale socket instances from mutating shared state during reconnection races - Add CONNECTING state check to prevent duplicate connection attempts - Normalize keyboard shortcut key check with toLowerCase() for cross-platform robustness (Caps Lock edge case) Addresses CodeRabbit review comments from PR #76. Co-Authored-By: Claude Opus 4.6 --- dashboard/src/lib/components/Shell.svelte | 2 +- dashboard/src/lib/stores/websocket.ts | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/dashboard/src/lib/components/Shell.svelte b/dashboard/src/lib/components/Shell.svelte index 9d4688c..ea288e8 100644 --- a/dashboard/src/lib/components/Shell.svelte +++ b/dashboard/src/lib/components/Shell.svelte @@ -9,7 +9,7 @@ let paletteOpen = $state(false); function handleKeydown(e: KeyboardEvent) { - if (e.key === 'k' && (e.metaKey || e.ctrlKey)) { + if (e.key.toLowerCase() === 'k' && (e.metaKey || e.ctrlKey)) { e.preventDefault(); paletteOpen = !paletteOpen; } diff --git a/dashboard/src/lib/stores/websocket.ts b/dashboard/src/lib/stores/websocket.ts index 1470290..0c2fd1f 100644 --- a/dashboard/src/lib/stores/websocket.ts +++ b/dashboard/src/lib/stores/websocket.ts @@ -34,7 +34,7 @@ function getWSUrl(): string { } function connect() { - if (ws?.readyState === WebSocket.OPEN) return; + if (ws && (ws.readyState === WebSocket.OPEN || ws.readyState === WebSocket.CONNECTING)) return; let socket: WebSocket; try { @@ -59,10 +59,12 @@ function connect() { }; socket.onerror = () => { + if (ws !== socket) return; socket.close(); }; socket.onmessage = (event) => { + if (ws !== socket) return; try { const data: WSEvent = JSON.parse(event.data); lastEvent.set(data); From 219142e0f65614401db2261a56ef4c4d07173e36 Mon Sep 17 00:00:00 2001 From: Justin Jones Date: Sat, 21 Mar 2026 17:30:45 -0500 Subject: [PATCH 2/2] =?UTF-8?q?fix(dashboard):=20address=20balrog=20findin?= =?UTF-8?q?gs=20=E2=80=94=20quest=20navigation=20reset=20and=20onerror=20c?= =?UTF-8?q?leanup?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Reset dataLoaded/loadFailed state when questName changes to prevent stale data when navigating between quest detail pages - Revert onerror stale guard — errored sockets should always be closed for cleanup; the onclose handler already guards shared state Co-Authored-By: Claude Opus 4.6 --- dashboard/src/lib/stores/websocket.ts | 1 - dashboard/src/routes/quest/[id]/+page.svelte | 9 +++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/dashboard/src/lib/stores/websocket.ts b/dashboard/src/lib/stores/websocket.ts index 0c2fd1f..04ab7c6 100644 --- a/dashboard/src/lib/stores/websocket.ts +++ b/dashboard/src/lib/stores/websocket.ts @@ -59,7 +59,6 @@ function connect() { }; socket.onerror = () => { - if (ws !== socket) return; socket.close(); }; diff --git a/dashboard/src/routes/quest/[id]/+page.svelte b/dashboard/src/routes/quest/[id]/+page.svelte index a942fbf..97dd21e 100644 --- a/dashboard/src/routes/quest/[id]/+page.svelte +++ b/dashboard/src/routes/quest/[id]/+page.svelte @@ -26,6 +26,15 @@ let loading = $state(false); + // Reset data when navigating between quests (component is reused) + $effect(() => { + questName; + dataLoaded = false; + loadFailed = false; + errandList = null; + tomeData = null; + }); + $effect(() => { if (quest && !dataLoaded && !loadFailed && !loading) { loading = true;