feat(nightlight): menu-driven, in-flake on/off (no ~/.local/state)
Night light is off by default and configured entirely through the menu,
writing into the downstream flake instead of ~/.local/state — so the
choice is git-tracked and reproducible across a clone+rebuild.
Two flags under a new settings.* section of the state file (exposed as
the nomarchy.settings option):
- settings.nightlight.installed — sticky, gates the hyprsunset unit;
nomarchy.nightlight.enable mkDefault-reads it. First enable from the
menu rebuilds to create the unit (the one accepted rebuild).
- settings.nightlight.on — runtime on/off, toggled instantly
(theme-sync set --no-switch + systemctl), no rebuild. An ExecCondition
reads the live flag at session start so an off survives reboot;
splitting it from the sticky flag means a later unrelated rebuild
never undoes an instant-off (no decay).
Drops the ~/.local/state/nomarchy/nightlight-off marker and the
ConditionPathExists hack. theme-sync set now skips the wallpaper
re-apply for non-wallpaper keys, and its rebuild notifications are
generic ("changes" not "theme").
First cut of the broader principle — any user-settable config gets a
menu writer that lands it in the flake; no state outside the checkout.
Docs (README §4, ROADMAP, template) updated to reflect it.
Eval- and round-trip-verified; on-hardware check pending.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
19
README.md
19
README.md
@@ -197,7 +197,7 @@ two tables below are split along exactly that line.
|
|||||||
| `nomarchy.keyboard.variant` | `""` | XKB variant for the session |
|
| `nomarchy.keyboard.variant` | `""` | XKB variant for the session |
|
||||||
| `nomarchy.keyboard.devices` | `{}` | Per-device layout overrides (Hyprland `device` blocks keyed by `hyprctl devices` name) — e.g. an external keyboard with its own layout/variant |
|
| `nomarchy.keyboard.devices` | `{}` | Per-device layout overrides (Hyprland `device` blocks keyed by `hyprctl devices` name) — e.g. an external keyboard with its own layout/variant |
|
||||||
| `nomarchy.keyboard.layouts` | `[]` | Extra candidate layouts; when set, a watcher prompts (rofi) for a layout on a newly-connected keyboard and remembers it per-device |
|
| `nomarchy.keyboard.layouts` | `[]` | Extra candidate layouts; when set, a watcher prompts (rofi) for a layout on a newly-connected keyboard and remembers it per-device |
|
||||||
| `nomarchy.nightlight.enable` | `false` | Scheduled blue-light filter (hyprsunset) — warm at night (`.temperature`, default 4000K) between `.sunset`/`.sunrise`, no shift by day; toggle it on/off from the menu (System › Night light) or the Waybar moon/sun indicator |
|
| `nomarchy.nightlight.enable` | `false` | Scheduled blue-light filter (hyprsunset) — warm at night (`.temperature`, default 4000K) between `.sunset`/`.sunrise`, no shift by day; off by default — enable it from the menu (System › Night light; the first enable rebuilds), then toggle on/off instantly from the menu or the Waybar moon indicator (writes `settings.nightlight.on` in your flake, no rebuild) and it survives reboot, so it stays reproducible |
|
||||||
| `nomarchy.updates.enable` | `false` | Passive update awareness: a background check (`.interval`, default daily) that flags when flake inputs (nixpkgs, the Nomarchy input, …) are behind upstream — and, with Flatpak on, when apps have updates (`.flatpak`) — via a Waybar indicator + notification. Never changes anything; click the indicator to run the upgrade flow |
|
| `nomarchy.updates.enable` | `false` | Passive update awareness: a background check (`.interval`, default daily) that flags when flake inputs (nixpkgs, the Nomarchy input, …) are behind upstream — and, with Flatpak on, when apps have updates (`.flatpak`) — via a Waybar indicator + notification. Never changes anything; click the indicator to run the upgrade flow |
|
||||||
| `nomarchy.hyprland.enable` | `true` | Nomarchy's Hyprland config |
|
| `nomarchy.hyprland.enable` | `true` | Nomarchy's Hyprland config |
|
||||||
| `nomarchy.waybar.enable` | `true` | Nomarchy's Waybar |
|
| `nomarchy.waybar.enable` | `true` | Nomarchy's Waybar |
|
||||||
@@ -292,6 +292,23 @@ imperative; nothing in Nix consumes the path): applied at session start and
|
|||||||
after every switch via a tiny activation hook, cycled instantly with
|
after every switch via a tiny activation hook, cycled instantly with
|
||||||
`bg next`.
|
`bg next`.
|
||||||
|
|
||||||
|
### Config the menu writes (not just themes)
|
||||||
|
|
||||||
|
The in-flake-state model isn't only for appearance. **Feature toggles you flip
|
||||||
|
from the menu are written into a `settings.*` section of the *same* state file**
|
||||||
|
— git-tracked, reproducible, never stashed in `~/.local/state`. The menu is just
|
||||||
|
an ergonomic writer for your flake, so version-controlling your downstream
|
||||||
|
reproduces the machine, settings and all. Where a toggle can take effect without
|
||||||
|
a rebuild it does: the menu writes the key (`--no-switch`) and flips the running
|
||||||
|
service, which reads the *live* flake state at session start, so the choice is
|
||||||
|
both instant and survives reboot.
|
||||||
|
|
||||||
|
**Night light** is the first to use this — enable it from the menu (System ›
|
||||||
|
Night light; the first enable rebuilds to install hyprsunset), then on/off is
|
||||||
|
instant. Internally it's two keys: `settings.nightlight.installed` (sticky —
|
||||||
|
gates the unit, the first enable rebuilds) and `settings.nightlight.on` (the
|
||||||
|
instant on/off). Expect more `nomarchy.*` toggles to migrate to this pattern.
|
||||||
|
|
||||||
### Per-theme app assets (`themes/<slug>/`)
|
### Per-theme app assets (`themes/<slug>/`)
|
||||||
|
|
||||||
Recoloring covers 95% of theming; the rest is one optional assets directory
|
Recoloring covers 95% of theming; the rest is one optional assets directory
|
||||||
|
|||||||
@@ -463,25 +463,34 @@ how to override it. Items marked ✓ are shipped.
|
|||||||
drives the HM `services.hyprsunset` with two time-based profiles
|
drives the HM `services.hyprsunset` with two time-based profiles
|
||||||
(`sunrise` → identity, `sunset` → `temperature`), so hyprsunset handles the
|
(`sunrise` → identity, `sunset` → `temperature`), so hyprsunset handles the
|
||||||
schedule and the on-login state. Active-profile-at-session-start was
|
schedule and the on-login state. Active-profile-at-session-start was
|
||||||
confirmed on hardware (2026-06-18). ✓ **Menu + Waybar toggle:**
|
confirmed on hardware (2026-06-18). ✓ **Menu + Waybar toggle (opt-in,
|
||||||
`nomarchy-nightlight` (in `nightlight.nix`, on PATH) starts/stops the
|
instant, in-flake state):** two git-tracked keys in the state file, both
|
||||||
hyprsunset *service* — `systemctl --user is-active` is the single source of
|
menu-written (exposed via the new `nomarchy.settings` option) —
|
||||||
truth, the screen restores to true colours when stopped, and it forces the
|
`settings.nightlight.installed` (**sticky**: gates the hyprsunset unit;
|
||||||
filter off for colour-sensitive work and back on without touching config. A
|
`nomarchy.nightlight.enable` `mkDefault`-reads it) and
|
||||||
`nomarchy-menu nightlight` entry (System submenu, self-gated on the unit
|
`settings.nightlight.on` (runtime on/off). **Off by default.** The *first*
|
||||||
existing) and a self-gating Waybar `custom/nightlight` indicator (moon = on,
|
enable from the menu writes `installed` and rebuilds to create the unit (the
|
||||||
sun = off; in the generated bar and both summer whole-swaps) drive it.
|
one accepted rebuild); **every toggle after is instant** —
|
||||||
✓ **Persistent off:** a manual `off` now drops a marker
|
`nomarchy-theme-sync set settings.nightlight.on … --no-switch` (atomic +
|
||||||
(`~/.local/state/nomarchy/nightlight-off`) and the unit refuses to (re)start
|
`git add -N`, no rebuild) plus a `systemctl` start/stop. Splitting the sticky
|
||||||
while it exists (`Unit.ConditionPathExists=!%h/…`), so an off survives
|
flag from the on/off is what avoids a **decay** bug: an instant-off writes
|
||||||
logout/reboot until toggled back on; `on`/toggle-on remove the marker first
|
only `on`, so an unrelated later rebuild (e.g. `sys-update`) never drops the
|
||||||
(a failed condition would otherwise no-op the start). Without the marker the
|
unit and "on" stays instant. Persistence across logout/reboot comes from an
|
||||||
service stays `WantedBy=graphical-session.target` and resumes its schedule at
|
`ExecCondition` on the unit (`nomarchy-nightlight should-start`) that reads the
|
||||||
login as before — the session-scoped behaviour is now the *default*, with
|
**live** working-tree on/off at start time — *not* the eval-frozen store copy
|
||||||
persistence opt-in via the toggle. Remaining (optional): geo (lat/long) auto
|
— so an off survives a reboot with no rebuild; a later rebuild bakes the same
|
||||||
|
value. No more `~/.local/state` marker, no marker `ConditionPathExists`. The
|
||||||
|
`nomarchy-menu` System-submenu entry is always shown (current on/off) so the
|
||||||
|
feature can be enabled from the menu; the self-gating Waybar
|
||||||
|
`custom/nightlight` indicator shows the moon while running and hides otherwise.
|
||||||
|
This is the first cut of a broader principle — **any user-settable config
|
||||||
|
gets a menu writer that lands it in the downstream flake; no state lives
|
||||||
|
outside the checkout** (next target: the per-device keyboard-layout memory
|
||||||
|
below, still in `~/.local/state`; then opt-in auto-commit of the flake on
|
||||||
|
each mutation, owned files only). Remaining (optional): geo (lat/long) auto
|
||||||
sunset/sunrise (would mean wlsunset, which schedules by location). Pending an
|
sunset/sunrise (would mean wlsunset, which schedules by location). Pending an
|
||||||
on-machine check (off persisting across reboot, and that stopping hyprsunset
|
on-machine check (first enable rebuilds + comes on; later toggles instant; off
|
||||||
cleanly restores the gamma).
|
persists across reboot via ExecCondition; stopping hyprsunset restores 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
|
||||||
|
|||||||
@@ -1,60 +1,74 @@
|
|||||||
# Night light — a scheduled blue-light filter via hyprsunset (Hyprland's own
|
# Night light — a scheduled blue-light filter via hyprsunset (Hyprland's own
|
||||||
# gamma/temperature tool). Warm at night, identity (no shift) by day;
|
# gamma/temperature tool). Warm at night, identity (no shift) by day; the
|
||||||
# hyprsunset's time-based `profile` entries handle the schedule and pick the
|
# schedule (temperature/sunrise/sunset) is tuned via nomarchy.nightlight.* in
|
||||||
# right state on session start. Opt-in via nomarchy.nightlight.enable.
|
# home.nix and baked into the unit's time-based `profile`.
|
||||||
#
|
#
|
||||||
# The hyprsunset HM service module is provided by home-manager; this only
|
# Off by default and opt-in. Two git-tracked flags in the state file, both
|
||||||
# configures it. Override anything with plain services.hyprsunset.* options.
|
# menu-written (no ~/.local/state):
|
||||||
#
|
# settings.nightlight.installed — does the hyprsunset unit exist? Sticky; the
|
||||||
# nomarchy-nightlight is the menu/Waybar toggle: it starts/stops the hyprsunset
|
# option mkDefault-reads it, so the FIRST enable from the menu rebuilds (to
|
||||||
# *service* (so `systemctl --user is-active` is the single source of truth and
|
# create the unit) and an instant-off is never undone by a later rebuild.
|
||||||
# the screen restores to true colours when stopped), letting you force the
|
# settings.nightlight.on — runtime on/off. Toggled INSTANTLY (write + systemctl,
|
||||||
# filter off for colour-sensitive work and back on without touching the config.
|
# no rebuild); read by the unit's ExecCondition (should-start) at session
|
||||||
|
# start so the choice survives logout/reboot via the *live* state, not the
|
||||||
|
# eval-frozen store copy. A later rebuild bakes the same value (no divergence).
|
||||||
{ config, lib, pkgs, ... }:
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
let
|
let
|
||||||
cfg = config.nomarchy.nightlight;
|
cfg = config.nomarchy.nightlight;
|
||||||
|
s = config.nomarchy.settings.nightlight;
|
||||||
|
sync = lib.getExe config.nomarchy.package;
|
||||||
|
# Runtime-on default for when the `on` key hasn't been written yet (e.g. right
|
||||||
|
# after the first enable). Baked at eval; only used when the live key is absent.
|
||||||
|
onDefault = lib.boolToString s.on;
|
||||||
|
|
||||||
# Toggle/status helper, on PATH so the menu and both the generated and
|
|
||||||
# whole-swap Waybars can drive it by name. Self-gates: when the unit doesn't
|
|
||||||
# exist (night-light not enabled) `status` prints nothing, so the Waybar
|
|
||||||
# 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.
|
# Instant runtime on/off: write the in-flake state WITHOUT a rebuild.
|
||||||
# Present => night-light stays off across logout/reboot until toggled on.
|
write_on() { ${sync} --quiet set settings.nightlight.on "$1" --no-switch; }
|
||||||
# Path is literal (not XDG_STATE_HOME) so it matches the unit's %h check.
|
# First enable: mark the feature installed and REBUILD to create the unit
|
||||||
marker="$HOME/.local/state/nomarchy/nightlight-off"
|
# (the one rebuild we accept; every toggle after is instant).
|
||||||
mark_off() { mkdir -p "$(dirname "$marker")"; : > "$marker"; }
|
install_feature() { ${sync} --quiet set settings.nightlight.installed true; }
|
||||||
mark_on() { rm -f "$marker"; }
|
# Read the LIVE working-tree on/off (~/.nomarchy via $NOMARCHY_PATH), not the
|
||||||
if ! systemctl --user cat "$unit" >/dev/null 2>&1; then
|
# store copy baked into this generation; fall back to the eval-time default
|
||||||
[ "''${1:-}" = status ] && exit 0
|
# when absent. Normalise Python's True/False bool rendering.
|
||||||
notify-send "Night light" "Not enabled — set nomarchy.nightlight.enable."
|
is_on() {
|
||||||
exit 0
|
v=$(${sync} get settings.nightlight.on 2>/dev/null) || v=${onDefault}
|
||||||
fi
|
case "$v" in true|True) return 0 ;; *) return 1 ;; esac
|
||||||
|
}
|
||||||
|
installed() { systemctl --user cat "$unit" >/dev/null 2>&1; }
|
||||||
|
start() { systemctl --user start "$unit" 2>/dev/null || true; }
|
||||||
|
stop() { systemctl --user stop "$unit" 2>/dev/null || true; }
|
||||||
case "''${1:-toggle}" in
|
case "''${1:-toggle}" in
|
||||||
|
should-start) is_on ;; # ExecCondition gate (login/reboot)
|
||||||
status)
|
status)
|
||||||
if systemctl --user is-active --quiet "$unit"; then
|
# Waybar (polls every 3s): moon while running; print nothing otherwise so
|
||||||
printf '{"text":"","tooltip":"Night light on — warm on schedule (click to disable)","class":"on"}\n'
|
# the module self-hides — enable / re-enable from the System menu.
|
||||||
else
|
systemctl --user is-active --quiet "$unit" \
|
||||||
printf '{"text":"","tooltip":"Night light off (click to enable)","class":"off"}\n'
|
&& printf '{"text":"","tooltip":"Night light on — warm on schedule (click to disable)","class":"on"}\n'
|
||||||
fi ;;
|
exit 0 ;;
|
||||||
on) mark_on; systemctl --user start "$unit" ;;
|
on)
|
||||||
off) mark_off; systemctl --user stop "$unit" ;;
|
if installed; then write_on true; start; else install_feature; start; fi ;;
|
||||||
|
off) write_on false; stop ;;
|
||||||
toggle)
|
toggle)
|
||||||
if systemctl --user is-active --quiet "$unit"; then
|
if systemctl --user is-active --quiet "$unit"; then
|
||||||
mark_off; systemctl --user stop "$unit"
|
write_on false; stop # on -> off (instant)
|
||||||
notify-send "Night light off" "Screen back to true colours (stays off until re-enabled)."
|
elif installed; then
|
||||||
|
write_on true; start # installed, off -> on (instant)
|
||||||
else
|
else
|
||||||
mark_on; systemctl --user start "$unit"
|
install_feature; start # first enable (rebuilds)
|
||||||
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|should-start]" >&2; exit 64 ;;
|
||||||
esac
|
esac
|
||||||
'';
|
'';
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
config = {
|
config = {
|
||||||
|
# Unit presence tracks the sticky `installed` flag the menu writes (first
|
||||||
|
# enable rebuilds). mkDefault so a hand-set nomarchy.nightlight.enable in
|
||||||
|
# home.nix also works as a declarative opt-in.
|
||||||
|
nomarchy.nightlight.enable = lib.mkDefault s.installed;
|
||||||
|
|
||||||
services.hyprsunset = lib.mkIf cfg.enable {
|
services.hyprsunset = lib.mkIf cfg.enable {
|
||||||
enable = true;
|
enable = true;
|
||||||
settings.profile = [
|
settings.profile = [
|
||||||
@@ -65,15 +79,12 @@ in
|
|||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
# Persistent off: a manual `off` drops ~/.local/state/nomarchy/nightlight-off,
|
# Gate the unit on the LIVE on/off state at start time (login/reboot), not
|
||||||
# and this Condition makes the unit refuse to (re)start while it exists — so
|
# at eval time — so a menu toggle (written without a rebuild) is honoured on
|
||||||
# an off survives logout/reboot. `nomarchy-nightlight on` removes it first
|
# the next session. A failed condition skips the unit (inactive, not failed).
|
||||||
# (a failed condition would otherwise no-op the start). %h = $HOME.
|
systemd.user.services.hyprsunset.Service.ExecCondition =
|
||||||
systemd.user.services.hyprsunset.Unit.ConditionPathExists =
|
lib.mkIf cfg.enable "${nomarchy-nightlight}/bin/nomarchy-nightlight should-start";
|
||||||
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 ];
|
home.packages = [ nomarchy-nightlight ];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -255,6 +255,17 @@ in
|
|||||||
description = "The parsed theme state (stateFile merged over defaults).";
|
description = "The parsed theme state (stateFile merged over defaults).";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
settings = lib.mkOption {
|
||||||
|
type = lib.types.attrs;
|
||||||
|
readOnly = true;
|
||||||
|
description = ''
|
||||||
|
Parsed feature settings — the `settings` section of the state file,
|
||||||
|
what the menu/Waybar toggles write (e.g. settings.nightlight.enable).
|
||||||
|
Feature options mkDefault-read from here, so a menu toggle lands in the
|
||||||
|
in-flake state (git-tracked, reproducible) rather than ~/.local/state.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
lib = lib.mkOption {
|
lib = lib.mkOption {
|
||||||
type = lib.types.attrs;
|
type = lib.types.attrs;
|
||||||
readOnly = true;
|
readOnly = true;
|
||||||
|
|||||||
@@ -370,8 +370,10 @@ ${themeRows}
|
|||||||
&& row "Audio" audio-volume-high
|
&& row "Audio" audio-volume-high
|
||||||
command -v system-config-printer >/dev/null 2>&1 && row "Printers" printer
|
command -v system-config-printer >/dev/null 2>&1 && row "Printers" printer
|
||||||
row "Do Not Disturb" notification-disabled
|
row "Do Not Disturb" notification-disabled
|
||||||
systemctl --user cat hyprsunset.service >/dev/null 2>&1 \
|
if systemctl --user is-active --quiet hyprsunset.service 2>/dev/null
|
||||||
&& row "Night light" weather-clear-night
|
then row "Night light (on)" weather-clear-night
|
||||||
|
else row "Night light (off)" weather-clear-night
|
||||||
|
fi
|
||||||
command -v nomarchy-snapshots >/dev/null 2>&1 && row "Snapshots" timeshift
|
command -v nomarchy-snapshots >/dev/null 2>&1 && row "Snapshots" timeshift
|
||||||
if [ -e "''${bats[0]}" ] && command -v powerprofilesctl >/dev/null 2>&1; then
|
if [ -e "''${bats[0]}" ] && command -v powerprofilesctl >/dev/null 2>&1; then
|
||||||
row "Power profile" preferences-system-power
|
row "Power profile" preferences-system-power
|
||||||
|
|||||||
@@ -54,6 +54,12 @@ let
|
|||||||
# tone for kanagawa/summer-*). Each preset declares its own so a theme
|
# tone for kanagawa/summer-*). Each preset declares its own so a theme
|
||||||
# switch always replaces it (deep_merge would otherwise leave it stuck).
|
# switch always replaces it (deep_merge would otherwise leave it stuck).
|
||||||
border = { active = "accent"; inactive = "overlay"; };
|
border = { active = "accent"; inactive = "overlay"; };
|
||||||
|
|
||||||
|
# Non-appearance feature settings the menu writes into this same in-flake
|
||||||
|
# state. nomarchy.nightlight: `installed` (sticky — gates the unit, so the
|
||||||
|
# first enable rebuilds) and `on` (instant runtime on/off). Defaulted so a
|
||||||
|
# sparse/older state file still evaluates; nomarchy.settings exposes them.
|
||||||
|
settings.nightlight = { installed = false; on = true; };
|
||||||
};
|
};
|
||||||
|
|
||||||
parsed = lib.recursiveUpdate defaults themeState;
|
parsed = lib.recursiveUpdate defaults themeState;
|
||||||
@@ -78,6 +84,11 @@ in
|
|||||||
config = {
|
config = {
|
||||||
nomarchy.theme = parsed // { inherit iconTheme border; };
|
nomarchy.theme = parsed // { inherit iconTheme border; };
|
||||||
|
|
||||||
|
# Feature toggles the menu writes (settings.nightlight.enable, …), exposed
|
||||||
|
# alongside the appearance state. Feature modules mkDefault-read from here
|
||||||
|
# so a menu toggle lands in the flake instead of in ~/.local/state.
|
||||||
|
nomarchy.settings = parsed.settings;
|
||||||
|
|
||||||
nomarchy.lib = {
|
nomarchy.lib = {
|
||||||
# "#7aa2f7" -> "rgb(7aa2f7)" (Hyprland color syntax)
|
# "#7aa2f7" -> "rgb(7aa2f7)" (Hyprland color syntax)
|
||||||
rgb = c: "rgb(${lib.removePrefix "#" c})";
|
rgb = c: "rgb(${lib.removePrefix "#" c})";
|
||||||
|
|||||||
@@ -131,9 +131,11 @@ let
|
|||||||
on-click = "nomarchy-powerprofile-cycle";
|
on-click = "nomarchy-powerprofile-cycle";
|
||||||
};
|
};
|
||||||
|
|
||||||
# Night-light (hyprsunset) toggle + state. Self-gates: hidden unless
|
# Night-light (hyprsunset) indicator. Self-gates: the moon shows only while
|
||||||
# nomarchy.nightlight is enabled (the status helper prints nothing then).
|
# the schedule runs; otherwise the status helper prints nothing => hidden
|
||||||
# Click starts/stops the schedule; moon = on, sun = off.
|
# (enable / re-enable from the System menu). Click toggles instantly — writes
|
||||||
|
# the in-flake on/off (settings.nightlight.on, no rebuild) and flips the unit
|
||||||
|
# with systemctl, so the choice lands in the flake and survives reboot.
|
||||||
"custom/nightlight" = {
|
"custom/nightlight" = {
|
||||||
exec = "nomarchy-nightlight status";
|
exec = "nomarchy-nightlight status";
|
||||||
return-type = "json";
|
return-type = "json";
|
||||||
|
|||||||
@@ -165,12 +165,12 @@ def run_switch() -> None:
|
|||||||
# Persistent (timeout 0): stays up for the whole rebuild — replaced
|
# Persistent (timeout 0): stays up for the whole rebuild — replaced
|
||||||
# in place by the success/failure notification below — so a multi-
|
# in place by the success/failure notification below — so a multi-
|
||||||
# minute switch never looks like it silently failed.
|
# minute switch never looks like it silently failed.
|
||||||
notify("Applying theme — rebuilding the desktop…", persistent=True)
|
notify("Applying changes — rebuilding the desktop…", persistent=True)
|
||||||
result = subprocess.run(argv) # stream output to the caller's terminal
|
result = subprocess.run(argv) # stream output to the caller's terminal
|
||||||
if result.returncode != 0:
|
if result.returncode != 0:
|
||||||
notify("Theme rebuild FAILED — see terminal / journal", urgency="critical")
|
notify("Rebuild FAILED — see terminal / journal", urgency="critical")
|
||||||
die("rebuild failed (state file already updated; fix and re-run)")
|
die("rebuild failed (state file already updated; fix and re-run)")
|
||||||
notify("Theme applied ✓")
|
notify("Changes applied ✓")
|
||||||
# Waybar runs from Hyprland's exec-once (not a systemd unit HM would restart
|
# Waybar runs from Hyprland's exec-once (not a systemd unit HM would restart
|
||||||
# on switch), so nudge the running bar to re-read its freshly rebuilt
|
# on switch), so nudge the running bar to re-read its freshly rebuilt
|
||||||
# config/style. SIGUSR2 = reload; harmless no-op if waybar isn't running.
|
# config/style. SIGUSR2 = reload; harmless no-op if waybar isn't running.
|
||||||
@@ -294,7 +294,11 @@ def cmd_set(args) -> None:
|
|||||||
check_fonts(state)
|
check_fonts(state)
|
||||||
if not args.no_switch:
|
if not args.no_switch:
|
||||||
run_switch()
|
run_switch()
|
||||||
apply_wallpaper(state)
|
# Only wallpaper/theme keys change what swww shows; skip the re-apply
|
||||||
|
# (and its transition) for unrelated keys like ui.* or settings.* so a
|
||||||
|
# gaps tweak or a feature toggle doesn't flash the background.
|
||||||
|
if args.path.split(".")[0] in ("wallpaper", "slug"):
|
||||||
|
apply_wallpaper(state)
|
||||||
|
|
||||||
|
|
||||||
def cmd_get(args) -> None:
|
def cmd_get(args) -> None:
|
||||||
|
|||||||
@@ -16,7 +16,8 @@
|
|||||||
|
|
||||||
# ── Opt-in features — uncomment and tweak to enable ─────────────────
|
# ── Opt-in features — uncomment and tweak to enable ─────────────────
|
||||||
# nomarchy.nightlight = { # scheduled blue-light filter (hyprsunset)
|
# nomarchy.nightlight = { # scheduled blue-light filter (hyprsunset)
|
||||||
# enable = true;
|
# enable = true; # declarative opt-in (or just enable it from
|
||||||
|
# # the menu: System › Night light)
|
||||||
# temperature = 4000; # night warmth in K — lower is warmer
|
# temperature = 4000; # night warmth in K — lower is warmer
|
||||||
# sunset = "20:00";
|
# sunset = "20:00";
|
||||||
# sunrise = "07:00";
|
# sunrise = "07:00";
|
||||||
|
|||||||
@@ -55,5 +55,6 @@
|
|||||||
"terminalOpacity": 0.96,
|
"terminalOpacity": 0.96,
|
||||||
"blur": true,
|
"blur": true,
|
||||||
"shadow": true
|
"shadow": true
|
||||||
}
|
},
|
||||||
|
"settings": {}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user