import * as Uebersicht from "uebersicht"; import * as DataWidget from "./data-widget.jsx"; import * as DataWidgetLoader from "./data-widget-loader.jsx"; import * as Icons from "../icons/icons.jsx"; import useWidgetRefresh from "../../hooks/use-widget-refresh"; import useServerSocket from "../../hooks/use-server-socket"; import { useSimpleBarContext } from "../simple-bar-context.jsx"; import * as Settings from "../../settings"; import * as Utils from "../../utils"; const { React } = Uebersicht; export default React.memo(UserWidgets); /** * UserWidgets component that renders a list of user-defined widgets. * @returns {JSX.Element[]} Array of UserWidget components. */ function UserWidgets() { const { settings } = useSimpleBarContext(); const { userWidgetsList } = settings.userWidgets; // Get the keys of the userWidgetsList object const keys = Object.keys(userWidgetsList); // Map over the keys and render a UserWidget for each key return keys.map((key) => ( )); } UserWidgets.displayName = "UserWidgets"; /** * UserWidget component that renders an individual user-defined widget. * @param {Object} props - The component props. * @param {string} props.index - The index of the widget. * @param {Object} props.widget - The widget configuration object. * @returns {JSX.Element|null} The rendered UserWidget component or null if not visible. */ const UserWidget = React.memo(({ index, widget }) => { const { displayIndex, settings } = useSimpleBarContext(); const [state, setState] = React.useState(); const [loading, setLoading] = React.useState(true); const [isWidgetActive, setIsWidgetActive] = React.useState(true); const { icon, backgroundColor, output, onClickAction, onRightClickAction, onMiddleClickAction, refreshFrequency, active, noIcon, hideWhenNoOutput = true, showOnDisplay = "", } = widget; // Determine if the widget should be visible based on display settings and active status const visible = Utils.isVisibleOnDisplay(displayIndex, showOnDisplay) && active; /** * Resets the widget state and loading status. */ const resetWidget = () => { setState(undefined); setLoading(false); setIsWidgetActive(true); }; /** * Fetches the widget output and updates the state. */ const getUserWidget = React.useCallback(async () => { if (!visible) return; const widgetOutput = await Utils.cachedRun(output, refreshFrequency); const cleanedOutput = Utils.cleanupOutput(widgetOutput); // Hide widget if script returns empty output and hideWhenNoOutput is enabled if ( hideWhenNoOutput && (!cleanedOutput.length || cleanedOutput.trim() === "") ) { setLoading(false); setIsWidgetActive(false); setState(undefined); return; } setState(widgetOutput); setIsWidgetActive(true); setLoading(false); }, [visible, output, hideWhenNoOutput, refreshFrequency]); // Use server socket to listen for widget updates useServerSocket( "user-widget", visible, getUserWidget, resetWidget, setLoading, index, ); // Refresh the widget at the specified frequency useWidgetRefresh(visible, getUserWidget, refreshFrequency); // Hide widget if not visible or if script indicates it should be inactive (only when hideWhenNoOutput is enabled) if (!visible || (hideWhenNoOutput && !isWidgetActive)) return null; const isCustomColor = !Settings.userWidgetColors.includes(backgroundColor); const property = settings.global.widgetsBackgroundColorAsForeground ? "color" : "backgroundColor"; const style = settings.global.noColorInData ? undefined : { [property]: isCustomColor ? backgroundColor : `var(${backgroundColor})`, }; if (loading) return ; const Icon = !noIcon ? Icons[icon] : null; const hasOnClickAction = onClickAction?.trim().length > 0; const hasRightClickAction = onRightClickAction?.trim().length > 0; const hasMiddleClickAction = onMiddleClickAction?.trim().length > 0; /** * Handles the click event for the widget. * @param {Event} e - The click event. */ const onClick = async (e) => { Utils.clickEffect(e); await Uebersicht.run(onClickAction); getUserWidget(); }; /** * Handles the right-click event for the widget. * @param {Event} e - The right-click event. */ const onRightClick = async (e) => { Utils.clickEffect(e); await Uebersicht.run(onRightClickAction); getUserWidget(); }; /** * Handles the middle-click event for the widget. * @param {Event} e - The middle-click event. */ const onMiddleClick = async (e) => { Utils.clickEffect(e); await Uebersicht.run(onMiddleClickAction); getUserWidget(); }; const onClickProps = { onClick: hasOnClickAction ? onClick : undefined, onRightClick: hasRightClickAction ? onRightClick : undefined, onMiddleClick: hasMiddleClickAction ? onMiddleClick : undefined, }; return ( {state} ); }); UserWidget.displayName = "UserWidget";