[AGS] Bar: Done (WiFi still missing, will be added at some later point)
This commit is contained in:
		
							
								
								
									
										26
									
								
								config/astal/components/bar/modules/Calendar.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								config/astal/components/bar/modules/Calendar.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | ||||
| import { GLib, Variable } from "astal"; | ||||
| import { Gtk } from "astal/gtk4"; | ||||
|  | ||||
| const Time = ({ format = "%a, %e.%m %H:%M:%S" }) => { | ||||
|     const time = Variable<string>("").poll( | ||||
|         1000, | ||||
|         () => GLib.DateTime.new_now_local().format(format)!, | ||||
|     ); | ||||
|  | ||||
|     return ( | ||||
|         <menubutton | ||||
|             cssClasses={["time", "bar-button"]} | ||||
|             hexpand | ||||
|             halign={Gtk.Align.CENTER} | ||||
|         > | ||||
|             <label onDestroy={() => time.drop()} label={time()} halign={Gtk.Align.CENTER}></label> | ||||
|             <popover> | ||||
|                 <Gtk.Calendar /> | ||||
|             </popover> | ||||
|         </menubutton> | ||||
|     ); | ||||
| }; | ||||
|  | ||||
| export default { | ||||
|     Time, | ||||
| }; | ||||
							
								
								
									
										197
									
								
								config/astal/components/bar/modules/Hyprland.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										197
									
								
								config/astal/components/bar/modules/Hyprland.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,197 @@ | ||||
