feat(timezone): opt-in automatic, location-following timezone
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>
This commit is contained in:
@@ -22,7 +22,7 @@ let
|
||||
'';
|
||||
in
|
||||
{
|
||||
imports = [ ./options.nix ./plymouth.nix ./file-manager.nix ./power.nix ./services.nix ./hardware.nix ];
|
||||
imports = [ ./options.nix ./plymouth.nix ./file-manager.nix ./power.nix ./services.nix ./hardware.nix ./timezone.nix ];
|
||||
|
||||
config = {
|
||||
# The safe half of distro branding: distroName flows into
|
||||
|
||||
@@ -46,6 +46,16 @@
|
||||
audio.enable = lib.mkEnableOption "the Pipewire audio stack" // { default = true; };
|
||||
bluetooth.enable = lib.mkEnableOption "Bluetooth support with blueman" // { default = true; };
|
||||
|
||||
autoTimezone.enable = lib.mkEnableOption ''
|
||||
automatic timezone detection (geoclue + automatic-timezoned): the
|
||||
system timezone — and so the Waybar clock — follows your location, so
|
||||
travelling to another zone updates the time on its own. Off by default
|
||||
(it's a location service and needs the network); toggle it from the
|
||||
System menu, which lands the choice in the in-flake state file. Enabling
|
||||
it unsets the static time.timeZone for you (a runtime timezone needs
|
||||
/etc/localtime writable), so the menu toggle drives a system rebuild''
|
||||
// { default = false; };
|
||||
|
||||
snapper.enable = lib.mkEnableOption ''
|
||||
hourly/daily BTRFS timeline snapshots of / via snapper, plus the
|
||||
`nixos-rebuild-snap` pre-rebuild-snapshot helper. No-op unless the
|
||||
|
||||
87
modules/nixos/timezone.nix
Normal file
87
modules/nixos/timezone.nix
Normal file
@@ -0,0 +1,87 @@
|
||||
# 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;
|
||||
})
|
||||
];
|
||||
}
|
||||
Reference in New Issue
Block a user