import { useEffect, useState } from 'react'; import { useRoute } from '@react-navigation/native'; import { View } from '@/components/shared/Themed'; import styled from '@emotion/native'; import TimerContent from '@/components/useCases/timer/view/TimerContent'; import FinishContent from '@/components/useCases/timer/view/FinishContent'; import { TimerBgColor } from '@/components/useCases/timer/business/type'; import { Audio } from 'expo-av'; import { Sound } from 'expo-av/build/Audio'; interface TimerProps { reps: number; restTime: number; workTime: number; } export default function Timer() { const route = useRoute(); const { reps, restTime, workTime } = route.params as TimerProps; const [currentRep, setCurrentRep] = useState(0); const [timeLeft, setTimeLeft] = useState(0); const [isWorkPhase, setIsWorkPhase] = useState(true); const [isRunning, setIsRunning] = useState(false); const [isFinish, setIsFinish] = useState(false); const [sound, setSound] = useState(); useEffect(() => { handleStart(); }, []); useEffect(() => { let timer: NodeJS.Timeout; if (isRunning && timeLeft > 0) { timer = setTimeout(() => { setTimeLeft(timeLeft - 1); }, 1000); } else if (isRunning && timeLeft === 0) { if (currentRep < reps) { if (isWorkPhase) { // If the work phase is over, move on to the rest phase playSound() setIsWorkPhase(false); setTimeLeft(restTime); } else { // If the rest phase is complete, move on to the next work phase playSound() setIsWorkPhase(true); setTimeLeft(workTime); setCurrentRep(currentRep + 1); } } else { // Done setIsRunning(false); setIsFinish(true); } } return () => clearTimeout(timer); }, [isRunning, timeLeft, currentRep, isWorkPhase, reps, workTime, restTime]); const handleStart = () => { setCurrentRep(1); setIsWorkPhase(true); setTimeLeft(workTime); setIsRunning(true); setIsFinish(false); }; async function configureAudio() { await Audio.setAudioModeAsync({ allowsRecordingIOS: false, staysActiveInBackground: false, playsInSilentModeIOS: true, shouldDuckAndroid: true, playThroughEarpieceAndroid: false, }); } useEffect(() => { configureAudio(); }, []); async function playSound() { const { sound } = await Audio.Sound.createAsync(require('../assets/audios/boxingBell.mp3')); setSound(sound); await sound.playAsync(); } useEffect(() => { return sound ? () => { sound.unloadAsync(); } : undefined; }, [sound]); const handleContine = () => { setIsRunning(true); }; const handleStop = () => { setIsRunning(false); }; const renderBgColor: () => TimerBgColor = () => { if (isFinish) return 'black'; if (isWorkPhase) return 'red'; return 'green'; } return ( {isFinish && ( )} {!isFinish && ( )} ); } const Container = styled(View)<{ bgColor: TimerBgColor }>(({ theme, bgColor }) => ({ flex: 1, alignItems: 'center', justifyContent: 'center', backgroundColor: theme.colors[bgColor] }));