Moved clock to web worker

This commit is contained in:
Dustin Brett 2021-10-16 22:19:27 -07:00
parent ac504e83d7
commit 4f72053c66
6 changed files with 94 additions and 65 deletions

View File

@ -0,0 +1,54 @@
export type LocaleTimeDate = {
date: string;
dateTime: string;
time: string;
};
const clockWorker = (): void => {
const locale = "en";
const secondsInMilliseconds = 1000;
const dateFormat: Intl.DateTimeFormatOptions = {
day: "numeric",
month: "long",
year: "numeric",
};
const timeFormat: Intl.DateTimeFormatOptions = {
hour: "numeric",
hour12: true,
minute: "2-digit",
second: "2-digit",
};
const dayFormat: Intl.DateTimeFormatOptions = {
weekday: "long",
};
const formatLocaleDateTime = (now: Date): LocaleTimeDate => {
const date = new Intl.DateTimeFormat(locale, dateFormat).format(now);
const day = new Intl.DateTimeFormat(locale, dayFormat).format(now);
const time = new Intl.DateTimeFormat(locale, timeFormat).format(now);
return {
date: `${date}\n${day}`,
dateTime: now.toISOString(),
time,
};
};
const sendTick = (): void => postMessage(formatLocaleDateTime(new Date()));
let initialized = false;
globalThis.addEventListener(
"message",
({ data }) => {
if (!initialized && data === "init") {
sendTick();
setTimeout(() => {
sendTick();
setInterval(sendTick, secondsInMilliseconds);
}, secondsInMilliseconds - new Date().getMilliseconds());
initialized = true;
}
},
{ passive: true }
);
};
export default clockWorker;

View File

@ -1,10 +1,17 @@
import type { LocaleTimeDate } from "components/system/Taskbar/Clock/clockWorker";
import clockWorker from "components/system/Taskbar/Clock/clockWorker";
import StyledClock from "components/system/Taskbar/Clock/StyledClock";
import useClock from "components/system/Taskbar/Clock/useClock";
import useLocaleDateTime from "components/system/Taskbar/Clock/useLocaleDateTime";
import { useCallback, useState } from "react";
import useWorker from "utils/useWorker";
const Clock = (): JSX.Element => {
const now = useClock();
const { date, time, dateTime } = useLocaleDateTime(now);
const [{ date = "", time = "", dateTime = "" }, setNow] =
useState<LocaleTimeDate>({} as LocaleTimeDate);
useWorker<LocaleTimeDate>(
clockWorker,
useCallback(({ data }) => setNow(data), [])
);
return (
<StyledClock dateTime={dateTime} title={date} suppressHydrationWarning>

View File

@ -1,22 +0,0 @@
import { useEffect, useState } from "react";
import { MILLISECONDS_IN_SECOND } from "utils/constants";
const useClock = (): Date => {
const [now, setNow] = useState(new Date());
const updateClock = (): void => setNow(new Date());
useEffect(() => {
let timeoutId: NodeJS.Timeout;
timeoutId = setTimeout(() => {
updateClock();
timeoutId = setInterval(updateClock, MILLISECONDS_IN_SECOND);
}, MILLISECONDS_IN_SECOND - new Date().getMilliseconds());
return () => clearTimeout(timeoutId);
}, []);
return now;
};
export default useClock;

View File

@ -1,28 +0,0 @@
import { useTheme } from "styled-components";
import { DEFAULT_LOCALE } from "utils/constants";
type LocaleTimeDate = {
date: string;
dateTime: string;
time: string;
};
const useLocaleDateTime = (now: Date): LocaleTimeDate => {
const { formats } = useTheme();
const formattedDate = new Intl.DateTimeFormat(
DEFAULT_LOCALE,
formats.date
).format(now);
const day = new Intl.DateTimeFormat(DEFAULT_LOCALE, {
weekday: "long",
}).format(now);
const date = `${formattedDate}\n${day}`;
const time = new Intl.DateTimeFormat(DEFAULT_LOCALE, formats.time).format(
now
);
const dateTime = now.toISOString();
return { date, dateTime, time };
};
export default useLocaleDateTime;

View File

@ -1,9 +1,4 @@
const formats = {
date: {
day: "numeric",
month: "long",
year: "numeric",
} as Intl.DateTimeFormatOptions,
dateModified: {
hour: "numeric",
hour12: true,
@ -11,12 +6,6 @@ const formats = {
} as Intl.DateTimeFormatOptions,
systemFont:
"system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif",
time: {
hour: "numeric",
hour12: true,
minute: "2-digit",
second: "2-digit",
} as Intl.DateTimeFormatOptions,
};
export default formats;

29
utils/useWorker.ts Normal file
View File

@ -0,0 +1,29 @@
import { useEffect, useState } from "react";
const useWorker = <T extends unknown>(
workerFunction: () => void,
onMessage: (message: { data: T }) => void
): void => {
const [worker, setWorker] = useState<Worker>();
useEffect(() => {
const workerUrl = URL.createObjectURL(
new Blob(["(", workerFunction.toString(), ")()"], {
type: "application/javascript",
})
);
setWorker(new Worker(workerUrl));
URL.revokeObjectURL(workerUrl);
}, [workerFunction]);
useEffect(() => {
worker?.addEventListener("message", onMessage, { passive: true });
worker?.postMessage("init");
return () => worker?.terminate();
}, [onMessage, worker]);
};
export default useWorker;