import Cpu from "@/services/cpu"; import Gpu from "@/services/gpu"; import Memory from "@/services/memory"; import Storage from "@/services/storage"; import { osId } from "@/utils/system"; import PopupWindow from "@/widgets/popupwindow"; import { bind, execAsync, GLib, type Binding } from "astal"; import { App, Gtk, type Widget } from "astal/gtk3"; import type cairo from "cairo"; const fmt = (bytes: number, pow: number) => +(bytes / 1024 ** pow).toFixed(2); const format = ({ total, used }: { total: number; used: number }) => { if (total >= 1024 ** 4) return `${fmt(used, 4)}/${fmt(total, 4)} TiB`; if (total >= 1024 ** 3) return `${fmt(used, 3)}/${fmt(total, 3)} GiB`; if (total >= 1024 ** 2) return `${fmt(used, 2)}/${fmt(total, 2)} MiB`; if (total >= 1024) return `${fmt(used, 1)}/${fmt(total, 1)} KiB`; return `${used}/${total} B`; }; const User = () => ( {!GLib.file_test(HOME + "/.face", GLib.FileTest.EXISTS) && ( ); const Locations = () => ( ); const Slider = ({ value }: { value: Binding }) => ( `font-size: ${v}px;`)} setup={self => { const halfPi = Math.PI / 2; const styleContext = self.get_style_context(); self.set_size_request(-1, styleContext.get_property("min-height", Gtk.StateFlags.NORMAL) as number); self.connect("draw", (_, cr: cairo.Context) => { const styleContext = self.get_style_context(); const width = self.get_allocated_width(); const height = styleContext.get_property("min-height", Gtk.StateFlags.NORMAL) as number; self.set_size_request(-1, height); const progressValue = styleContext.get_property("font-size", Gtk.StateFlags.NORMAL) as number; let radius = styleContext.get_property("border-radius", Gtk.StateFlags.NORMAL) as number; const bg = styleContext.get_background_color(Gtk.StateFlags.NORMAL); cr.setSourceRGBA(bg.red, bg.green, bg.blue, bg.alpha); // Background cr.arc(radius, radius, radius, -Math.PI, -halfPi); // Top left cr.arc(width - radius, radius, radius, -halfPi, 0); // Top right cr.arc(width - radius, height - radius, radius, 0, halfPi); // Bottom right cr.arc(radius, height - radius, radius, halfPi, Math.PI); // Bottom left cr.fill(); // Flatten when near 0 radius = Math.min(radius, Math.min(width * progressValue, height) / 2); const progressPosition = width * progressValue - radius; const fg = styleContext.get_color(Gtk.StateFlags.NORMAL); cr.setSourceRGBA(fg.red, fg.green, fg.blue, fg.alpha); // Foreground cr.arc(radius, radius, radius, -Math.PI, -halfPi); // Top left cr.arc(progressPosition, radius, radius, -halfPi, 0); // Top right cr.arc(progressPosition, height - radius, radius, 0, halfPi); // Bottom right cr.arc(radius, height - radius, radius, halfPi, Math.PI); // Bottom left cr.fill(); }); }} /> ); const Resource = ({ icon, name, value, labelSetup, }: { icon: string; name: string; value: Binding; labelSetup?: (self: Widget.Label) => void; }) => ( ); const HwResources = () => ( {Gpu.get_default().available && } { const mem = Memory.get_default(); const update = () => (self.label = format(mem)); self.hook(mem, "notify::used", update); self.hook(mem, "notify::total", update); update(); }} /> { const storage = Storage.get_default(); const update = () => (self.label = format(storage)); self.hook(storage, "notify::used", update); self.hook(storage, "notify::total", update); update(); }} /> ); export default () => ( {/* */} );