import React, { useCallback, useEffect, useState } from 'react'; import DateTimePickerModal from 'react-native-modal-datetime-picker'; import styled from 'styled-components/native'; import { useDispatch } from 'react-redux'; import { useTypedSelector } from '@/store'; import TimerIcon from '@/assets/icons/timer.svg'; import { setTimerDate } from '@/store/sleep-timer'; import ticksToDuration from '@/utility/ticksToDuration'; import useDefaultStyles from '@/components/Colors'; import { TouchableOpacity } from 'react-native-gesture-handler'; import { t } from '@/localisation'; const Container = styled.View` align-self: flex-start; align-items: flex-start; padding: 8px; margin-left: -8px; flex: 0 1 auto; border-radius: 8px; `; const View = styled.View` display: flex; flex-direction: row; align-items: center; gap: 8px; `; const Label = styled.Text` font-size: 13px; `; export default function Timer() { // Keep an incrementing counter to force the component to update when the // interval is active. const [, setCounter] = useState(0); // Show the picker or not const [showPicker, setShowPicker] = useState(false); // Retrieve Redux state and methods const date = useTypedSelector(state => state.sleepTimer.date); const dispatch = useDispatch(); // Retrieve styles const defaultStyles = useDefaultStyles(); // Deal with a date being selected const handleConfirm = useCallback((date: Date) => { // GUARD: If the date is in the past, we need to add 24 hours to it to // ensure it is in the future if (date.getTime() < new Date().getTime()) { date = new Date(date.getTime() + 24 * 60 * 60 * 1_000); } // Only accept minutes and hours date.setSeconds(0); // Set the date and close the picker dispatch(setTimerDate(date)); setShowPicker(false); }, [dispatch]); // Close the picker when it is canceled const handleCancelDatePicker = useCallback(() => { setShowPicker(false); dispatch(setTimerDate(null)); }, [dispatch]); // Show it when it should be opened const showDatePicker = useCallback(() => { setShowPicker(!showPicker); }, [showPicker]); // Periodically trigger updates useEffect(() => { // GUARD: If there's no date, there's no need to update if (!date) { return; } // Set an interval that periodically increments the counter when a date // is active const interval = setInterval(() => { setCounter((i) => i + 1); }, 1_000); // Clean up the interval on re-renders return () => clearInterval(interval); }, [date]); // Calculate the remaining time by subtracting it from the current date const remainingTime = date && date - new Date().getTime(); return ( ); }