From 6140123cbc3c90347e0078ba19553066ddf0a0ba Mon Sep 17 00:00:00 2001 From: soraefir Date: Fri, 12 Jun 2026 18:40:44 +0200 Subject: [PATCH] rm ags --- flake.lock | 45 -- flake.nix | 11 - modules/home/wayland/apps/ags/default.nix | 57 -- modules/home/wayland/apps/ags/src/app.tsx | 768 ------------------- modules/home/wayland/apps/ags/src/style.scss | 176 ----- modules/home/wayland/apps/default.nix | 2 +- modules/home/wayland/hyprland/config.nix | 1 - 7 files changed, 1 insertion(+), 1059 deletions(-) delete mode 100644 modules/home/wayland/apps/ags/default.nix delete mode 100644 modules/home/wayland/apps/ags/src/app.tsx delete mode 100644 modules/home/wayland/apps/ags/src/style.scss diff --git a/flake.lock b/flake.lock index a7075cf..5c4b1ae 100644 --- a/flake.lock +++ b/flake.lock @@ -1,48 +1,5 @@ { "nodes": { - "ags": { - "inputs": { - "astal": [ - "astal" - ], - "nixpkgs": [ - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1775689345, - "narHash": "sha256-tM3s7CX+tgxlYW0Sk3nzVThg2MHn08foIuMxABupxIs=", - "owner": "aylur", - "repo": "ags", - "rev": "bbee2f18939f1ec7ff720e717cf305e73635628f", - "type": "github" - }, - "original": { - "owner": "aylur", - "repo": "ags", - "type": "github" - } - }, - "astal": { - "inputs": { - "nixpkgs": [ - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1780295699, - "narHash": "sha256-gt9jeb/HOoiUSOTnE5I9K/B9LEbjJW5k37Xq99HOf/Q=", - "owner": "aylur", - "repo": "astal", - "rev": "271851bbc07748100382ae7caf6ef71c70c01bfc", - "type": "github" - }, - "original": { - "owner": "aylur", - "repo": "astal", - "type": "github" - } - }, "base16-schemes": { "flake": false, "locked": { @@ -297,8 +254,6 @@ }, "root": { "inputs": { - "ags": "ags", - "astal": "astal", "darwin": "darwin", "hardware": "hardware", "home-manager": "home-manager", diff --git a/flake.nix b/flake.nix index e80c35a..8e26870 100755 --- a/flake.nix +++ b/flake.nix @@ -34,17 +34,6 @@ url = "github:nix-community/nixos-vscode-server"; inputs.nixpkgs.follows = "nixpkgs"; }; - - astal = { - url = "github:aylur/astal"; - inputs.nixpkgs.follows = "nixpkgs"; - }; - - ags = { - url = "github:aylur/ags"; - inputs.nixpkgs.follows = "nixpkgs"; - inputs.astal.follows = "astal"; - }; }; outputs = inputs: diff --git a/modules/home/wayland/apps/ags/default.nix b/modules/home/wayland/apps/ags/default.nix deleted file mode 100644 index f93120d..0000000 --- a/modules/home/wayland/apps/ags/default.nix +++ /dev/null @@ -1,57 +0,0 @@ -{ inputs, lib, config, pkgs, ... }: -let - colorsScss = '' - $base00: #${config.colorScheme.palette.base00}; - $base01: #${config.colorScheme.palette.base01}; - $base02: #${config.colorScheme.palette.base02}; - $base03: #${config.colorScheme.palette.base03}; - $base04: #${config.colorScheme.palette.base04}; - $base05: #${config.colorScheme.palette.base05}; - $base06: #${config.colorScheme.palette.base06}; - $base07: #${config.colorScheme.palette.base07}; - $base08: #${config.colorScheme.palette.base08}; - $base09: #${config.colorScheme.palette.base09}; - $base0A: #${config.colorScheme.palette.base0A}; - $base0B: #${config.colorScheme.palette.base0B}; - $base0C: #${config.colorScheme.palette.base0C}; - $base0D: #${config.colorScheme.palette.base0D}; - $base0E: #${config.colorScheme.palette.base0E}; - $base0F: #${config.colorScheme.palette.base0F}; - - - $fg: $base07; - $bg0: $base00; - $bg1: $base01; - - $border-color: $base03; - $border-color-focus: $base04; - $border-radius: ${config.colorScheme.palette.border-radius}px; - $border-width: ${config.colorScheme.palette.border-width}px; - - $gaps-screen: ${config.colorScheme.palette.gaps-screen}px; - $gaps-window: ${config.colorScheme.palette.gaps-window}px; - ''; - configDir = pkgs.runCommandLocal "ags-config" {} '' - mkdir -p "$out" - cp -r ${lib.cleanSource ./src}/. "$out/" - mkdir -p "$out/css" - cat > "$out/css/_colors.scss" <<'EOF' - ${colorsScss} - EOF - ''; -in { - - imports = [ inputs.ags.homeManagerModules.default ]; - config = lib.mkIf (config.usercfg.wm == "Wayland") { - programs.ags = { - enable = true; - configDir = configDir; - extraPackages = with pkgs; [ - inputs.astal.packages.${pkgs.system}.battery - fzf - bluez - custom.amdgpu_top - ]; - }; - }; -} diff --git a/modules/home/wayland/apps/ags/src/app.tsx b/modules/home/wayland/apps/ags/src/app.tsx deleted file mode 100644 index c28f7cd..0000000 --- a/modules/home/wayland/apps/ags/src/app.tsx +++ /dev/null @@ -1,768 +0,0 @@ -import app from "ags/gtk4/app" -import { Astal } from "ags/gtk4" -import { createState, onCleanup } from "ags" -import { readFileAsync } from "ags/file" -import { execAsync } from "ags/process" -import { createPoll } from "ags/time" -import Gdk from "gi://Gdk?version=4.0" -import GLib from "gi://GLib" -import Gtk from "gi://Gtk?version=4.0" - -import style from "./style.scss" - -type Workspace = { - id: number - occupied: boolean - focused: boolean -} - -type BatteryState = { - available: boolean - percent: number - status: string - remaining: string - icon: string -} - -type SystemState = { - cpu: number - gpu: number - memory: number - memoryText: string - battery: BatteryState -} - -type ConnectivityState = { - wifi: { - label: string - detail: string - icon: string - } - ethernet: { - label: string - detail: string - icon: string - } - bluetooth: { - label: string - detail: string - icon: string - } -} - -type ClockState = { - hour: string - minute: string - month: string - year: string -} - -const SYSTEM_INIT: SystemState = { - cpu: 0, - gpu: 0, - memory: 0, - memoryText: "0 / 0 GiB", - battery: { - available: false, - percent: 0, - status: "No battery", - remaining: "", - icon: "󰂎", - }, -} - -const CONNECTIVITY_INIT: ConnectivityState = { - wifi: { - label: "Wi-Fi", - detail: "Unavailable", - icon: "󰖪", - }, - ethernet: { - label: "Ethernet", - detail: "Disconnected", - icon: "󰈀", - }, - bluetooth: { - label: "Bluetooth", - detail: "Off", - icon: "󰂲", - }, -} - -const CLOCK_INIT: ClockState = { - hour: "--", - minute: "--", - month: "--", - year: "--", -} - -let previousCpuSample: { total: number; idle: number } | null = null -const [powerMenuVisible, setPowerMenuVisible] = createState(false) - -function attachHover(widget: Gtk.Widget, onEnter: () => void, onLeave: () => void) { - const controller = new Gtk.EventControllerMotion() - controller.connect("enter", onEnter) - controller.connect("leave", onLeave) - widget.add_controller(controller) -} - -function clampPercent(value: number) { - if (!Number.isFinite(value)) { - return 0 - } - - return Math.max(0, Math.min(100, Math.round(value))) -} - -async function commandOrEmpty(command: string | string[]) { - try { - return (await execAsync(command)).trim() - } catch { - return "" - } -} - -async function readText(path: string) { - try { - return (await readFileAsync(path)).trim() - } catch { - return "" - } -} - -async function readNumber(path: string) { - const value = Number(await readText(path)) - return Number.isFinite(value) ? value : 0 -} - -function run(command: string) { - execAsync(["bash", "-lc", command]).catch((error) => console.error(error)) -} - -function focusWorkspace(id: number) { - run(`hyprctl dispatch workspace ${id}`) -} - -function mediaAction(action: string) { - run(`playerctl ${action}`) -} - -async function readWeather() { - const line = await commandOrEmpty([ - "bash", - "-lc", - "curl -fsS 'https://wttr.in/?format=%l:+%C+%t' 2>/dev/null | head -n1", - ]) - - return line || "Weather unavailable" -} - -function renderCalendar(now: Date) { - const monthLabel = now.toLocaleString("en-US", { month: "short" }).toUpperCase() - const year = now.getFullYear() - const header = `${monthLabel} ${year}` - const weekdays = "MO TU WE TH FR SA SU" - const first = new Date(year, now.getMonth(), 1) - const lastDay = new Date(year, now.getMonth() + 1, 0).getDate() - const offset = (first.getDay() + 6) % 7 - const slots = Array.from({ length: offset + lastDay }, (_, index) => - index < offset ? " " : String(index - offset + 1).padStart(2, " "), - ) - - const rows = [] - for (let index = 0; index < slots.length; index += 7) { - rows.push(slots.slice(index, index + 7).join(" ")) - } - - return [header, weekdays, ...rows].join("\n").replace(/ /g, "\u2007") -} - -function workspaceIcon(workspace: Workspace) { - if (workspace.focused) { - return "󰮯" - } - - if (workspace.occupied) { - return "󰊠" - } - - return "󰧞" -} - -function wifiIcon(detail: string) { - if (detail === "Off") { - return "󰖩" - } - - const strength = Number(detail.split("%", 1)[0]) - - if (!Number.isFinite(strength) || strength <= 0) { - return "󰖪" - } - - if (strength < 25) { - return "󰤯" - } - - if (strength < 50) { - return "󰤟" - } - - if (strength < 75) { - return "󰤢" - } - - return "󰤨" -} - -function batteryIcon(percent: number, status: string) { - if (status === "Charging") { - return "󰂄" - } - - if (percent <= 10) { - return "󰂎" - } - - if (percent <= 20) { - return "󰁺" - } - - if (percent <= 30) { - return "󰁻" - } - - if (percent <= 40) { - return "󰁼" - } - - if (percent <= 50) { - return "󰁽" - } - - if (percent <= 60) { - return "󰁾" - } - - if (percent <= 70) { - return "󰁿" - } - - if (percent <= 80) { - return "󰂀" - } - - if (percent <= 90) { - return "󰂁" - } - - return "󰂂" -} - -function formatHours(hours: number) { - const totalMinutes = Math.max(0, Math.round(hours * 60)) - const hh = String(Math.floor(totalMinutes / 60)).padStart(2, "0") - const mm = String(totalMinutes % 60).padStart(2, "0") - return `${hh}:${mm}` -} - -async function readWorkspaces() { - const [workspacesRaw, monitorsRaw] = await Promise.all([ - commandOrEmpty(["hyprctl", "-j", "workspaces"]), - commandOrEmpty(["hyprctl", "-j", "monitors"]), - ]) - - const workspaces = workspacesRaw ? JSON.parse(workspacesRaw) : [] - const monitors = monitorsRaw ? JSON.parse(monitorsRaw) : [] - const focused = monitors.find((monitor: any) => monitor.focused)?.activeWorkspace?.id ?? 1 - const occupied = new Set( - workspaces - .map((workspace: any) => Number(workspace.id)) - .filter((id: number) => Number.isFinite(id) && id > 0), - ) - - return Array.from({ length: 10 }, (_, index) => { - const id = index + 1 - - return { - id, - occupied: occupied.has(id), - focused: focused === id, - } - }) -} - -async function readSystem() { - const [statRaw, meminfoRaw, gpuRaw] = await Promise.all([ - readText("/proc/stat"), - readText("/proc/meminfo"), - commandOrEmpty(["amdgpu_top", "-J", "-n", "1"]), - ]) - - let cpu = 0 - const statLine = statRaw.split("\n")[0] ?? "" - const cpuValues = statLine - .split(/\s+/) - .slice(1) - .map((value) => Number(value)) - .filter((value) => Number.isFinite(value)) - - if (cpuValues.length >= 4) { - const total = cpuValues.reduce((sum, value) => sum + value, 0) - const idle = (cpuValues[3] ?? 0) + (cpuValues[4] ?? 0) - - if (previousCpuSample) { - const totalDelta = total - previousCpuSample.total - const idleDelta = idle - previousCpuSample.idle - - if (totalDelta > 0) { - cpu = clampPercent(((totalDelta - idleDelta) / totalDelta) * 100) - } - } - - previousCpuSample = { total, idle } - } - - const memTotal = Number(meminfoRaw.match(/^MemTotal:\s+(\d+)/m)?.[1] ?? 0) - const memAvailable = Number(meminfoRaw.match(/^MemAvailable:\s+(\d+)/m)?.[1] ?? 0) - const memUsed = Math.max(0, memTotal - memAvailable) - const memory = memTotal > 0 ? clampPercent((memUsed / memTotal) * 100) : 0 - const memoryText = `${(memUsed / 1024 / 1024).toFixed(1)} / ${(memTotal / 1024 / 1024).toFixed(1)} GiB` - - let gpu = 0 - - if (gpuRaw) { - try { - const gpuData = JSON.parse(gpuRaw) - const device = gpuData.devices?.[0] ?? {} - - gpu = - clampPercent( - Number( - device.gpu_activity?.GFX?.value ?? - device.GRBM2?.["Command Processor - Graphics"]?.value ?? - device.GRBM2?.["CommandProcessor-Graphics"]?.value ?? - 0, - ), - ) || 0 - } catch { - gpu = 0 - } - } - - const batteryPresent = Boolean(await readText("/sys/class/power_supply/BAT0/status")) - let battery = SYSTEM_INIT.battery - - if (batteryPresent) { - const [status, percent, powerNow, energyNow, energyFull] = await Promise.all([ - readText("/sys/class/power_supply/BAT0/status"), - readNumber("/sys/class/power_supply/BAT0/capacity"), - readNumber("/sys/class/power_supply/BAT0/power_now"), - readNumber("/sys/class/power_supply/BAT0/energy_now"), - readNumber("/sys/class/power_supply/BAT0/energy_full"), - ]) - - let remaining = status - - if (powerNow > 0 && energyNow > 0 && energyFull > 0) { - const hours = - status === "Charging" - ? (energyFull - energyNow) / powerNow - : status === "Discharging" - ? energyNow / powerNow - : 0 - - if (hours > 0) { - remaining = `${formatHours(hours)} ${status === "Charging" ? "to full" : "left"}` - } - } - - battery = { - available: true, - percent: clampPercent(percent), - status, - remaining, - icon: batteryIcon(percent, status), - } - } - - return { - cpu, - gpu, - memory, - memoryText, - battery, - } -} - -async function readConnectivity() { - const deviceStatus = await commandOrEmpty(["nmcli", "-t", "-f", "DEVICE,TYPE,STATE,CONNECTION", "device", "status"]) - const devices = deviceStatus - .split("\n") - .map((line) => line.trim()) - .filter(Boolean) - .map((line) => { - const [device, type, state, connection] = line.split(":") - return { device, type, state, connection } - }) - - const wifiDevice = devices.find((device) => device.type === "wifi") - const ethernetDevice = devices.find((device) => device.type === "ethernet") - - let wifi = CONNECTIVITY_INIT.wifi - - if (wifiDevice) { - if (wifiDevice.state === "connected") { - const wifiList = await commandOrEmpty([ - "nmcli", - "-t", - "-f", - "IN-USE,SIGNAL,SSID", - "device", - "wifi", - "list", - "--rescan", - "no", - ]) - const activeLine = - wifiList - .split("\n") - .map((line) => line.trim()) - .find((line) => line.startsWith("*:")) ?? "" - const [, signalRaw = "0", ssid = wifiDevice.connection] = activeLine.split(":") - const signal = clampPercent(Number(signalRaw)) - - wifi = { - label: "Wi-Fi", - detail: `${signal}% ${ssid || wifiDevice.connection}`, - icon: wifiIcon(`${signal}%`), - } - } else if (wifiDevice.state === "disconnected") { - wifi = { - label: "Wi-Fi", - detail: "Idle", - icon: "󰖪", - } - } - } - - const ethernet = - ethernetDevice && ethernetDevice.state === "connected" - ? { - label: "Ethernet", - detail: ethernetDevice.connection || ethernetDevice.device, - icon: "󰈀", - } - : CONNECTIVITY_INIT.ethernet - - const bluetoothShow = await commandOrEmpty(["bash", "-lc", "bluetoothctl show 2>/dev/null || true"]) - const bluetoothDevices = await commandOrEmpty([ - "bash", - "-lc", - "bluetoothctl devices Connected 2>/dev/null | cut -d' ' -f3- || true", - ]) - const bluetoothPowered = /Powered:\s+yes/.test(bluetoothShow) - const connectedDevices = bluetoothDevices.split("\n").map((line) => line.trim()).filter(Boolean) - - const bluetooth = bluetoothPowered - ? { - label: "Bluetooth", - detail: connectedDevices[0] ?? "Ready", - icon: connectedDevices.length > 0 ? "󰂱" : "󰂯", - } - : CONNECTIVITY_INIT.bluetooth - - return { - wifi, - ethernet, - bluetooth, - } -} - -function Section(props: { title: string; className?: string; children?: JSX.Element | Array }) { - return ( - - - ) -} - -function StatRow(props: { - icon: any - label: any - value: any - fraction?: any - visible?: any -}) { - return ( - - - - - - ) -} - -function StatusRow(props: { icon: any; label: any; detail: any }) { - return ( - - - ) -} - -function ActionButton(props: { icon: string; tooltip: string; command: string }) { - return ( - - ) -} - -function WorkspacesSection() { - const workspaces = createPoll([], 1500, readWorkspaces) - const workspaceIds = Array.from({ length: 10 }, (_, index) => index + 1) - - return ( -
- - {workspaceIds.map((id) => { - const workspace = workspaces( - (items) => items.find((item) => item.id === id) ?? { id, occupied: false, focused: false }, - ) - - return ( - - ) - })} - -
- ) -} - -function MediaSection() { - return ( -
- - - - - -
- ) -} - -function SystemSection() { - const system = createPoll(SYSTEM_INIT, 2500, readSystem) - - return ( -
- `${value.cpu}%`)} - fraction={system((value) => value.cpu / 100)} - /> - `${value.gpu}%`)} - fraction={system((value) => value.gpu / 100)} - /> - `${value.memory}%`)} - fraction={system((value) => value.memory / 100)} - /> - value.battery.icon)} - label={system((value) => value.battery.status)} - value={system((value) => `${value.battery.percent}%`)} - fraction={system((value) => value.battery.percent / 100)} - visible={system((value) => value.battery.available)} - /> -
- ) -} - -function ConnectivitySection() { - const connectivity = createPoll(CONNECTIVITY_INIT, 5000, readConnectivity) - - return ( -
- value.wifi.icon)} - label={connectivity((value) => value.wifi.label)} - detail={connectivity((value) => value.wifi.detail)} - /> - value.bluetooth.icon)} - label={connectivity((value) => value.bluetooth.label)} - detail={connectivity((value) => value.bluetooth.detail)} - /> - value.ethernet.icon)} - label={connectivity((value) => value.ethernet.label)} - detail={connectivity((value) => value.ethernet.detail)} - /> -
- ) -} - -function WidgetsSection() { - return ( -
- - - - - - -
- ) -} - -function ClockPowerSection() { - const clock = createPoll(CLOCK_INIT, 1000, () => { - const now = GLib.DateTime.new_now_local() - - return { - hour: now.format("%H") ?? "--", - minute: now.format("%M") ?? "--", - month: now.format("%m") ?? "--", - year: now.format("%y") ?? "--", - } - }) - const [clockHovered, setClockHovered] = createState(false) - - return ( -
- -
- ) -} - -function PowerMenu({ gdkmonitor }: { gdkmonitor: Gdk.Monitor }) { - const weather = createPoll("Weather unavailable", 900000, readWeather) - const calendar = createPoll(renderCalendar(new Date()), 60000, () => renderCalendar(new Date())) - const { TOP, BOTTOM, LEFT, RIGHT } = Astal.WindowAnchor - - return ( - - -