更新圖示與部署更新機制並整理 README
This commit is contained in:
55
src/App.tsx
55
src/App.tsx
@@ -1,4 +1,4 @@
|
||||
import { useEffect, useMemo, useState } from 'react'
|
||||
import { useEffect, useMemo, useRef, useState } from 'react'
|
||||
import { NavLink, Route, Routes, useLocation } from 'react-router-dom'
|
||||
import './App.css'
|
||||
import { loadMatchResults, saveMatchHistory } from './lib/api'
|
||||
@@ -80,6 +80,7 @@ const STREAK_TITLES: Record<number, string> = {
|
||||
8: '成為傳說',
|
||||
}
|
||||
const PWA_UPDATE_EVENT = 'badminton-scoreboard:pwa-update-ready'
|
||||
const APP_VERSION_POLL_MS = 30000
|
||||
|
||||
function App() {
|
||||
const location = useLocation()
|
||||
@@ -117,6 +118,7 @@ function App() {
|
||||
const [streakAnnouncement, setStreakAnnouncement] = useState<StreakAnnouncement | null>(null)
|
||||
const [victoryAnnouncement, setVictoryAnnouncement] = useState<VictoryAnnouncement | null>(null)
|
||||
const [pwaUpdateReady, setPwaUpdateReady] = useState(false)
|
||||
const currentAppVersionRef = useRef<string | null>(null)
|
||||
|
||||
const parsedAreaA = useMemo(() => parseRoster(areaAInput), [areaAInput])
|
||||
const parsedAreaB = useMemo(() => parseRoster(areaBInput), [areaBInput])
|
||||
@@ -188,6 +190,57 @@ function App() {
|
||||
}
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
let active = true
|
||||
|
||||
const checkAppVersion = async () => {
|
||||
try {
|
||||
const response = await fetch('/api/version', {
|
||||
cache: 'no-store',
|
||||
headers: {
|
||||
'cache-control': 'no-cache',
|
||||
},
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
return
|
||||
}
|
||||
|
||||
const payload = (await response.json()) as {
|
||||
ok?: boolean
|
||||
version?: string
|
||||
}
|
||||
const nextVersion = payload.version?.trim()
|
||||
|
||||
if (!active || !nextVersion) {
|
||||
return
|
||||
}
|
||||
|
||||
if (!currentAppVersionRef.current) {
|
||||
currentAppVersionRef.current = nextVersion
|
||||
return
|
||||
}
|
||||
|
||||
if (currentAppVersionRef.current !== nextVersion) {
|
||||
currentAppVersionRef.current = nextVersion
|
||||
setPwaUpdateReady(true)
|
||||
}
|
||||
} catch {
|
||||
// Ignore transient version-check failures and retry on next poll.
|
||||
}
|
||||
}
|
||||
|
||||
void checkAppVersion()
|
||||
const timer = window.setInterval(() => {
|
||||
void checkAppVersion()
|
||||
}, APP_VERSION_POLL_MS)
|
||||
|
||||
return () => {
|
||||
active = false
|
||||
window.clearInterval(timer)
|
||||
}
|
||||
}, [])
|
||||
|
||||
const resetScoring = (nextState: ScoreState = initialScoreState) => {
|
||||
setScoreState(nextState)
|
||||
setScoreHistory([])
|
||||
|
||||
Reference in New Issue
Block a user