import React, { useEffect, useState } from 'react'; import { StyleSheet, View, ViewStyle } from 'react-native'; import { useStyles } from '../../hooks'; import { ComponentStyleProp, LLComponentStyleFn } from '../../types'; export type LLWidgetInteractiveTimerStyles = { container: ViewStyle; innerContainer: ViewStyle; }; export type LLWidgetInteractiveTimerProps = ComponentStyleProp & { interactiveTimeout?: number | null; onInteractiveTimeout?: () => void; updateInterval?: number; }; const DEFAULT_INTERACTIVE_TIMER_UPDATE_INTERVAL = 500; export function LLWidgetInteractiveTimer({ interactiveTimeout, styles: stylesProp, onInteractiveTimeout, updateInterval = DEFAULT_INTERACTIVE_TIMER_UPDATE_INTERVAL, }: LLWidgetInteractiveTimerProps) { const [timer, setTimer] = useState(interactiveTimeout ? 0 : undefined); const interactiveTimerStyles = useStyles({ componentStylesFn: getWidgetInteractiveTimerStyles, stylesProp, }); useEffect(() => { if (interactiveTimeout === timer) { onInteractiveTimeout?.(); } }, [interactiveTimeout, timer, onInteractiveTimeout]); useEffect(() => { if (!interactiveTimeout) { return; } let timeoutId; function updateTimer(timeoutInterval) { timeoutId = setTimeout(() => { setTimer((oldTimer) => { const newTimer = Math.min( interactiveTimeout, (oldTimer ?? 0) + updateInterval ); if (newTimer === interactiveTimeout) { clearTimeout(timeoutId); } else { updateTimer( Math.min(updateInterval, interactiveTimeout - newTimer) ); } return newTimer; }); }, timeoutInterval); } updateTimer(Math.max(updateInterval, 0)); return () => { clearTimeout(timeoutId); }; }, [interactiveTimeout]); if (!interactiveTimeout || !timer) { return undefined; } const timerWidth = Math.round((timer / interactiveTimeout) * 100); return ( ); } const getWidgetInteractiveTimerStyles: LLComponentStyleFn = ({ theme }) => StyleSheet.create({ container: { position: 'absolute', top: 0, left: 0, right: 0, display: 'flex', justifyContent: 'flex-start', height: 4, backgroundColor: theme.widgetSelectedOption, }, innerContainer: { height: '100%', borderRadius: 2, backgroundColor: theme.primaryButtonBackground, }, });