fix(ags-v3): nice-to-have — portabilité, perf, réactivité

- Prompt.tsx: GLib.get_user_name() au lieu de hardcode "tetardtek"
- ghost-shell.desktop: $HOME au lieu de chemin absolu
- SystemStats.tsx: lecture /proc/stat + /proc/meminfo (zero fork, économie batterie)
- Battery.tsx: createDerivedBinding percentage+charging — réactif sur branchement
This commit is contained in:
2026-03-26 09:13:36 +01:00
parent da22b6446d
commit 51b725e1f7
4 changed files with 74 additions and 33 deletions

View File

@@ -1,13 +1,18 @@
import AstalBattery from "gi://AstalBattery" import AstalBattery from "gi://AstalBattery"
import { createBinding } from "ags" import { createBinding, createDerivedBinding } from "ags"
export default function Battery() { export default function Battery() {
const bat = AstalBattery.get_default() const bat = AstalBattery.get_default()
const text = createBinding(bat, "percentage")((p: number) => { const percentage = createBinding(bat, "percentage")
const charging = createBinding(bat, "charging")
const text = createDerivedBinding(
[percentage, charging],
(p: number, isCharging: boolean) => {
const pct = Math.round(p * 100) const pct = Math.round(p * 100)
let icon = "" let icon = ""
if (bat.charging) icon = "󰂄" if (isCharging) icon = "󰂄"
else if (pct > 90) icon = "󰁹" else if (pct > 90) icon = "󰁹"
else if (pct > 70) icon = "󰂁" else if (pct > 70) icon = "󰂁"
else if (pct > 50) icon = "󰁿" else if (pct > 50) icon = "󰁿"
@@ -15,15 +20,19 @@ export default function Battery() {
else if (pct > 10) icon = "󰁻" else if (pct > 10) icon = "󰁻"
else icon = "󰂃" else icon = "󰂃"
return `${icon} ${pct}%` return `${icon} ${pct}%`
}) },
)
const cls = createBinding(bat, "percentage")((p: number) => { const cls = createDerivedBinding(
[percentage, charging],
(p: number, isCharging: boolean) => {
const pct = Math.round(p * 100) const pct = Math.round(p * 100)
if (bat.charging) return "battery charging" if (isCharging) return "battery charging"
if (pct <= 10) return "battery low" if (pct <= 10) return "battery low"
if (pct <= 20) return "battery warning" if (pct <= 20) return "battery warning"
return "battery" return "battery"
}) },
)
return <label class={cls} label={text} /> return <label class={cls} label={text} />
} }

View File

@@ -1,6 +1,9 @@
import GLib from "gi://GLib"
import { createPoll } from "ags/time" import { createPoll } from "ags/time"
export default function Prompt() { export default function Prompt() {
const username = GLib.get_user_name() || "user"
const cursor = createPoll("_", 600, () => { const cursor = createPoll("_", 600, () => {
// alternate between _ and empty to create blink // alternate between _ and empty to create blink
return Date.now() % 1200 < 600 ? "_" : " " return Date.now() % 1200 < 600 ? "_" : " "
@@ -8,7 +11,7 @@ export default function Prompt() {
return ( return (
<box> <box>
<label class="prompt-name" label="tetardtek" /> <label class="prompt-name" label={username} />
<label class="prompt-cursor" label={cursor} /> <label class="prompt-cursor" label={cursor} />
</box> </box>
) )

View File

@@ -1,21 +1,50 @@
import GLib from "gi://GLib"
import { createPoll } from "ags/time" import { createPoll } from "ags/time"
import { exec } from "ags/process"
function readProc(path: string): string | null {
try {
const [ok, contents] = GLib.file_get_contents(path)
if (ok && contents) return new TextDecoder().decode(contents)
} catch {}
return null
}
let prevIdle = 0
let prevTotal = 0
function getCpuUsage(): string { function getCpuUsage(): string {
try { const content = readProc("/proc/stat")
const out = exec("bash -c \"top -bn1 | grep 'Cpu(s)' | awk '{print 100 - $8}'\"") if (!content) return "?"
return `${Math.round(parseFloat(out))}`
} catch { const line = content.split("\n")[0] // "cpu user nice system idle ..."
return "?" const parts = line.split(/\s+/).slice(1).map(Number)
} const idle = parts[3] + parts[4] // idle + iowait
const total = parts.reduce((a, b) => a + b, 0)
const dIdle = idle - prevIdle
const dTotal = total - prevTotal
prevIdle = idle
prevTotal = total
if (dTotal === 0) return "0"
return `${Math.round(((dTotal - dIdle) / dTotal) * 100)}`
} }
function getRamUsage(): string { function getRamUsage(): string {
try { const content = readProc("/proc/meminfo")
return exec("bash -c \"free | awk '/Mem:/ {printf \\\"%.0f\\\", $3/$2 * 100}'\"") if (!content) return "?"
} catch {
return "?" const lines = content.split("\n")
let total = 0, available = 0
for (const line of lines) {
if (line.startsWith("MemTotal:")) total = parseInt(line.split(/\s+/)[1])
if (line.startsWith("MemAvailable:")) available = parseInt(line.split(/\s+/)[1])
if (total && available) break
} }
if (!total) return "?"
return `${Math.round(((total - available) / total) * 100)}`
} }
export default function SystemStats() { export default function SystemStats() {

View File

@@ -2,5 +2,5 @@
Type=Application Type=Application
Name=Ghost Shell Name=Ghost Shell
Comment=violet-chaton v2 AGS statusbar Comment=violet-chaton v2 AGS statusbar
Exec=ags run -d /home/tetardtek/.config/ags-v3 -g 3 Exec=sh -c "ags run -d $HOME/.config/ags-v3 -g 3"
X-GNOME-Autostart-enabled=true X-GNOME-Autostart-enabled=true