import {ReactElement, useCallback, useRef, useState} from "react"; import {ProgressBar, Stack} from "react-bootstrap"; import {useAnimationFrame} from "./AnimationHook"; import {isDefined} from "../types/type_check"; import "./TurnTimer.css"; import formatDuration from "format-duration"; export interface TurnTimerArgs { readonly title?: string readonly startTime?: number readonly endTime?: number readonly displayedTime?: number readonly resolutionMs?: number } const DEFAULT_RESOLUTION_MS = 100; export function TurnTimer({title, startTime, endTime, displayedTime, resolutionMs = DEFAULT_RESOLUTION_MS}: TurnTimerArgs): ReactElement { const [currentTime, setCurrentTime] = useState(() => displayedTime ?? Date.now()) const accumulatedTime = useRef(0) const animationCallback = useCallback(isDefined(displayedTime) ? () => null : (delta: number) => { accumulatedTime.current += delta if (accumulatedTime.current > resolutionMs) { accumulatedTime.current %= resolutionMs setCurrentTime(Date.now()) } }, [displayedTime, setCurrentTime, accumulatedTime]) useAnimationFrame(animationCallback) if (isDefined(displayedTime) && displayedTime !== currentTime) { setCurrentTime(displayedTime) accumulatedTime.current = resolutionMs } let totalTime: number|null = null let timeRemaining: number|null = null let timeElapsed: number|null = null if (isDefined(startTime)) { if (isDefined(endTime)) { totalTime = endTime - startTime timeRemaining = endTime - currentTime } else { timeElapsed = currentTime - startTime } } else if (isDefined(endTime)) { timeRemaining = endTime - currentTime } return

{title}

{(timeRemaining !== null || timeElapsed !== null) &&
{formatDuration(timeRemaining ?? timeElapsed ?? 0)}
} {timeRemaining !== null && totalTime !== null && }
}