aboutsummaryrefslogtreecommitdiff
path: root/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/time.jsx
diff options
context:
space:
mode:
Diffstat (limited to 'users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/time.jsx')
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/data/time.jsx144
1 files changed, 144 insertions, 0 deletions
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/time.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/time.jsx
new file mode 100755
index 0000000..6890ffb
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/time.jsx
@@ -0,0 +1,144 @@
1import * as Uebersicht from "uebersicht";
2import * as DataWidget from "./data-widget.jsx";
3import * as DataWidgetLoader from "./data-widget-loader.jsx";
4import useWidgetRefresh from "../../hooks/use-widget-refresh";
5import useServerSocket from "../../hooks/use-server-socket";
6import { useSimpleBarContext } from "../simple-bar-context.jsx";
7import * as Utils from "../../utils";
8
9export { timeStyles as styles } from "../../styles/components/data/time";
10
11const { React } = Uebersicht;
12
13const DEFAULT_REFRESH_FREQUENCY = 1000;
14
15/**
16 * Time widget component.
17 * @returns {JSX.Element|null} The rendered widget.
18 */
19export const Widget = React.memo(() => {
20 const { displayIndex, settings } = useSimpleBarContext();
21 const { widgets, timeWidgetOptions } = settings;
22 const { timeWidget } = widgets;
23 const {
24 refreshFrequency,
25 hour12,
26 dayProgress,
27 showSeconds,
28 showOnDisplay,
29 showIcon,
30 } = timeWidgetOptions;
31
32 // Determine if the widget should be visible on the current display
33 const visible =
34 Utils.isVisibleOnDisplay(displayIndex, showOnDisplay) && timeWidget;
35
36 // Calculate the refresh frequency for the widget
37 const refresh = React.useMemo(
38 () =>
39 Utils.getRefreshFrequency(refreshFrequency, DEFAULT_REFRESH_FREQUENCY),
40 [refreshFrequency],
41 );
42
43 const [state, setState] = React.useState();
44 const [loading, setLoading] = React.useState(visible);
45
46 // Options for formatting the time string
47 const options = React.useMemo(
48 () => ({
49 hour: "numeric",
50 minute: "numeric",
51 second: showSeconds ? "numeric" : undefined,
52 hour12,
53 }),
54 [hour12, showSeconds],
55 );
56
57 /**
58 * Resets the widget state.
59 */
60 const resetWidget = () => {
61 setState(undefined);
62 setLoading(false);
63 };
64
65 /**
66 * Fetches the current time and updates the widget state.
67 */
68 const getTime = React.useCallback(() => {
69 if (!visible) return;
70 const time = new Date().toLocaleString("en-UK", options);
71 setState({ time });
72 setLoading(false);
73 }, [visible, options]);
74
75 // Use server socket to get time updates
76 useServerSocket("time", visible, getTime, resetWidget, setLoading);
77 // Refresh the widget at the specified interval
78 useWidgetRefresh(visible, getTime, refresh);
79
80 if (loading) return <DataWidgetLoader.Widget className="time" />;
81 if (!state) return null;
82 const { time } = state;
83
84 // Calculate the progress of the current day
85 const [dayStart, dayEnd] = [new Date(), new Date()];
86 dayStart.setHours(0, 0, 0);
87 dayEnd.setHours(0, 0, 0);
88 dayEnd.setDate(dayEnd.getDate() + 1);
89 const range = dayEnd - dayStart;
90 const diff = Math.max(0, dayEnd - new Date());
91 const fillerWidth = (100 - (100 * diff) / range) / 100;
92
93 /**
94 * Icon component for the time widget.
95 * @returns {JSX.Element} The rendered icon.
96 */
97 const TimeIcon = () => {
98 return <Icon time={time} />;
99 };
100
101 return (
102 <DataWidget.Widget
103 classes="time"
104 Icon={showIcon ? TimeIcon : null}
105 disableSlider
106 >
107 {time}
108 {dayProgress && (
109 <div
110 className="time__filler"
111 style={{ transform: `scaleX(${fillerWidth})` }}
112 />
113 )}
114 </DataWidget.Widget>
115 );
116});
117
118Widget.displayName = "Time";
119
120/**
121 * Icon component for displaying the time as a clock.
122 * @param {Object} props - The component props.
123 * @param {string} props.time - The current time string.
124 * @returns {JSX.Element} The rendered icon.
125 */
126function Icon({ time }) {
127 const [hours, minutes] = time.split(":");
128
129 const hoursInDegree = ((parseInt(hours, 10) % 12) / 12) * 360;
130 const minutesInDegree = (parseInt(minutes, 10) / 60) * 360;
131
132 return (
133 <div className="time__icon">
134 <div
135 className="time__hours"
136 style={{ transform: `rotate(${hoursInDegree}deg)` }}
137 />
138 <div
139 className="time__minutes"
140 style={{ transform: `rotate(${minutesInDegree}deg)` }}
141 />
142 </div>
143 );
144}