nomarchy.system.autoTimezone (off by default): geoclue + automatic- timezoned drive /etc/localtime from your location, so travelling to another zone updates the Waybar clock on its own. Menu-driven, in-flake state (the night-light / keyboard philosophy): the flag is settings.autoTimezone in theme-state.json (git-tracked); a System-menu entry toggles it. Because it's a SYSTEM service — not a user unit it can start/stop instantly like night-light — the toggle (nomarchy-autotimezone, run in a terminal) writes the flag --no-switch then drives `sudo nixos-rebuild` (bakes the service + the time.timeZone override) plus `home-manager switch` (the Waybar-refresh watcher); both sides read the one flag. - modules/nixos/timezone.nix: parses settings.autoTimezone from nomarchy.system.stateFile (like Plymouth), gates geoclue2 + automatic-timezoned, and mkForce-nulls time.timeZone — automatic- timezoned sets it null at normal priority, which collides with the installer's static value (a hard eval error), so force wins and reverts cleanly when disabled. Ships the nomarchy-autotimezone toggle. - modules/home/timezone.nix: a tiny user service watching timedate1's change signal that reloads Waybar (SIGUSR2) on a real zone change, so the clock follows live (Waybar captures the zone at construction). Gated on the same flag via nomarchy.settings.autoTimezone. - rofi menu: "Auto timezone (on/off)" in the System submenu. - option + template example + ROADMAP entry; theme.nix seeds the flag. Eval-verified on (geoclue+daemon on, tz forced null over a static installer value, watcher present) and off (static tz intact, nothing extra); home + system both build green. Needs an on-hardware check (geoclue detection + the SIGUSR2 clock refresh aren't CI-testable). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
88 lines
3.6 KiB
Nix
88 lines
3.6 KiB
Nix
# Automatic timezone detection (opt-in) — the system timezone, and so the
|
|
# Waybar clock, follows your location, so travelling to another zone updates
|
|
# the time on its own. Geoclue feeds `automatic-timezoned`, which drives
|
|
# /etc/localtime at runtime.
|
|
#
|
|
# In-flake state, menu-driven (the keyboard/night-light philosophy): the on/off
|
|
# flag lives in the same theme-state.json under `settings.autoTimezone`
|
|
# (git-tracked, reproducible), written by the System-menu toggle
|
|
# (nomarchy-autotimezone). Because this is a SYSTEM service — not a user unit it
|
|
# can start/stop instantly like night-light — the toggle drives a system rebuild
|
|
# (plus a home switch for the Waybar-refresh watcher in timezone.nix home-side).
|
|
{ config, lib, pkgs, ... }:
|
|
|
|
let
|
|
cfg = config.nomarchy.system;
|
|
|
|
# Read the same state file the rest of the system side uses (Plymouth too),
|
|
# wired by lib.mkFlake. The flag defaults off when the file is absent/sparse.
|
|
state =
|
|
if cfg.stateFile != null
|
|
then builtins.fromJSON (builtins.readFile cfg.stateFile)
|
|
else { };
|
|
stateEnabled = (state.settings or { }).autoTimezone or false;
|
|
|
|
sync = lib.getExe pkgs.nomarchy-theme-sync;
|
|
|
|
# Menu/CLI toggle. Runs as the normal user (it owns the flake checkout +
|
|
# writes the state); sudos only the system switch, like sys-update. Writes
|
|
# the in-flake flag, then rebuilds: the system rebuild bakes the service +
|
|
# the time.timeZone override, the home switch installs/removes the Waybar
|
|
# refresh watcher — both read the same flag we just wrote.
|
|
nomarchy-autotimezone = pkgs.writeShellScriptBin "nomarchy-autotimezone" ''
|
|
set -e
|
|
if [ "$(id -u)" -eq 0 ]; then
|
|
echo "nomarchy-autotimezone: run as your normal user (it sudos the rebuild itself)" >&2
|
|
exit 1
|
|
fi
|
|
flake="''${NOMARCHY_PATH:-$HOME/.nomarchy}"
|
|
|
|
cur=$(${sync} get settings.autoTimezone 2>/dev/null) || cur=false
|
|
case "''${1:-toggle}" in
|
|
on) new=true ;;
|
|
off) new=false ;;
|
|
toggle) case "$cur" in true|True) new=false ;; *) new=true ;; esac ;;
|
|
status) echo "$cur"; exit 0 ;;
|
|
*) echo "usage: nomarchy-autotimezone [toggle|on|off|status]" >&2; exit 64 ;;
|
|
esac
|
|
|
|
${sync} --quiet set settings.autoTimezone "$new" --no-switch
|
|
|
|
if [ "$new" = true ]; then
|
|
notify-send "Auto timezone" "Enabling — rebuilding the system…" 2>/dev/null || true
|
|
else
|
|
notify-send "Auto timezone" "Disabling — rebuilding the system…" 2>/dev/null || true
|
|
fi
|
|
|
|
sudo nixos-rebuild switch --flake "$flake#default"
|
|
home-manager switch --flake "$flake"
|
|
|
|
if [ "$new" = true ]; then
|
|
notify-send "Auto timezone on" "The clock now follows your location." 2>/dev/null || true
|
|
else
|
|
notify-send "Auto timezone off" "Back to the fixed timezone in system.nix." 2>/dev/null || true
|
|
fi
|
|
'';
|
|
in
|
|
{
|
|
config = lib.mkMerge [
|
|
{
|
|
# Shipped unconditionally so the menu can enable the feature even while
|
|
# it's off. Track the in-flake flag; mkDefault so a hand-set
|
|
# nomarchy.system.autoTimezone.enable in system.nix still wins.
|
|
environment.systemPackages = [ nomarchy-autotimezone ];
|
|
nomarchy.system.autoTimezone.enable = lib.mkDefault stateEnabled;
|
|
}
|
|
|
|
(lib.mkIf cfg.autoTimezone.enable {
|
|
services.geoclue2.enable = true;
|
|
services.automatic-timezoned.enable = true;
|
|
# A runtime timezone needs /etc/localtime writable. automatic-timezoned
|
|
# sets time.timeZone = null itself, but the installer writes a static
|
|
# value at normal priority, which would collide (a hard eval error) —
|
|
# mkForce null overrides both and resolves cleanly.
|
|
time.timeZone = lib.mkForce null;
|
|
})
|
|
];
|
|
}
|