import React, {useEffect, useState, memo, useCallback} from "react"; import {View, Text} from "react-native"; import Svg, {Circle} from "react-native-svg"; import Animated, { Easing, useSharedValue, withTiming, useAnimatedProps, } from "react-native-reanimated"; import createStyle from "./circular-timer.styles"; import CircularTimerProps from "./interfaces"; const AnimatedCircle = Animated.createAnimatedComponent(Circle); const CircularTimer = ({ duration, width = 60, height = 60, onFinish, viewStyle, textStyle, easingType = Easing.linear, progressColor = "red", circleColor = "white", animateFillProgress = false, isCountDown = true, intervalDuration = 1000, strokeWidth = 5, }: CircularTimerProps) => { const styles = createStyle({width, height}); const radius = width / 2; const circumference = 2 * Math.PI * radius; const progress = useSharedValue(1); const [timeLeft, setTimeLeft] = useState(isCountDown ? duration : 1); useEffect(() => { progress.value = withTiming(duration, { duration: duration * intervalDuration, easing: easingType ?? Easing.linear, }); const interval = setInterval(() => { setTimeLeft((prev) => { if (isCountDown ? prev === 1 : prev === duration) { clearInterval(interval); return isCountDown ? 0 : duration; } return isCountDown ? prev - 1 : prev + 1; }); }, intervalDuration); return () => clearInterval(interval); }, [duration]); useEffect(() => { if (isCountDown ? timeLeft === 0 : timeLeft === duration + 1) { onFinish(); } }, [timeLeft]); const formatTimeToMinutesSecondsMillisec = useCallback( (time: Number) => { const milliseconds = time * intervalDuration; const minutes = Math.floor(milliseconds / 60000); const seconds = Math.floor((milliseconds % 60000) / 1000); return `${minutes < 10 ? "0" : ""}${minutes}:${ seconds < 10 ? "0" : "" }${seconds}`; }, [timeLeft] ); const animatedProps = useAnimatedProps(() => { return { strokeDashoffset: animateFillProgress ? circumference - (progress.value / duration) * circumference : (progress.value / duration) * circumference, }; }); return ( {formatTimeToMinutesSecondsMillisec(timeLeft)} ); }; export default memo(CircularTimer);