From 98e6baccc150209214e2331850bd2aaebcbcbb33 Mon Sep 17 00:00:00 2001 From: Dorian Date: Mon, 9 Mar 2026 09:18:33 +0000 Subject: [PATCH] fix: handle canvas context loss with recovery and fallback overlay Listen for webglcontextlost/restored events on the fight canvas. Show "recovering" overlay on context loss, re-init scene on restore. Co-Authored-By: Claude Opus 4.6 --- frontend/src/components/FightViewer.vue | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/frontend/src/components/FightViewer.vue b/frontend/src/components/FightViewer.vue index da62e76..37ccc3d 100644 --- a/frontend/src/components/FightViewer.vue +++ b/frontend/src/components/FightViewer.vue @@ -26,6 +26,7 @@ let scene: FightSceneController | null = null const sceneReady = ref(false) let cleanupTimerHandle: ReturnType | null = null let destroyed = false +const contextLost = ref(false) const isReplaying = ref(false) const ttsProgress = ref(-1) @@ -195,6 +196,18 @@ async function initScene() { container.prepend(newCanvas) } canvasRef.value = newCanvas + contextLost.value = false + + // Handle WebGL/Canvas context loss (GPU pressure, tab backgrounding, etc.) + newCanvas.addEventListener('webglcontextlost', (e) => { + e.preventDefault() // Allow context restoration + contextLost.value = true + sceneReady.value = false + }) + newCanvas.addEventListener('webglcontextrestored', () => { + contextLost.value = false + initScene() // Re-create the scene with fresh context + }) // Wrap scene creation in try/catch + timeout so a mobile sprite loading failure // or hang never blocks the overlay/voice/round flow @@ -720,6 +733,13 @@ async function _doReplay() {
+ +
+
+

CANVAS CONTEXT LOST

+

Recovering...

+
+