aboutsummaryrefslogtreecommitdiff
path: root/users/ryan/modules/simple-bar/simple-bar-source/lib/components/settings/user-widgets-creator.jsx
diff options
context:
space:
mode:
Diffstat (limited to 'users/ryan/modules/simple-bar/simple-bar-source/lib/components/settings/user-widgets-creator.jsx')
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/settings/user-widgets-creator.jsx297
1 files changed, 297 insertions, 0 deletions
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/settings/user-widgets-creator.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/settings/user-widgets-creator.jsx
new file mode 100755
index 0000000..a026047
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/settings/user-widgets-creator.jsx
@@ -0,0 +1,297 @@
1import * as Uebersicht from "uebersicht";
2import * as Icons from "../icons/icons.jsx";
3import * as Settings from "../../settings";
4import * as Utils from "../../utils";
5import ColorPicker from "./color-picker.jsx";
6import IconPicker from "./icon-picker.jsx";
7
8const { React } = Uebersicht;
9
10/**
11 * UserWidgetsCreator component allows users to create and manage custom widgets.
12 * @param {Object} props - The component props.
13 * @param {Object} props.defaultValue - The default value for the widgets.
14 * @param {Function} props.onChange - The function to call when the widgets change.
15 * @returns {JSX.Element} The UserWidgetsCreator component.
16 */
17export default function UserWidgetsCreator({ defaultValue, onChange }) {
18 const [widgets, setWidgets] = React.useState(defaultValue || {});
19 const keys = Object.keys(widgets);
20
21 // Determine the highest widget ID and calculate the new ID for a new widget
22 const highestId = keys.reduce((acc, key) => {
23 const keyAsNumber = parseInt(key, 10);
24 return keyAsNumber > acc ? keyAsNumber : acc;
25 }, 1);
26 const newId = highestId + 1;
27
28 // Function to add a new widget
29 const onClick = () =>
30 setWidgets((widgets) => ({
31 ...widgets,
32 [newId]: { ...Settings.userWidgetDefault },
33 }));
34
35 // Function to handle changes to a widget
36 const onWidgetChange = (index, field, value) => {
37 const newWidgets = { ...widgets };
38 const newKeys = Object.keys(newWidgets);
39 const updatedWidgets = newKeys.reduce((acc, key, i) => {
40 const widget = newWidgets[key];
41 return {
42 ...acc,
43 [i + 1]: key === index ? { ...widget, [field]: value } : widget,
44 };
45 }, {});
46 setWidgets(updatedWidgets);
47 };
48
49 // Effect to detect changes in widgets and call onChange prop
50 React.useEffect(() => {
51 const diffs = Utils.compareObjects(defaultValue, widgets);
52 const hasDiffs = Object.keys(diffs).length > 0;
53 if (hasDiffs) onChange({ target: { value: widgets } });
54 }, [defaultValue, onChange, widgets]);
55
56 return (
57 <div className="user-widgets-creator">
58 {keys.map((key, i) => (
59 <UserWidgetCreator
60 key={`${key}-${widgets[key].backgroundColor}`}
61 index={key}
62 onWidgetChange={onWidgetChange}
63 setWidgets={setWidgets}
64 widget={widgets[key]}
65 isFirst={i === 0}
66 isLast={i === keys.length - 1}
67 />
68 ))}
69 <button className="user-widgets-creator__add" onClick={onClick}>
70 <Icons.Add />
71 Add a custom widget
72 </button>
73 </div>
74 );
75}
76
77/**
78 * UserWidgetCreator component allows users to configure individual widgets.
79 * @param {Object} props - The component props.
80 * @param {string} props.index - The index of the widget.
81 * @param {boolean} props.isFirst - Whether the widget is the first in the list.
82 * @param {boolean} props.isLast - Whether the widget is the last in the list.
83 * @param {Function} props.onWidgetChange - The function to call when the widget changes.
84 * @param {Function} props.setWidgets - The function to set the widgets state.
85 * @param {Object} props.widget - The widget data.
86 * @returns {JSX.Element} The UserWidgetCreator component.
87 */
88function UserWidgetCreator({
89 index,
90 isFirst,
91 isLast,
92 onWidgetChange,
93 setWidgets,
94 widget,
95}) {
96 const {
97 title,
98 icon,
99 backgroundColor,
100 output,
101 onClickAction,
102 onRightClickAction,
103 onMiddleClickAction,
104 refreshFrequency,
105 active = true,
106 noIcon = false,
107 hideWhenNoOutput = true,
108 showOnDisplay = "",
109 } = widget;
110
111 const indexAsNumber = parseInt(index, 10);
112
113 // Function to remove a widget
114 const onRemoveClick = () => {
115 setWidgets((widgets) => {
116 const keys = Object.keys(widgets);
117 return keys.reduce(
118 (acc, key) => (key === index ? acc : { ...acc, [key]: widgets[key] }),
119 {},
120 );
121 });
122 };
123
124 // Function to handle changes to widget fields
125 const onChange = (field, chexbox = false) => {
126 return (e) => {
127 const value = (chexbox ? e?.target?.checked : e?.target?.value) ?? "";
128 onWidgetChange(index, field, value);
129 };
130 };
131
132 // Function to move the widget up in the list
133 const onBeforeClick = () => {
134 setWidgets((widgets) => {
135 const swapedWidget = widgets[indexAsNumber - 1];
136 return {
137 ...widgets,
138 [indexAsNumber - 1]: widget,
139 [indexAsNumber]: swapedWidget,
140 };
141 });
142 };
143
144 // Function to move the widget down in the list
145 const onAfterClick = () => {
146 setWidgets((widgets) => {
147 const swapedWidget = widgets[indexAsNumber + 1];
148 return {
149 ...widgets,
150 [indexAsNumber + 1]: widget,
151 [indexAsNumber]: swapedWidget,
152 };
153 });
154 };
155
156 return (
157 <div key={indexAsNumber} className="user-widget-creator">
158 <div className="user-widget-creator__sort-buttons">
159 {!isFirst && (
160 <button
161 className="user-widget-creator__sort-button user-widget-creator__sort-button--before"
162 onClick={onBeforeClick}
163 >
164 <Icons.ChevronTop />
165 </button>
166 )}
167 {!isLast && (
168 <button
169 className="user-widget-creator__sort-button user-widget-creator__sort-button--after"
170 onClick={onAfterClick}
171 >
172 <Icons.ChevronBottom />
173 </button>
174 )}
175 </div>
176 <button className="user-widget-creator__remove" onClick={onRemoveClick}>
177 <Icons.Remove />
178 </button>
179 <div className="user-widget-creator__index">
180 n°<b>{index}</b>
181 </div>
182 <IconPicker callback={onWidgetChange} index={index} selectedIcon={icon} />
183 <div className="user-widget-creator__right">
184 <div className="user-widget-creator__right-top">
185 <ColorPicker
186 callback={onWidgetChange}
187 index={index}
188 selectedColor={backgroundColor}
189 />
190 <input
191 className="user-widget-creator__title"
192 onChange={onChange("title")}
193 type="text"
194 defaultValue={title}
195 />
196 <label htmlFor={`refresh-frequency-${index}`}>
197 Refresh frequency (ms):
198 </label>
199 <input
200 className="user-widget-creator__refresh-frequency"
201 onChange={onChange("refreshFrequency")}
202 id={`refresh-frequency-${index}`}
203 type="text"
204 defaultValue={refreshFrequency}
205 />
206 </div>
207 <div className="user-widget-creator__input-group">
208 <label htmlFor={`show-on-display-${index}`}>Show on display: </label>
209 <input
210 className="user-widget-creator__show-on-display"
211 onChange={onChange("showOnDisplay")}
212 id={`show-on-display-${index}`}
213 type="text"
214 defaultValue={showOnDisplay}
215 placeholder="example: 1,2 (leave blank to show on all displays)"
216 spellCheck={false}
217 />
218 </div>
219 <div className="user-widget-creator__input-group">
220 <label htmlFor={`output-${index}`}>Command/script path: </label>
221 <input
222 className="user-widget-creator__output"
223 onChange={onChange("output")}
224 id={`output-${index}`}
225 type="text"
226 defaultValue={output}
227 spellCheck={false}
228 />
229 </div>
230 <div className="user-widget-creator__input-group">
231 <label htmlFor={`on-click-action-${index}`}>
232 On click command/script path:{" "}
233 </label>
234 <input
235 className="user-widget-creator__on-click-action"
236 onChange={onChange("onClickAction")}
237 id={`on-click-action-${index}`}
238 type="text"
239 defaultValue={onClickAction}
240 spellCheck={false}
241 />
242 </div>
243 <div className="user-widget-creator__input-group">
244 <label htmlFor={`on-right-click-action-${index}`}>
245 On right click command/script path:{" "}
246 </label>
247 <input
248 className="user-widget-creator__on-right-click-action"
249 onChange={onChange("onRightClickAction")}
250 id={`on-right-click-action-${index}`}
251 type="text"
252 defaultValue={onRightClickAction}
253 spellCheck={false}
254 />
255 </div>
256 <div className="user-widget-creator__input-group">
257 <label htmlFor={`on-middle-click-action-${index}`}>
258 On middle click command/script path:{" "}
259 </label>
260 <input
261 className="user-widget-creator__on-middle-click-action"
262 onChange={onChange("onMiddleClickAction")}
263 id={`on-middle-click-action-${index}`}
264 type="text"
265 defaultValue={onMiddleClickAction}
266 spellCheck={false}
267 />
268 </div>
269 <div className="user-widget-creator__input-group">
270 <input
271 id={`active-${index}`}
272 type="checkbox"
273 defaultChecked={active}
274 onChange={onChange("active", true)}
275 />
276 <label htmlFor={`active-${index}`}>Active</label>
277 <input
278 id={`no-icon-${index}`}
279 type="checkbox"
280 defaultChecked={noIcon}
281 onChange={onChange("noIcon", true)}
282 />
283 <label htmlFor={`no-icon-${index}`}>No icon</label>
284 <input
285 id={`hide-when-no-output-${index}`}
286 type="checkbox"
287 defaultChecked={hideWhenNoOutput}
288 onChange={onChange("hideWhenNoOutput", true)}
289 />
290 <label htmlFor={`hide-when-no-output-${index}`}>
291 Hide when no script output
292 </label>
293 </div>
294 </div>
295 </div>
296 );
297}