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 Utils from "../../utils"; export { wifiStyles as styles } from "../../styles/components/data/wifi"; const { React } = Uebersicht; const DEFAULT_REFRESH_FREQUENCY = 20000; /** * Wifi widget component. * @returns {JSX.Element|null} The Wifi widget. */ export const Widget = React.memo(() => { const { displayIndex, settings, pushMissive } = useSimpleBarContext(); const { widgets, networkWidgetOptions } = settings; const { wifiWidget } = widgets; const { refreshFrequency, hideWifiIfDisabled, toggleWifiOnClick, networkDevice, hideNetworkName, showOnDisplay, showIcon, } = networkWidgetOptions; const visible = Utils.isVisibleOnDisplay(displayIndex, showOnDisplay) && wifiWidget; const refresh = React.useMemo( () => Utils.getRefreshFrequency(refreshFrequency, DEFAULT_REFRESH_FREQUENCY), [refreshFrequency], ); const [state, setState] = React.useState(); const [loading, setLoading] = React.useState(visible); /** * Resets the widget state. */ const resetWidget = () => { setState(undefined); setLoading(false); }; /** * Fetches the wifi status and SSID. */ const getWifi = React.useCallback(async () => { if (!visible) return; const [status, ssid] = await Promise.all([ Utils.cachedRun( `ifconfig ${networkDevice} | grep status | cut -c 10-`, refresh, ), Utils.cachedRun( `system_profiler SPAirPortDataType | awk '/Current Network/ {getline;$1=$1;print $0 | "tr -d ':'";exit}'`, refresh, ), ]); setState({ status: Utils.cleanupOutput(status), ssid: Utils.cleanupOutput(ssid), }); setLoading(false); }, [networkDevice, visible, refresh]); useServerSocket("wifi", visible, getWifi, resetWidget, setLoading); useWidgetRefresh(visible, getWifi, refresh); if (loading) return ; if (!state) return null; const { status, ssid } = state; const isActive = status === "active"; const name = renderName(ssid, hideNetworkName); if (hideWifiIfDisabled && !isActive) return null; const classes = Utils.classNames("wifi", { "wifi--hidden-name": !name, "wifi--inactive": !isActive, }); const Icon = isActive ? Icons.Wifi : Icons.WifiOff; /** * Handles the click event to toggle wifi. * @param {React.MouseEvent} e - The click event. */ const onClick = async (e) => { Utils.clickEffect(e); await toggleWifi(isActive, networkDevice, pushMissive); getWifi(); }; return ( {name} ); }); Widget.displayName = "Wifi"; /** * Toggles the wifi on or off. * @param {boolean} isActive - Whether the wifi is currently active. * @param {string} networkDevice - The network device name. * @param {function} pushMissive - Function to push notifications. */ async function toggleWifi(isActive, networkDevice, pushMissive) { if (isActive) { await Uebersicht.run(`networksetup -setairportpower ${networkDevice} off`); Utils.notification("Disabling network...", pushMissive); } else { await Uebersicht.run(`networksetup -setairportpower ${networkDevice} on`); Utils.notification("Enabling network...", pushMissive); } } /** * Opens the wifi preferences pane. * @param {React.MouseEvent} e - The click event. */ function openWifiPreferences(e) { Utils.clickEffect(e); Uebersicht.run(`open /System/Library/PreferencePanes/Network.prefPane/`); } /** * Renders the wifi network name. * @param {string} name - The network name. * @param {boolean} hideNetworkName - Whether to hide the network name. * @returns {string} The rendered network name. */ function renderName(name, hideNetworkName) { if (!name || hideNetworkName) return ""; if (name === "with an AirPort network.y off.") return "Disabled"; if (name === "with an AirPort network.") return "Searching..."; return name; }