From a79a89d855c79b9b967d8d6ab5df0c1cffff8d93 Mon Sep 17 00:00:00 2001 From: Nicolas Mowen Date: Mon, 26 Feb 2024 13:58:33 -0700 Subject: [PATCH] Be smarter about updating timeago --- web/src/components/dynamic/TimeAgo.tsx | 59 +++++++++++++++++++------- 1 file changed, 43 insertions(+), 16 deletions(-) diff --git a/web/src/components/dynamic/TimeAgo.tsx b/web/src/components/dynamic/TimeAgo.tsx index 3dd510cef..df2b70285 100644 --- a/web/src/components/dynamic/TimeAgo.tsx +++ b/web/src/components/dynamic/TimeAgo.tsx @@ -8,7 +8,7 @@ interface IProp { /** OPTIONAL: boolean that determines whether to show the time-ago text in dense format */ dense?: boolean; /** OPTIONAL: set custom refresh interval in milliseconds, default 1000 (1 sec) */ - refreshInterval?: number; + manualRefreshInterval?: number; } type TimeUnit = { @@ -17,24 +17,28 @@ type TimeUnit = { value: number; }; -const timeAgo = ({ time, currentTime = new Date(), dense = false }: IProp): string => { - if (typeof time !== 'number' || time < 0) return 'Invalid Time Provided'; +const timeAgo = ({ + time, + currentTime = new Date(), + dense = false, +}: IProp): string => { + if (typeof time !== "number" || time < 0) return "Invalid Time Provided"; const pastTime: Date = new Date(time); const elapsedTime: number = currentTime.getTime() - pastTime.getTime(); const timeUnits: TimeUnit[] = [ - { unit: 'yr', full: 'year', value: 31536000 }, - { unit: 'mo', full: 'month', value: 0 }, - { unit: 'd', full: 'day', value: 86400 }, - { unit: 'h', full: 'hour', value: 3600 }, - { unit: 'm', full: 'minute', value: 60 }, - { unit: 's', full: 'second', value: 1 }, + { unit: "yr", full: "year", value: 31536000 }, + { unit: "mo", full: "month", value: 0 }, + { unit: "d", full: "day", value: 86400 }, + { unit: "h", full: "hour", value: 3600 }, + { unit: "m", full: "minute", value: 60 }, + { unit: "s", full: "second", value: 1 }, ]; const elapsed: number = elapsedTime / 1000; if (elapsed < 10) { - return 'just now'; + return "just now"; } for (let i = 0; i < timeUnits.length; i++) { @@ -48,7 +52,8 @@ const timeAgo = ({ time, currentTime = new Date(), dense = false }: IProp): stri const currentMonth = currentTime.getUTCMonth(); const currentYear = currentTime.getUTCFullYear(); - let monthDiff = (currentYear - pastYear) * 12 + (currentMonth - pastMonth); + let monthDiff = + (currentYear - pastYear) * 12 + (currentMonth - pastMonth); // check if the time provided is the previous month but not exceeded 1 month ago. if (currentTime.getUTCDate() < pastTime.getUTCDate()) { @@ -57,18 +62,37 @@ const timeAgo = ({ time, currentTime = new Date(), dense = false }: IProp): stri if (monthDiff > 0) { const unitAmount = monthDiff; - return `${unitAmount}${dense ? timeUnits[i].unit : ` ${timeUnits[i].full}`}${dense ? '' : 's'} ago`; + return `${unitAmount}${dense ? timeUnits[i].unit : ` ${timeUnits[i].full}`}${dense ? "" : "s"} ago`; } } else if (elapsed >= timeUnits[i].value) { const unitAmount: number = Math.floor(elapsed / timeUnits[i].value); - return `${unitAmount}${dense ? timeUnits[i].unit : ` ${timeUnits[i].full}`}${dense ? '' : 's'} ago`; + return `${unitAmount}${dense ? timeUnits[i].unit : ` ${timeUnits[i].full}`}${dense ? "" : "s"} ago`; } } - return 'Invalid Time'; + return "Invalid Time"; }; -const TimeAgo: FunctionComponent = ({ refreshInterval = 1000, ...rest }): JSX.Element => { +const TimeAgo: FunctionComponent = ({ + time, + manualRefreshInterval, + ...rest +}): JSX.Element => { const [currentTime, setCurrentTime] = useState(new Date()); + const refreshInterval = useMemo(() => { + if (manualRefreshInterval) { + return manualRefreshInterval; + } + + const currentTs = currentTime.getTime() / 1000; + if (currentTs - time < 60) { + return 1000; // refresh every second + } else if (currentTs - time < 3600) { + return 60000; // refresh every minute + } else { + return 3600000; // refresh every hour + } + }, [currentTime, manualRefreshInterval]); + useEffect(() => { const intervalId: NodeJS.Timeout = setInterval(() => { setCurrentTime(new Date()); @@ -76,7 +100,10 @@ const TimeAgo: FunctionComponent = ({ refreshInterval = 1000, ...rest }): return () => clearInterval(intervalId); }, [refreshInterval]); - const timeAgoValue = useMemo(() => timeAgo({ currentTime, ...rest }), [currentTime, rest]); + const timeAgoValue = useMemo( + () => timeAgo({ time, currentTime, ...rest }), + [currentTime, rest] + ); return {timeAgoValue}; };