feat: live charge limit, identity retunes, btop assets (product calls)
All checks were successful
Check / eval (push) Successful in 3m0s

- Charge limit: udev GROUP=users on threshold; menu applies sysfs live
  and persists state; boot/AC oneshot prefers live theme-state.json.
- Look & Feel: Reset wallpaper (auto); Theme/next/night light already there.
- NVIDIA first-class wrappers deferred past v1 (keep #59 comments).
- Identity taste: white, lumon, hackerman, matte-black, miasma.
- Hand btop.theme for identity + boreal/executive-slate/neon-glass.

Verified: V0 contrast; V1 battery-charge-limit VM. V3 live sysfs on laptop.
This commit is contained in:
Bernardo Magri
2026-07-10 12:12:13 +01:00
parent 099d214529
commit eb951569cf
21 changed files with 306 additions and 474 deletions

View File

@@ -5,13 +5,12 @@
# gate on powerprofilesctl being present, so there's no system→home wiring
# to keep in sync (the same way the Waybar battery widget auto-hides on
# desktops). See the roadmap in README.md.
{ config, lib, ... }:
{ config, lib, pkgs, ... }:
let
cfg = config.nomarchy.system.power;
ppd = cfg.backend == "ppd";
tlp = cfg.backend == "tlp";
chargeLimit = cfg.laptop && cfg.batteryChargeLimit != null;
in
{
config = lib.mkIf cfg.enable {
@@ -40,36 +39,51 @@ in
# TLP's own knob only applies under TLP — so a tiny oneshot writes
# the threshold directly, independent of the backend. Re-applied on
# AC state changes by the udev rule below (some firmwares reset the
# threshold when the charger is unplugged). `[ -w ]` skips paths that
# don't exist, so this is a clean no-op on hardware without the control.
systemd.services.nomarchy-battery-charge-limit = lib.mkIf chargeLimit {
description = "Cap battery charging at ${toString cfg.batteryChargeLimit}%";
# threshold when the charger is unplugged).
#
# Instant menu path (user decision 2026-07-10): the threshold node is
# group-writable for `users` so nomarchy-menu can echo live without
# rebuild; this oneshot still owns boot + AC-replug re-apply. Prefer
# live theme-state.json under /home/*/.nomarchy so a menu change
# survives reboot before the next sys-rebuild bakes the Nix option.
systemd.services.nomarchy-battery-charge-limit = lib.mkIf cfg.laptop {
description = "Apply battery charge end threshold from state or config";
wantedBy = [ "multi-user.target" ];
path = [ pkgs.jq pkgs.coreutils ];
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
};
script = ''
# Name-agnostic (BAT0, CMB0, ): same type/scope filter as
# nomarchy-battery-notify BACKLOG #60.
set -euo pipefail
# Baked generation default (empty = full charge / no cap).
limit=${if cfg.batteryChargeLimit != null then toString cfg.batteryChargeLimit else ""}
# Prefer the newest live state write (menu path, no rebuild yet).
for st in /home/*/.nomarchy/theme-state.json; do
[ -r "$st" ] || continue
v=$(jq -r '.settings.power.batteryChargeLimit // empty' "$st" 2>/dev/null || true)
case "$v" in
""|null|Null) ;;
*[!0-9]*) ;;
*) limit=$v ;;
esac
done
[ -n "$limit" ] || limit=100
# Name-agnostic system batteries (BACKLOG #60).
for d in /sys/class/power_supply/*/; do
[ "$(cat "$d/type" 2>/dev/null)" = Battery ] || continue
[ "$(cat "$d/scope" 2>/dev/null || echo System)" = Device ] && continue
thresh="$d/charge_control_end_threshold"
[ -w "$thresh" ] && echo ${toString cfg.batteryChargeLimit} > "$thresh"
[ -w "$thresh" ] && echo "$limit" > "$thresh" || true
done
exit 0
'';
};
# Re-apply the threshold whenever the mains adapter changes state: the
# boot oneshot above runs once, but some firmwares clear the limit when
# the charger is unplugged, so it must be re-asserted on the event.
# Matched by ATTR{type}=="Mains" (vendor-neutral — the kernel name
# AC/AC0/ADP1/ACAD varies); --no-block so the RUN+= returns at once
# (systemd kills long-running udev workers); restart (not try-restart)
# so it re-applies even if the boot run was inactive.
services.udev.extraRules = lib.mkIf chargeLimit ''
# Writable threshold for the logged-in user (menu live apply) + AC
# re-apply of the oneshot. Laptop only; no-op when the attr is absent.
services.udev.extraRules = lib.mkIf cfg.laptop ''
SUBSYSTEM=="power_supply", ATTR{type}=="Battery", TEST=="charge_control_end_threshold", GROUP="users", MODE="0664"
SUBSYSTEM=="power_supply", ATTR{type}=="Mains", RUN+="${config.systemd.package}/bin/systemctl --no-block restart nomarchy-battery-charge-limit.service"
'';
};