/** * This file is part of the SplendidBear Websites' projects. * * Copyright (c) 2026 @ www.splendidbear.org * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ import React, { useEffect, useRef, useState } from 'react'; import { useGame } from '@mine-contexts'; import BonusBox from './BonusBox'; import BonusStatsDialog from './BonusStatsDialog'; const renderAvatar = player => { if (!player.registered) return null; return (
{player.avatar ? {player.name} : {player.name.slice(0, 2).toUpperCase()} }
); }; const GameTimer = () => { const { overlay, connectionLost, endRef, activePlayer, red, blue } = useGame(); const [redTime, setRedTime] = useState(0); const [blueTime, setBlueTime] = useState(0); const [isRunning, setIsRunning] = useState(false); const [bonusDialogOpen, setBonusDialogOpen] = useState(false); const timerIntervalRef = useRef(null); const gameStartedRef = useRef(false); const redStartTimeRef = useRef(null); const blueStartTimeRef = useRef(null); const lastActivePlayerRef = useRef(null); const pausedRedTimeRef = useRef(0); const pausedBlueTimeRef = useRef(0); useEffect(() => { if (!overlay && !gameStartedRef.current) { gameStartedRef.current = true; setIsRunning(true); setRedTime(0); setBlueTime(0); redStartTimeRef.current = Date.now(); blueStartTimeRef.current = Date.now(); pausedRedTimeRef.current = 0; pausedBlueTimeRef.current = 0; lastActivePlayerRef.current = activePlayer; } }, [activePlayer, overlay]); useEffect(() => { if (endRef.current) setIsRunning(false); }, [endRef]); useEffect(() => { if (connectionLost) setIsRunning(false); }, [connectionLost]); useEffect(() => { if (!isRunning) return; if (lastActivePlayerRef.current !== activePlayer) { const startRef = lastActivePlayerRef.current ? blueStartTimeRef.current : redStartTimeRef.current; if (startRef) { const elapsed = Math.floor((Date.now() - startRef) / 1000); if (lastActivePlayerRef.current) { pausedBlueTimeRef.current += elapsed; } else { pausedRedTimeRef.current += elapsed; } } if (activePlayer) { blueStartTimeRef.current = Date.now(); } else { redStartTimeRef.current = Date.now(); } lastActivePlayerRef.current = activePlayer; } }, [activePlayer, isRunning]); useEffect(() => { if (!isRunning) { if (timerIntervalRef.current) { clearInterval(timerIntervalRef.current); } return; } timerIntervalRef.current = setInterval(() => { let currentRedTime = pausedRedTimeRef.current; let currentBlueTime = pausedBlueTimeRef.current; if (!activePlayer && redStartTimeRef.current) { currentRedTime += Math.floor((Date.now() - redStartTimeRef.current) / 1000); } else if (activePlayer && blueStartTimeRef.current) { currentBlueTime += Math.floor((Date.now() - blueStartTimeRef.current) / 1000); } setRedTime(currentRedTime); setBlueTime(currentBlueTime); }, 100); return () => { if (timerIntervalRef.current) { clearInterval(timerIntervalRef.current); } }; }, [isRunning, activePlayer]); useEffect(() => { const handleFocus = () => { if (isRunning) { let currentRedTime = pausedRedTimeRef.current; let currentBlueTime = pausedBlueTimeRef.current; if (!activePlayer && redStartTimeRef.current) { currentRedTime += Math.floor((Date.now() - redStartTimeRef.current) / 1000); } else if (activePlayer && blueStartTimeRef.current) { currentBlueTime += Math.floor((Date.now() - blueStartTimeRef.current) / 1000); } setRedTime(currentRedTime); setBlueTime(currentBlueTime); } }; window.addEventListener('focus', handleFocus); return () => window.removeEventListener('focus', handleFocus); }, [isRunning, activePlayer]); useEffect(() => () => { if (timerIntervalRef.current) clearInterval(timerIntervalRef.current); }, []); const formatTime = seconds => { const mins = Math.floor(seconds / 60); const secs = seconds % 60; return `${String(mins).padStart(2, '0')}:${String(secs).padStart(2, '0')}`; }; const openBonusDialog = () => setBonusDialogOpen(true); const closeBonusDialog = () => setBonusDialogOpen(false); return (
{renderAvatar(red)} {formatTime(redTime)}
{renderAvatar(blue)} {formatTime(blueTime)}
); }; export default GameTimer;