feat(nightlight): persistent off via state marker
A manual `off` now drops ~/.local/state/nomarchy/nightlight-off and the hyprsunset unit refuses to (re)start while it exists (Unit.ConditionPathExists=!%h/...), so the off survives logout/reboot until toggled back on. `on`/toggle-on remove the marker before starting (a failed condition would otherwise no-op the start). Without the marker behaviour is unchanged: the service stays WantedBy=graphical-session.target and resumes its schedule at login, so persistence is opt-in via the toggle. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -459,15 +459,17 @@ how to override it. Items marked ✓ are shipped.
|
|||||||
`nomarchy-menu nightlight` entry (System submenu, self-gated on the unit
|
`nomarchy-menu nightlight` entry (System submenu, self-gated on the unit
|
||||||
existing) and a self-gating Waybar `custom/nightlight` indicator (moon = on,
|
existing) and a self-gating Waybar `custom/nightlight` indicator (moon = on,
|
||||||
sun = off; in the generated bar and both summer whole-swaps) drive it.
|
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
|
✓ **Persistent off:** a manual `off` now drops a marker
|
||||||
but it's `WantedBy=graphical-session.target`, so the next login auto-starts
|
(`~/.local/state/nomarchy/nightlight-off`) and the unit refuses to (re)start
|
||||||
it and night-light returns to its schedule (off never persists). Remaining
|
while it exists (`Unit.ConditionPathExists=!%h/…`), so an off survives
|
||||||
(optional): (1) **persistent off** — a state marker
|
logout/reboot until toggled back on; `on`/toggle-on remove the marker first
|
||||||
(`~/.local/state/nomarchy/nightlight-off`) the unit honours via
|
(a failed condition would otherwise no-op the start). Without the marker the
|
||||||
`ConditionPathExists=!%h/…`, so a manual off survives logout/reboot until
|
service stays `WantedBy=graphical-session.target` and resumes its schedule at
|
||||||
toggled back; (2) geo (lat/long) auto sunset/sunrise (would mean wlsunset,
|
login as before — the session-scoped behaviour is now the *default*, with
|
||||||
which schedules by location). Pending an on-machine check that stopping
|
persistence opt-in via the toggle. Remaining (optional): geo (lat/long) auto
|
||||||
hyprsunset cleanly restores the gamma.
|
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):**
|
- **Keyboard layouts (per-device + switching):**
|
||||||
- ✓ **Per-device declarative layout:** `nomarchy.keyboard.devices`
|
- ✓ **Per-device declarative layout:** `nomarchy.keyboard.devices`
|
||||||
(`{ "<hyprctl-device-name>" = { layout; variant; }; }`) generates Hyprland
|
(`{ "<hyprctl-device-name>" = { layout; variant; }; }`) generates Hyprland
|
||||||
|
|||||||
@@ -21,6 +21,12 @@ let
|
|||||||
# module hides itself — same pattern as the power-profile indicator.
|
# module hides itself — same pattern as the power-profile indicator.
|
||||||
nomarchy-nightlight = pkgs.writeShellScriptBin "nomarchy-nightlight" ''
|
nomarchy-nightlight = pkgs.writeShellScriptBin "nomarchy-nightlight" ''
|
||||||
unit=hyprsunset.service
|
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
|
if ! systemctl --user cat "$unit" >/dev/null 2>&1; then
|
||||||
[ "''${1:-}" = status ] && exit 0
|
[ "''${1:-}" = status ] && exit 0
|
||||||
notify-send "Night light" "Not enabled — set nomarchy.nightlight.enable."
|
notify-send "Night light" "Not enabled — set nomarchy.nightlight.enable."
|
||||||
@@ -33,14 +39,14 @@ let
|
|||||||
else
|
else
|
||||||
printf '{"text":"","tooltip":"Night light off (click to enable)","class":"off"}\n'
|
printf '{"text":"","tooltip":"Night light off (click to enable)","class":"off"}\n'
|
||||||
fi ;;
|
fi ;;
|
||||||
on) systemctl --user start "$unit" ;;
|
on) mark_on; systemctl --user start "$unit" ;;
|
||||||
off) systemctl --user stop "$unit" ;;
|
off) mark_off; systemctl --user stop "$unit" ;;
|
||||||
toggle)
|
toggle)
|
||||||
if systemctl --user is-active --quiet "$unit"; then
|
if systemctl --user is-active --quiet "$unit"; then
|
||||||
systemctl --user stop "$unit"
|
mark_off; systemctl --user stop "$unit"
|
||||||
notify-send "Night light off" "Screen back to true colours."
|
notify-send "Night light off" "Screen back to true colours (stays off until re-enabled)."
|
||||||
else
|
else
|
||||||
systemctl --user start "$unit"
|
mark_on; systemctl --user start "$unit"
|
||||||
notify-send "Night light on" "Warm filter follows your schedule."
|
notify-send "Night light on" "Warm filter follows your schedule."
|
||||||
fi ;;
|
fi ;;
|
||||||
*) echo "usage: nomarchy-nightlight [toggle|status|on|off]" >&2; exit 64 ;;
|
*) 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
|
# 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.
|
# can exec it even when night-light is off without the call failing.
|
||||||
home.packages = [ nomarchy-nightlight ];
|
home.packages = [ nomarchy-nightlight ];
|
||||||
|
|||||||
Reference in New Issue
Block a user