diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index 429d178..4584032 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -459,15 +459,17 @@ how to override it. Items marked ✓ are shipped. `nomarchy-menu nightlight` entry (System submenu, self-gated on the unit existing) and a self-gating Waybar `custom/nightlight` indicator (moon = on, sun = off; in the generated bar and both summer whole-swaps) drive it. - The toggle is **session-scoped by design**: `stop` halts the running unit - but it's `WantedBy=graphical-session.target`, so the next login auto-starts - it and night-light returns to its schedule (off never persists). Remaining - (optional): (1) **persistent off** — a state marker - (`~/.local/state/nomarchy/nightlight-off`) the unit honours via - `ConditionPathExists=!%h/…`, so a manual off survives logout/reboot until - toggled back; (2) geo (lat/long) auto sunset/sunrise (would mean wlsunset, - which schedules by location). Pending an on-machine check that stopping - hyprsunset cleanly restores the gamma. + ✓ **Persistent off:** a manual `off` now drops a marker + (`~/.local/state/nomarchy/nightlight-off`) and the unit refuses to (re)start + while it exists (`Unit.ConditionPathExists=!%h/…`), so an off survives + logout/reboot until toggled back on; `on`/toggle-on remove the marker first + (a failed condition would otherwise no-op the start). Without the marker the + service stays `WantedBy=graphical-session.target` and resumes its schedule at + login as before — the session-scoped behaviour is now the *default*, with + persistence opt-in via the toggle. Remaining (optional): geo (lat/long) auto + sunset/sunrise (would mean wlsunset, which schedules by location). Pending an + on-machine check (off persisting across reboot, and that stopping hyprsunset + cleanly restores the gamma). - **Keyboard layouts (per-device + switching):** - ✓ **Per-device declarative layout:** `nomarchy.keyboard.devices` (`{ "" = { layout; variant; }; }`) generates Hyprland diff --git a/modules/home/nightlight.nix b/modules/home/nightlight.nix index db4aca0..c757503 100644 --- a/modules/home/nightlight.nix +++ b/modules/home/nightlight.nix @@ -21,6 +21,12 @@ let # module hides itself — same pattern as the power-profile indicator. nomarchy-nightlight = pkgs.writeShellScriptBin "nomarchy-nightlight" '' unit=hyprsunset.service + # Persistent-off marker — mirrors the unit's ConditionPathExists below. + # Present => night-light stays off across logout/reboot until toggled on. + # Path is literal (not XDG_STATE_HOME) so it matches the unit's %h check. + marker="$HOME/.local/state/nomarchy/nightlight-off" + mark_off() { mkdir -p "$(dirname "$marker")"; : > "$marker"; } + mark_on() { rm -f "$marker"; } if ! systemctl --user cat "$unit" >/dev/null 2>&1; then [ "''${1:-}" = status ] && exit 0 notify-send "Night light" "Not enabled — set nomarchy.nightlight.enable." @@ -33,14 +39,14 @@ let else printf '{"text":"󰖙","tooltip":"Night light off (click to enable)","class":"off"}\n' fi ;; - on) systemctl --user start "$unit" ;; - off) systemctl --user stop "$unit" ;; + on) mark_on; systemctl --user start "$unit" ;; + off) mark_off; systemctl --user stop "$unit" ;; toggle) if systemctl --user is-active --quiet "$unit"; then - systemctl --user stop "$unit" - notify-send "Night light off" "Screen back to true colours." + mark_off; systemctl --user stop "$unit" + notify-send "Night light off" "Screen back to true colours (stays off until re-enabled)." else - systemctl --user start "$unit" + mark_on; systemctl --user start "$unit" notify-send "Night light on" "Warm filter follows your schedule." fi ;; *) echo "usage: nomarchy-nightlight [toggle|status|on|off]" >&2; exit 64 ;; @@ -59,6 +65,13 @@ in ]; }; + # Persistent off: a manual `off` drops ~/.local/state/nomarchy/nightlight-off, + # and this Condition makes the unit refuse to (re)start while it exists — so + # an off survives logout/reboot. `nomarchy-nightlight on` removes it first + # (a failed condition would otherwise no-op the start). %h = $HOME. + systemd.user.services.hyprsunset.Unit.ConditionPathExists = + lib.mkIf cfg.enable "!%h/.local/state/nomarchy/nightlight-off"; + # Always on PATH (it self-gates at runtime), so a static whole-swap Waybar # can exec it even when night-light is off without the call failing. home.packages = [ nomarchy-nightlight ];