更新圖示與部署更新機制並整理 README

This commit is contained in:
2026-04-16 20:35:31 +08:00
parent 36a39f0b8f
commit c097ceb9ad
11 changed files with 1134 additions and 1019 deletions

View File

@@ -948,6 +948,10 @@
border-radius: 999px;
padding: 14px 14px;
cursor: pointer;
user-select: none;
-webkit-user-select: none;
-webkit-touch-callout: none;
touch-action: manipulation;
font: inherit;
font-size: 1rem;
color: #4a2e1d;
@@ -964,6 +968,9 @@
.rail-pill-hold-wrap {
display: grid;
gap: 8px;
user-select: none;
-webkit-user-select: none;
-webkit-touch-callout: none;
}
.rail-pill-hold-wrap-active {

View File

@@ -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([])

File diff suppressed because it is too large Load Diff