| import AstalTray from "gi://AstalTray"; | ||||
| import { bind, GObject } from "astal"; | ||||
| import AstalHyprland from "gi://AstalHyprland"; | ||||
| import { Gtk } from "astal/gtk4"; | ||||
|  | ||||
| const SYNC = GObject.BindingFlags.SYNC_CREATE; | ||||
|  | ||||
| const SysTray = () => { | ||||
|     const trayBox = new Gtk.Box({ cssClasses: ["bar-button"] }); | ||||
|     const tray = AstalTray.get_default(); | ||||
|  | ||||
|     const trayItems = new Map<string, Gtk.MenuButton>(); | ||||
|     const trayAddedHandler = tray.connect("item-added", (_, id) => { | ||||
|         const item = tray.get_item(id); | ||||
|         const popover = Gtk.PopoverMenu.new_from_model(item.menu_model); | ||||
|         const icon = new Gtk.Image(); | ||||
|         const button = new Gtk.MenuButton({ | ||||
|             popover, | ||||
|             child: icon, | ||||
|             cssClasses: ["tray-item"], | ||||
|         }); | ||||
|  | ||||
|         item.bind_property("gicon", icon, "gicon", SYNC); | ||||
|         popover.insert_action_group("dbusmenu", item.action_group); | ||||
|         item.connect("notify::action-group", () => { | ||||
|             popover.insert_action_group("dbusmenu", item.action_group); | ||||
|         }); | ||||
|  | ||||
|         trayItems.set(id, button); | ||||
|         trayBox.append(button); | ||||
|     }); | ||||
|  | ||||
|     const trayRemovedHandler = tray.connect("item-removed", (_, id) => { | ||||
|         const button = trayItems.get(id); | ||||
|         if (button) { | ||||
|             trayBox.remove(button); | ||||
|             button.run_dispose(); | ||||
|             trayItems.delete(id); | ||||
|         } | ||||
|     }); | ||||
|  | ||||
|     trayBox.connect("destroy", () => { | ||||
|         tray.disconnect(trayAddedHandler); | ||||
|         tray.disconnect(trayRemovedHandler); | ||||
|     }); | ||||
|  | ||||
|     return trayBox; | ||||
| }; | ||||
|  | ||||
| const Workspace = () => { | ||||
|     const hypr = AstalHyprland.get_default(); | ||||
|  | ||||
|     return ( | ||||
|         <box> | ||||
|             {bind(hypr, "workspaces").as(wss => | ||||
|                 wss | ||||
|                     .filter(ws => !(ws.id >= -99 && ws.id <= -2)) // filter out special workspaces | ||||
|                     .sort((a, b) => a.id - b.id) | ||||
|                     .map(ws => ( | ||||
|                         <button | ||||
|                             cssClasses={bind(hypr, "focusedWorkspace").as(fw => | ||||
|                                 ws === fw | ||||
|                                     ? [ | ||||
|                                           "focused-workspace-button", | ||||
|                                           "workspace-button", | ||||
|                                       ] | ||||
|                                     : ["workspace-button"], | ||||
|                             )} | ||||
|                             onButtonPressed={() => ws.focus()} | ||||
|                             child={<label label={String(ws.id)}></label>} | ||||
|                         ></button> | ||||
|                     )), | ||||
|             )} | ||||
|         </box> | ||||
|     ); | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * Displays the name of the currently active window and provides a popover for | ||||
|  * displaying all available clients | ||||
|  */ | ||||
| const ActiveWindow = () => { | ||||
|     const hypr = AstalHyprland.get_default(); | ||||
|     const focused = bind(hypr, "focusedClient"); | ||||
|  | ||||
|     const WindowPopover = (): Gtk.Popover => { | ||||
|         // Set up boxes + Popover | ||||
|         const clients = new Map<string, Gtk.Button>(); | ||||
|         const popover = new Gtk.Popover(); | ||||
|         const popoverBox = new Gtk.Box({ | ||||
|             orientation: Gtk.Orientation.VERTICAL, | ||||
|         }); | ||||
|  | ||||
|         const widgetTitle = new Gtk.Label({ | ||||
|             cssClasses: ["title-2"], | ||||
|             label: "Available Windows", | ||||
|         }); | ||||
|  | ||||
|         popoverBox.append(widgetTitle); | ||||
|  | ||||
|         const seaparator = new Gtk.Separator({ | ||||
|             marginTop: 5, | ||||
|             marginBottom: 10, | ||||
|         }); | ||||
|  | ||||
|         popoverBox.append(seaparator); | ||||
|  | ||||
|         const addClient = (client: AstalHyprland.Client) => { | ||||
|             const clientBox = new Gtk.Box(); | ||||
|  | ||||
|             // Workspace description | ||||
|             const descWS = new Gtk.Label({ label: "(WS " }); | ||||
|  | ||||
|             // Workpsace information | ||||
|             const workspace = new Gtk.Label(); | ||||
|             client.workspace.bind_property("name", workspace, "label", SYNC); | ||||
|  | ||||
|             const windowClassDesc = new Gtk.Label({ label: ") [" }); | ||||
|  | ||||
|             const windowClass = new Gtk.Label(); | ||||
|             windowClass.label = client.get_initial_class(); | ||||
|  | ||||
|             const titleDesc = new Gtk.Label({ label: "] " }); | ||||
|             titleDesc.set_margin_end(2); | ||||
|  | ||||
|             const title = new Gtk.Label(); | ||||
|             client.bind_property("title", title, "label", SYNC); | ||||
|  | ||||
|             clientBox.append(descWS); | ||||
|             clientBox.append(workspace); | ||||
|             clientBox.append(windowClassDesc); | ||||
|             clientBox.append(windowClass); | ||||
|             clientBox.append(titleDesc); | ||||
|             clientBox.append(title); | ||||
|  | ||||
|             const button = new Gtk.Button(); | ||||
|             button.connect( 'clicked', () => { | ||||
|                 client.workspace.focus(); | ||||
|             } ); | ||||
|             button.set_child(clientBox); | ||||
|  | ||||
|             popoverBox.append(button); | ||||
|  | ||||
|             clients.set(client.get_address(), button); | ||||
|         }; | ||||
|  | ||||
|         // Populate with already added clients | ||||
|         const c = hypr.get_clients(); | ||||
|         for (let index = 0; index < c.length; index++) { | ||||
|             addClient(c[index]); | ||||
|         } | ||||
|  | ||||
|         hypr.connect("client-added", (_, client) => { | ||||
|             addClient(client); | ||||
|         }); | ||||
|  | ||||
|         hypr.connect("client-removed", (_, client) => { | ||||
|             const c = clients.get(client); | ||||
|             if (c) { | ||||
|                 popoverBox.remove(c); | ||||
|                 c.run_dispose(); | ||||
|                 clients.delete(client); | ||||
|             } | ||||
|         }); | ||||
|  | ||||
|         popover.set_child(popoverBox); | ||||
|         return popover; | ||||
|     }; | ||||
|  | ||||
|     const windowPopover = WindowPopover(); | ||||
|  | ||||
|     // ─────────────────────────────────────────────────────────────────── | ||||
|     // Return fully assembled HyprlandFocusedClient box | ||||
|     // ─────────────────────────────────────────────────────────────────── | ||||
|     return ( | ||||
|         <box visible={focused.as(Boolean)}> | ||||
|             <button | ||||
|                 onClicked={() => windowPopover.popup()} | ||||
|                 cssClasses={["bar-button"]} | ||||
|             > | ||||
|                 {focused.as( | ||||
|                     client => | ||||
|                         client && ( | ||||
|                             <label label={bind(client, "title").as(String)} /> | ||||
|                         ), | ||||
|                 )} | ||||
|             </button> | ||||
|             {windowPopover} | ||||
|         </box> | ||||
|     ); | ||||
| }; | ||||
|  | ||||
| export default { | ||||
|     Workspace, | ||||
|     ActiveWindow, | ||||
|     SysTray, | ||||
| }; | ||||
							
								
								
									
										186
									
								
								config/astal/components/bar/modules/QuickView.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										186
									
								
								config/astal/components/bar/modules/QuickView.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,186 @@ | ||||
| import { bind } from "astal"; | ||||
| import AstalBattery from "gi://AstalBattery"; | ||||
| import AstalBluetooth from "gi://AstalBluetooth"; | ||||
| import AstalNetwork from "gi://AstalNetwork"; | ||||
| import AstalWp from "gi://AstalWp"; | ||||
| import { Gtk } from "astal/gtk4"; | ||||
| import Brightness from "../../../util/brightness"; | ||||
| import QuickActions from "../../QuickActions/QuickActions"; | ||||
|  | ||||
| const STATE = AstalNetwork.DeviceState; | ||||
|  | ||||
| const QuickView = () => { | ||||
|     const qa = QuickActions.QuickActions(); | ||||
|     const showQuickActions = () => { | ||||
|         qa.popup(); | ||||
|     }; | ||||
|  | ||||
|     return ( | ||||
|         <button | ||||
|             onClicked={() => showQuickActions()} | ||||
|             cssClasses={["quick-action-button"]} | ||||
|             child={ | ||||
|                 <box> | ||||
|                     <BatteryWidget></BatteryWidget> | ||||
|                     <Audio></Audio> | ||||
|                     <BluetoothWidget></BluetoothWidget> | ||||
|                     <NetworkWidget></NetworkWidget> | ||||
|                     <BrightnessWidget></BrightnessWidget> | ||||
|                     <image iconName={"system-shutdown-symbolic"}></image> | ||||
|                     {qa} | ||||
|                 </box> | ||||
|             } | ||||
|         ></button> | ||||
|     ); | ||||
| }; | ||||
|  | ||||
| const NetworkWidget = () => { | ||||
|     const network = AstalNetwork.get_default(); | ||||
|  | ||||
|     return ( | ||||
|         <box> | ||||
|             <image | ||||
|                 iconName={bind(network, "state").as(state => { | ||||
|                     if (state === AstalNetwork.State.CONNECTING) { | ||||
|                         return "chronometer-reset-symbolic"; | ||||
|                     } else if ( | ||||
|                         state === AstalNetwork.State.CONNECTED_LOCAL || | ||||
|                         state === AstalNetwork.State.CONNECTED_SITE || | ||||
|                         state === AstalNetwork.State.CONNECTED_GLOBAL | ||||
|                     ) { | ||||
|                         return "network-wired-activated-symbolic"; | ||||
|                     } else { | ||||
|                         return "paint-unknown-symbolic"; | ||||
|                     } | ||||
|                 })} | ||||
|                 cssClasses={["network-widget", "quick-view-symbol"]} | ||||
|                 visible={bind(network.wifi, "state").as( | ||||
|                     state => state !== STATE.ACTIVATED, | ||||
|                 )} | ||||
|             ></image> | ||||
|             <image | ||||
|                 iconName={bind(network.wifi, "state").as(state => { | ||||
|                     if (state === STATE.ACTIVATED) { | ||||
|                         return network.wifi.iconName; | ||||
|                     } else { | ||||
|                         return ""; | ||||
|                     } | ||||
|                 })} | ||||
|                 cssClasses={["network-widget", "quick-view-symbol"]} | ||||
|                 visible={bind(network.wifi, "state").as( | ||||
|                     state => state === STATE.ACTIVATED, | ||||
|                 )} | ||||
|             ></image> | ||||
|         </box> | ||||
|     ); | ||||
| }; | ||||
|  | ||||
| const BluetoothWidget = () => { | ||||
|     const bluetooth = AstalBluetooth.get_default(); | ||||
|     const enabled = bind(bluetooth.adapter, "powered"); | ||||
|     const connected = bind(bluetooth, "isConnected"); | ||||
|  | ||||
|     // For each connected BT device, render status | ||||
|     return ( | ||||
|         <box> | ||||
|             <box visible={enabled.as(e => e)}> | ||||
|                 <image | ||||
|                     iconName={"bluetooth-active-symbolic"} | ||||
|                     visible={connected.as(c => c)} | ||||
|                 ></image> | ||||
|                 <image | ||||
|                     iconName={"bluetooth-disconnected-symbolic"} | ||||
|                     visible={connected.as(c => !c)} | ||||
|                 ></image> | ||||
|             </box> | ||||
|             <image | ||||
|                 iconName={"bluetooth-disabled-symbolic"} | ||||
|                 visible={enabled.as(e => !e)} | ||||
|             ></image> | ||||
|             <box> | ||||
|                 {bind(bluetooth, "devices").as(devices => { | ||||
|                     return devices.map(device => { | ||||
|                         return ( | ||||
|                             <box visible={bind(device, "connected").as(c => c)}> | ||||
|                                 <image | ||||
|                                     iconName={bind(device, "icon").as( | ||||
|                                         icon => icon, | ||||
|                                     )} | ||||
|                                 ></image> | ||||
|                                 <label | ||||
|                                     label={bind(device, "batteryPercentage").as( | ||||
|                                         n => { | ||||
|                                             return n + "%"; | ||||
|                                         }, | ||||
|                                     )} | ||||
|                                 ></label> | ||||
|                             </box> | ||||
|                         ); | ||||
|                     }); | ||||
|                 })} | ||||
|             </box> | ||||
|         </box> | ||||
|     ); | ||||
| }; | ||||
|  | ||||
| const BatteryWidget = () => { | ||||
|     const battery = AstalBattery.get_default(); | ||||
|     if (battery.get_is_present()) { | ||||
|         return ( | ||||
|             <image | ||||
|                 iconName={bind(battery, "iconName").as(icon => icon)} | ||||
|                 cssClasses={["quick-view-symbol"]} | ||||
|             ></image> | ||||
|         ); | ||||
|     } else { | ||||
|         return <box></box>; | ||||
|     } | ||||
|     // Else, no battery available -> Don't show the widget | ||||
| }; | ||||
|  | ||||
| const BrightnessWidget = () => { | ||||
|     const brightness = Brightness.get_default(); | ||||
|     const screen_brightness = bind(brightness, "screen"); | ||||
|  | ||||
|     return ( | ||||
|         <label | ||||
|             label={"🌣" + screen_brightness} | ||||
|             visible={bind(brightness, "screenAvailable")} | ||||
|             cssClasses={["quick-view-symbol"]} | ||||
|         ></label> | ||||
|     ); | ||||
| }; | ||||
|  | ||||
| const Audio = () => { | ||||
|     const wireplumber = AstalWp.get_default(); | ||||
|     if (wireplumber) { | ||||
|         return ( | ||||
|             <box orientation={Gtk.Orientation.HORIZONTAL}> | ||||
|                 <image | ||||
|                     iconName={bind(wireplumber.defaultSpeaker, "volumeIcon").as( | ||||
|                         icon => icon, | ||||
|                     )} | ||||
|                     cssClasses={["quick-view-symbol"]} | ||||
|                 ></image> | ||||
|                 <image | ||||
|                     iconName={bind( | ||||
|                         wireplumber.defaultMicrophone, | ||||
|                         "volumeIcon", | ||||
|                     ).as(icon => icon)} | ||||
|                     cssClasses={["quick-view-symbol"]} | ||||
|                 ></image> | ||||
|             </box> | ||||
|         ); | ||||
|     } else { | ||||
|         print( | ||||
|             "[ WirePlumber ] Could not connect, Audio support in bar will be missing", | ||||
|         ); | ||||
|         return <image iconName={"action-unavailable-symbolic"}></image>; | ||||
|     } | ||||
| }; | ||||
|  | ||||
| // cssClasses={[ 'quick-view-symbol' ]} | ||||
|  | ||||
| export default { | ||||
|     QuickView, | ||||
| }; | ||||
							
								
								
									
										211
									
								
								config/astal/components/bar/modules/SystemInfo.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										211
									
								
								config/astal/components/bar/modules/SystemInfo.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,211 @@ | ||||
| import { exec, execAsync, GLib, interval, Variable } from "astal"; | ||||
| import { Gtk } from "astal/gtk4"; | ||||
| import AstalBattery from "gi://AstalBattery?version=0.1"; | ||||
|  | ||||
| const FETCH_INTERVAL = 2000; | ||||
|  | ||||
| const cpuUtil = Variable("0%"); | ||||
| const ramUtil = Variable("0%"); | ||||
| const ramUsed = Variable("0MiB"); | ||||
| const gpuUtil = Variable("0%"); | ||||
| let gpuName = "card1"; | ||||
| let enabled = false; | ||||
|  | ||||
| const refreshStats = (): Stats => { | ||||
|     gpuName = exec(`/bin/bash -c "ls /sys/class/drm/ | grep '^card[0-9]*$'"`); | ||||
|     const cpuNameInSensors = "CPUTIN"; | ||||
|     const stats = { | ||||
|         kernel: exec("uname -sr"), | ||||
|         netSpeed: exec( | ||||
|             `/bin/bash -c "interface=$(ip route get 8.8.8.8 | awk '{print $5; exit}') && cat \"/sys/class/net/$interface/speed\""`, | ||||
|         ), | ||||
|         cpuTemp: exec( | ||||
|             `/bin/bash -c "sensors | grep -m1 ${cpuNameInSensors} | awk '{print $2}'"`, | ||||
|         ), | ||||
|         cpuClk: exec( | ||||
|             `awk '/cpu MHz/ {sum+=$4; ++n} END {print sum/n " MHz"}' /proc/cpuinfo`, | ||||
|         ), | ||||
|         gpuTemp: exec( | ||||
|             `/bin/bash -c "sensors | grep -E 'edge' | awk '{print $2}'"`, | ||||
|         ), | ||||
|         gpuClk: exec( | ||||
|             `/bin/bash -c "cat /sys/class/drm/${gpuName}/device/pp_dpm_sclk | grep '\\*' | awk '{print $2 $3}'"`, | ||||
|         ), | ||||
|         vram: | ||||
|             Math.round( | ||||
|                 parseInt( | ||||
|                     exec( | ||||
|                         `cat /sys/class/drm/${gpuName}/device/mem_info_vram_used`, | ||||
|                     ), | ||||
|                 ) / | ||||
|                     1024 / | ||||
|                     1024, | ||||
|             ) + "MiB", | ||||
|         availableVRAM: | ||||
|             Math.round( | ||||
|                 parseInt( | ||||
|                     exec( | ||||
|                         `cat /sys/class/drm/${gpuName}/device/mem_info_vram_total`, | ||||
|                     ), | ||||
|                 ) / | ||||
|                     1024 / | ||||
|                     1024, | ||||
|             ) + "MiB", | ||||
|     }; | ||||
|  | ||||
|     return stats; | ||||
| }; | ||||
|  | ||||
| const systemStats: Variable<Stats> = Variable(refreshStats()); | ||||
|  | ||||
| const availableFeatures = { | ||||
|     cpu: true, | ||||
|     ram: true, | ||||
| }; | ||||
|  | ||||
| const featureTest = () => { | ||||
|     // Check if awk & sed are available | ||||
|     try { | ||||
|         exec("awk -V"); | ||||
|         exec("sed --version"); | ||||
|         enabled = true; | ||||
|     } catch (e) { | ||||
|         printerr( | ||||
|             "[ SysInfo ] AWK or SED missing! No system info will be available", | ||||
|         ); | ||||
|         enabled = false; | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     // Check if mpstat is available | ||||
|     try { | ||||
|         exec("mpstat -V"); | ||||
|     } catch (e) { | ||||
|         availableFeatures.cpu = false; | ||||
|         printerr( | ||||
|             "[ SysInfo ] Feature Test for CPU info failed. mpstat from the sysstat package missing!", | ||||
|         ); | ||||
|     } | ||||
| }; | ||||
|  | ||||
| const info = () => { | ||||
|     return ( | ||||
|         <box vertical> | ||||
|             <label | ||||
|                 label={"System Information"} | ||||
|                 cssClasses={["title-2"]} | ||||
|             ></label> | ||||
|             <Gtk.Separator marginTop={5} marginBottom={10}></Gtk.Separator> | ||||
|             <label | ||||
|                 vexpand | ||||
|                 halign={Gtk.Align.START} | ||||
|                 hexpand | ||||
|                 label={ramUsed(used => { | ||||
|                     return "RAM: " + used + ` (${ramUtil.get()}%)`; | ||||
|                 })} | ||||
|             ></label> | ||||
|             <label | ||||
|                 label={systemStats(stats => { | ||||
|                     return `CPU: ${stats.cpuTemp}, ${stats.cpuClk} | ||||
| GPU: ${stats.gpuTemp}, ${stats.gpuClk} (${stats.vram} / ${stats.availableVRAM}) | ||||
| Network: ${stats.netSpeed} mb/s | ||||
| Kernel: ${stats.kernel}`; | ||||
|                 })} | ||||
|             ></label> | ||||
|             <Gtk.Separator marginTop={10}></Gtk.Separator> | ||||
|             <button | ||||
|                 onClicked={() => exec( `/bin/sh -c "kitty --hold fish -c 'fastfetch'"` )} | ||||
|                 child={ | ||||
|                     <label label={"View FastFetch"}></label> | ||||
|                 }></button> | ||||
|         </box> | ||||
|     ); | ||||
| }; | ||||
|  | ||||
| const SystemInformationPanel = () => { | ||||
|     const popover = new Gtk.Popover(); | ||||
|  | ||||
|     popover.set_child(info()); | ||||
|  | ||||
|     return popover; | ||||
| }; | ||||
|  | ||||
| const sysInfoFetcher = () => { | ||||
|     if (enabled) { | ||||
|         if (availableFeatures.cpu) { | ||||
|             cpuUtil.set( | ||||
|                 "" + | ||||
|                     Math.round( | ||||
|                         parseFloat(exec(`/bin/fish -c cpu-utilization`)), | ||||
|                     ), | ||||
|             ); | ||||
|         } | ||||
|         if (availableFeatures.ram) { | ||||
|             ramUtil.set( | ||||
|                 "" + | ||||
|                     Math.round( | ||||
|                         parseFloat( | ||||
|                             exec( | ||||
|                                 `/bin/bash -c "free | awk '/Mem/ { printf(\\"%.2f\\\\n\\", ($3/$2)*100) }'"`, | ||||
|                             ), | ||||
|                         ), | ||||
|                     ), | ||||
|             ); | ||||
|             ramUsed.set( | ||||
|                 exec( | ||||
|                     `/bin/bash -c \"free -h | awk '/^Mem:/ {print $3 \\" used of \\" $2}'\"`, | ||||
|                 ) | ||||
|                     .replaceAll("Gi", "GiB") | ||||
|                     .replaceAll("Mi", "MiB"), | ||||
|             ); | ||||
|         } | ||||
|         gpuUtil.set(exec("cat /sys/class/drm/card1/device/gpu_busy_percent")); | ||||
|     } | ||||
| }; | ||||
|  | ||||
| const panel = SystemInformationPanel(); | ||||
|  | ||||
| const SystemInfo = () => { | ||||
|     featureTest(); | ||||
|  | ||||
|     const openSysInfo = async () => { | ||||
|         panel.popup(); | ||||
|         systemStats.set(refreshStats()); | ||||
|     }; | ||||
|  | ||||
|     if (enabled) { | ||||
|         sysInfoFetcher(); | ||||
|         interval(FETCH_INTERVAL, sysInfoFetcher); | ||||
|  | ||||
|         return ( | ||||
|             <button | ||||
|                 onClicked={() => openSysInfo()} | ||||
|                 child={ | ||||
|                     <box tooltipText={ramUsed(v => v)}> | ||||
|                         <image | ||||
|                             iconName={"power-profile-performance-symbolic"} | ||||
|                             marginEnd={1} | ||||
|                         ></image> | ||||
|                         <label | ||||
|                             label={cpuUtil(util => util)} | ||||
|                             marginEnd={5} | ||||
|                         ></label> | ||||
|                         <image iconName={"histogram-symbolic"}></image> | ||||
|                         <label label={ramUtil(util => util)}></label> | ||||
|                         <image iconName={"show-gpu-effects-symbolic"}></image> | ||||
|                         <label label={gpuUtil(util => util)}></label> | ||||
|                         {panel} | ||||
|                     </box> | ||||
|                 } | ||||
|                 cssClasses={["bar-button"]} | ||||
|             ></button> | ||||
|         ); | ||||
|     } else { | ||||
|         return <image iconName={"action-unavailable-symbolic"}></image>; | ||||
|     } | ||||
| }; | ||||
|  | ||||
| export default { | ||||
|     SystemInfo, | ||||
|     panel, | ||||
| }; | ||||
							
								
								
									
										10
									
								
								config/astal/components/bar/modules/stats.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								config/astal/components/bar/modules/stats.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | ||||
| interface Stats { | ||||
|     kernel: string; | ||||
|     netSpeed: string; | ||||
|     cpuTemp: string; | ||||
|     cpuClk: string; | ||||
|     gpuTemp: string; | ||||
|     gpuClk: string; | ||||
|     vram: string; | ||||
|     availableVRAM: string; | ||||
| } | ||||
		Reference in New Issue
	
	Block a user