import { useEffect, useState } from "react"; import { useRoute, useNavigation } 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 { activateKeepAwakeAsync, deactivateKeepAwake } from "expo-keep-awake"; import { loadUserSettings } from "@/components/shared/business/AsyncStorage"; import BackgroundTimer from "react-native-background-timer"; import { useAudio } from "@/components/useCases/timer/business/useAudio"; import { useNotification } from "@/components/useCases/timer/business/useNotifications"; interface TimerProps { reps: number; restTime: number; workTime: number; } export default function Timer() { const navigation = useNavigation(); 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 [soundEnabled, setSoundEnabled] = useState(true); const { playSound } = useAudio( require("../assets/audios/boxingBell.mp3"), soundEnabled, ); const { updateNotification, cancelNotification } = useNotification( "123456789", { channelId: "timer-channel", channelName: "Timer Notification", channelDescription: "Notifications pour le timer", }, ); useEffect(() => { const init = async () => { try { const soundEnabledLocal = await loadUserSettings("soundEnabled"); setSoundEnabled(Boolean(Number(soundEnabledLocal))); handleStart(); await activateKeepAwakeAsync(); } catch (error) { throw new Error("Erreur lors du chargement des paramètres utilisateur"); } }; init(); }, []); // when the user exits the screen, desactivate the keepAwake useEffect(() => { const unsubscribe = navigation.addListener("beforeRemove", (_) => { deactivateKeepAwake(); }); return unsubscribe; }, [navigation]); useEffect(() => { let timerId: number | null = null; if (isRunning && timeLeft > 0) { timerId = BackgroundTimer.setInterval(() => { const newTime = timeLeft - 1; setTimeLeft(newTime); updateNotification( "Timer en cours", `Phase: ${isWorkPhase ? "Travail" : "Repos"}, Temps restant: ${newTime}s`, ); }, 1000); } else if (isRunning && timeLeft === 0) { nextRep(); } return () => { if (timerId !== null) { BackgroundTimer.clearInterval(timerId); } }; }, [isRunning, timeLeft]); const handleStart = () => { setCurrentRep(1); setIsWorkPhase(true); setTimeLeft(workTime); setIsRunning(true); setIsFinish(false); updateNotification( "Timer en cours", `Phase: ${isWorkPhase ? "Travail" : "Repos"}, Temps restant: ${timeLeft}s`, ); }; const handleReset = () => { setCurrentRep(1); setIsWorkPhase(true); setTimeLeft(workTime); setIsRunning(false); setIsFinish(false); cancelNotification(); }; const nextRep = () => { if (currentRep < reps) { if (isWorkPhase) { playSound(); setIsWorkPhase(false); setTimeLeft(restTime); } else { playSound(); setIsWorkPhase(true); setTimeLeft(workTime); setCurrentRep((prevRep) => prevRep + 1); } } else { playSound(); setIsFinish(true); setIsRunning(false); cancelNotification(); } }; const previousRep = () => { if (isWorkPhase) { if (currentRep > 1) { setIsWorkPhase(false); setTimeLeft(restTime); setCurrentRep((prevRep) => prevRep - 1); } } else { setIsWorkPhase(true); setTimeLeft(workTime); } }; 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.fixed[bgColor], }), );