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 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
bcb323e30f
commit
98e6baccc1
@@ -26,6 +26,7 @@ let scene: FightSceneController | null = null
|
|||||||
const sceneReady = ref(false)
|
const sceneReady = ref(false)
|
||||||
let cleanupTimerHandle: ReturnType<typeof setTimeout> | null = null
|
let cleanupTimerHandle: ReturnType<typeof setTimeout> | null = null
|
||||||
let destroyed = false
|
let destroyed = false
|
||||||
|
const contextLost = ref(false)
|
||||||
|
|
||||||
const isReplaying = ref(false)
|
const isReplaying = ref(false)
|
||||||
const ttsProgress = ref(-1)
|
const ttsProgress = ref(-1)
|
||||||
@@ -195,6 +196,18 @@ async function initScene() {
|
|||||||
container.prepend(newCanvas)
|
container.prepend(newCanvas)
|
||||||
}
|
}
|
||||||
canvasRef.value = 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
|
// Wrap scene creation in try/catch + timeout so a mobile sprite loading failure
|
||||||
// or hang never blocks the overlay/voice/round flow
|
// or hang never blocks the overlay/voice/round flow
|
||||||
@@ -720,6 +733,13 @@ async function _doReplay() {
|
|||||||
<!-- Canvas + floating overlays -->
|
<!-- Canvas + floating overlays -->
|
||||||
<div ref="canvasContainer" class="flex-1 relative min-h-0" :class="{ 'glitch-container': glitching }">
|
<div ref="canvasContainer" class="flex-1 relative min-h-0" :class="{ 'glitch-container': glitching }">
|
||||||
<canvas ref="canvasRef" class="w-full h-full block" />
|
<canvas ref="canvasRef" class="w-full h-full block" />
|
||||||
|
<!-- Context lost fallback -->
|
||||||
|
<div v-if="contextLost" class="absolute inset-0 z-40 bg-black/80 flex items-center justify-center">
|
||||||
|
<div class="text-center">
|
||||||
|
<p class="font-pixel text-xs text-ko mb-2">CANVAS CONTEXT LOST</p>
|
||||||
|
<p class="font-mono text-[10px] text-text-muted">Recovering...</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<!-- TTS model download progress -->
|
<!-- TTS model download progress -->
|
||||||
<div v-if="ttsProgress >= 0 && ttsProgress < 100" class="absolute bottom-1 left-2 right-2 z-30">
|
<div v-if="ttsProgress >= 0 && ttsProgress < 100" class="absolute bottom-1 left-2 right-2 z-30">
|
||||||
<div class="bg-black/60 rounded px-2 py-1 flex items-center gap-2">
|
<div class="bg-black/60 rounded px-2 py-1 flex items-center gap-2">
|
||||||
|
|||||||
Reference in New Issue
Block a user