import { Text, zero } from "@streamplace/components"; import * as chrono from "chrono-node"; import { useEffect, useState } from "react"; import { View, useWindowDimensions } from "react-native"; interface CountdownProps { from?: string; to?: string; small?: boolean; } interface LabelBoxProps { children: React.ReactNode; small?: boolean; } const LabelBox = ({ children, small }: LabelBoxProps) => { return ( {children} ); }; export function Countdown({ from, to, small }: CountdownProps) { const [now, setNow] = useState(Date.now()); const [dest, setDest] = useState(null); const { width, height } = useWindowDimensions(); useEffect(() => { if (from) { const fromDate = chrono.parseDate(from); if (fromDate === null) { throw new Error("could not parse from"); } setDest(fromDate.getTime()); } else if (to) { const toDate = chrono.parseDate(to); if (toDate === null) { throw new Error("could not parse to"); } setDest(toDate.getTime()); } else { throw new Error("must provide either from or to"); } }, [from, to]); useEffect(() => { const tick = () => { if (!running) { return; } requestAnimationFrame(tick); setNow(Date.now()); }; let running = true; tick(); return () => { running = false; }; }, []); if (dest === null) { return ; } let diff = Math.abs(dest - now); if (to && now > dest) { diff = 0; } else if (from && now < dest) { diff = 0; } small = small ?? width <= 600; const [years, days, hrs, min, sec, ms] = toLabels(diff); const unitStyle = [ zero.mx[small ? 2 : 4], zero.flex.values[0], { flexDirection: "column" }, ]; const timeTextStyle = [ { fontFamily: "monospace" }, small ? { fontSize: 18 } : { fontSize: 128 }, small ? { lineHeight: 24 } : { lineHeight: 40 }, ]; return ( {years} YEARS {days} DAYS {hrs} HRS {min} MIN {sec} SEC {ms} MS ); } const toLabels = ( now: number, ): [string, string, string, string, string, string] => { const ms = now % 1000; now = Math.floor(now / 1000); const sec = now % 60; now = Math.floor(now / 60); const min = now % 60; now = Math.floor(now / 60); const hrs = now % 24; now = Math.floor(now / 24); const days = now % 365; now = Math.floor(now / 365); const years = now; return [ pad(years, 4), pad(days, 3), pad(hrs, 2), pad(min, 2), pad(sec, 2), pad(ms, 3), ]; }; const pad = (num: number, n: number): string => { let str = `${num}`; while (str.length < n) { str = "0" + str; } return str; };