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;
};