# Auto time-of-day theme switch (BACKLOG #79, VISION § D). A user timer # runs `nomarchy-state-sync auto` at the configured sunrise and sunset, # which reads settings.autoTheme = { enable, day, night, sunrise, sunset } # from the state file and applies the day or night preset for the current # clock — through the SAME one engine as a manual `apply` (no second # pipeline). # # The trigger times are BAKED into OnCalendar at rebuild (originally this # was a 15-min poll; exact times won on wasted wakeups — Bernardo # 2026-07-18), so a time edit must rebuild: the menu's Sunrise/Sunset # writes run `auto --force`, whose apply is that rebuild. Missed # transitions are covered without polling: Persistent=true catches ones # that pass while powered off, systemd fires elapsed OnCalendar timers on # resume from suspend, and OnStartupSec settles the theme just after # login. The command self-gates (no-op when disabled) and is idempotent # (it only rebuilds when the active theme actually needs to change), so # every extra firing is cheap. # # Install is gated on the state flag (like nomarchy.updates gates on its # enable), so a machine not using the feature carries no timer; enabling # it from the menu (slice 3) writes the flag + rebuilds, which is what # brings the timer into being. { config, lib, pkgs, ... }: let at = config.nomarchy.settings.autoTheme or { }; # "HH:MM" or the fallback — mirrors _hhmm_to_min in nomarchy-state-sync, # so a hand-edited state can't bake an OnCalendar systemd rejects. hhmm = v: fallback: if builtins.isString v && builtins.match "([01][0-9]|2[0-3]):[0-5][0-9]" v != null then v else fallback; in lib.mkIf (at.enable or false) { systemd.user.services.nomarchy-auto-theme = { Unit.Description = "Apply the day/night theme for the current time"; Service = { Type = "oneshot"; # The rebuild (`home-manager switch`) and its tools resolve from the # system + per-user profiles — same PATH shape nomarchy-updates uses. Environment = "PATH=/run/current-system/sw/bin:/etc/profiles/per-user/${config.home.username}/bin"; ExecStart = "${pkgs.nomarchy-state-sync}/bin/nomarchy-state-sync auto"; }; }; systemd.user.timers.nomarchy-auto-theme = { Unit.Description = "Day/night theme switch at sunrise and sunset"; Timer = { OnStartupSec = "1min"; # settle on the right theme shortly after login OnCalendar = [ "*-*-* ${hhmm (at.sunrise or null) "07:00"}:00" # sunrise → day "*-*-* ${hhmm (at.sunset or null) "20:00"}:00" # sunset → night ]; Persistent = true; # catch a transition missed while powered off }; Install.WantedBy = [ "timers.target" ]; }; }