diff options
| author | nsfisis <nsfisis@gmail.com> | 2025-03-04 22:55:01 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2025-03-08 10:12:44 +0900 |
| commit | 1e6df136d8202c8adf65948527f4c3e7583b338c (patch) | |
| tree | 7c82476f6bbbc71d72ab7e71e39559eca197fd95 /frontend/app/components/GolfWatchApp.tsx | |
| parent | 54316868c3bec1ff9b04643dfe6c13cf56bf3246 (diff) | |
| download | iosdc-japan-2025-albatross-1e6df136d8202c8adf65948527f4c3e7583b338c.tar.gz iosdc-japan-2025-albatross-1e6df136d8202c8adf65948527f4c3e7583b338c.tar.zst iosdc-japan-2025-albatross-1e6df136d8202c8adf65948527f4c3e7583b338c.zip | |
websocket to polling
Diffstat (limited to 'frontend/app/components/GolfWatchApp.tsx')
| -rw-r--r-- | frontend/app/components/GolfWatchApp.tsx | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/frontend/app/components/GolfWatchApp.tsx b/frontend/app/components/GolfWatchApp.tsx new file mode 100644 index 0000000..fe71932 --- /dev/null +++ b/frontend/app/components/GolfWatchApp.tsx @@ -0,0 +1,127 @@ +import { useAtomValue, useSetAtom } from "jotai"; +import { useContext, useEffect, useState } from "react"; +import { useTimer } from "react-use-precision-timer"; +import { + ApiAuthTokenContext, + apiGetGame, + apiGetGameWatchLatestStates, + apiGetGameWatchRanking, +} from "../api/client"; +import type { components } from "../api/schema"; +import { + gameStateKindAtom, + setCurrentTimestampAtom, + setGameStartedAtAtom, + setLatestGameStatesAtom, + setRankingAtom, +} from "../states/watch"; +import GolfWatchAppGaming from "./GolfWatchApps/GolfWatchAppGaming"; +import GolfWatchAppStarting from "./GolfWatchApps/GolfWatchAppStarting"; +import GolfWatchAppWaiting from "./GolfWatchApps/GolfWatchAppWaiting"; + +type Game = components["schemas"]["Game"]; + +export type Props = { + game: Game; +}; + +export default function GolfWatchApp({ game }: Props) { + const apiAuthToken = useContext(ApiAuthTokenContext); + + const gameStateKind = useAtomValue(gameStateKindAtom); + const setGameStartedAt = useSetAtom(setGameStartedAtAtom); + const setCurrentTimestamp = useSetAtom(setCurrentTimestampAtom); + const setLatestGameStates = useSetAtom(setLatestGameStatesAtom); + const setRanking = useSetAtom(setRankingAtom); + + useTimer({ delay: 1000, startImmediately: true }, setCurrentTimestamp); + + const playerA = game.main_players[0]!; + const playerB = game.main_players[1]!; + + const playerProfileA = { + id: playerA.user_id, + displayName: playerA.display_name, + iconPath: playerA.icon_path ?? null, + }; + const playerProfileB = { + id: playerB.user_id, + displayName: playerB.display_name, + iconPath: playerB.icon_path ?? null, + }; + + const [isDataPolling, setIsDataPolling] = useState(false); + + useEffect(() => { + if (isDataPolling) { + return; + } + const timerId = setInterval(async () => { + if (isDataPolling) { + return; + } + setIsDataPolling(true); + + try { + if (gameStateKind === "waiting") { + const { game: g } = await apiGetGame(apiAuthToken, game.game_id); + if (g.started_at != null) { + setGameStartedAt(g.started_at); + } + } else if (gameStateKind === "gaming") { + const { states } = await apiGetGameWatchLatestStates( + apiAuthToken, + game.game_id, + ); + setLatestGameStates(states); + const { ranking } = await apiGetGameWatchRanking( + apiAuthToken, + game.game_id, + ); + setRanking(ranking); + } + } catch (error) { + console.error(error); + } finally { + setIsDataPolling(false); + } + }, 1000); + + return () => { + clearInterval(timerId); + }; + }, [ + isDataPolling, + apiAuthToken, + game.game_id, + gameStateKind, + setGameStartedAt, + setLatestGameStates, + setRanking, + ]); + + if (gameStateKind === "waiting") { + return ( + <GolfWatchAppWaiting + gameDisplayName={game.display_name} + playerProfileA={playerProfileA} + playerProfileB={playerProfileB} + /> + ); + } else if (gameStateKind === "starting") { + return <GolfWatchAppStarting gameDisplayName={game.display_name} />; + } else if (gameStateKind === "gaming" || gameStateKind === "finished") { + return ( + <GolfWatchAppGaming + gameDisplayName={game.display_name} + playerProfileA={playerProfileA} + playerProfileB={playerProfileB} + problemTitle={game.problem.title} + problemDescription={game.problem.description} + gameResult={null /* TODO */} + /> + ); + } else { + return null; + } +} |
