fix: add back-button guard and tab-switch re-sync to HumanFightPage

- Warn before navigating away from active fight (beforeRouteLeave)
- Re-poll challenge state when tab becomes visible (visibilitychange)
- Prevents silent forfeit on back-button and stale timer after tab switch

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Dorian
2026-03-09 08:41:26 +00:00
co-authored by Claude Opus 4.6
parent 0f95cbf881
commit b00f52c1e6
+20 -1
View File
@@ -1,6 +1,6 @@
<script setup lang="ts">
import { ref, computed, onMounted, onUnmounted, nextTick } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { useRoute, useRouter, onBeforeRouteLeave } from 'vue-router'
import { useNostr } from '../composables/useNostr'
import FightViewer from '../components/FightViewer.vue'
import type { FightData } from '../game/fight/types'
@@ -74,6 +74,16 @@ const hasChoices = computed(() =>
currentChallenge.value?.choices && currentChallenge.value.choices.length > 0
)
// Back-button guard — warn if fight is active
onBeforeRouteLeave((_to, _from, next) => {
const isActive = phase.value === 'challenge' || phase.value === 'submitted' || phase.value === 'timeout' || phase.value === 'between' || phase.value === 'waiting'
if (isActive && !window.confirm('Fight in progress! Leave and forfeit?')) {
next(false)
return
}
next()
})
onMounted(() => {
if (!myBot.value) {
router.push('/join')
@@ -81,6 +91,7 @@ onMounted(() => {
}
startPolling()
window.addEventListener('keydown', handleKeyboard)
document.addEventListener('visibilitychange', handleVisibilityChange)
})
onUnmounted(() => {
@@ -88,8 +99,16 @@ onUnmounted(() => {
stopTimer()
if (feedbackTimer.value) clearTimeout(feedbackTimer.value)
window.removeEventListener('keydown', handleKeyboard)
document.removeEventListener('visibilitychange', handleVisibilityChange)
})
// Tab switching — re-poll and re-sync timer when tab becomes visible
function handleVisibilityChange() {
if (document.visibilityState === 'visible' && (phase.value === 'challenge' || phase.value === 'waiting' || phase.value === 'between')) {
pollForChallenge()
}
}
// BUG-5: Keyboard shortcuts for MC choices (A-D or 1-4)
function handleKeyboard(e: KeyboardEvent) {
if (phase.value !== 'challenge' || !currentChallenge.value?.choices?.length) return