feat(theme-sync): persistent switch notification so slow switches read as progress

The "Applying theme — rebuilding…" toast used the default timeout, so it
vanished seconds into a multi-minute home-manager switch — leaving the
user with no signal and the impression the selection failed. Now it's
persistent (timeout 0) and all theme notifications share a synchronous
tag, so swaync REPLACES it in place with "Theme applied ✓" (or a critical
failure toast that persists) when the rebuild finishes.

notify() grew persistent/urgency/summary params. Honest indeterminate
feedback — HM exposes no percentage, so no fake progress bar.

Verified: py_compile clean; the full apply→switch→notify path runs end to
end (dummy NOMARCHY_REBUILD). The in-place replacement is visible only in
a real swaync session.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Bernardo Magri
2026-06-13 15:52:41 +01:00
parent 20df0d8a60
commit 084b2a0500
3 changed files with 31 additions and 26 deletions

View File

@@ -309,12 +309,11 @@ close · `SUPER+1..9` workspaces · `Print` region screenshot.
screen, tuigreet/MOTD text, and the `distroId` question (it changes
`DEFAULT_HOSTNAME` and upstream `isNixos` checks — needs a test pass;
nixos-* CLI names stay regardless)
- **Theme-switch feedback:** a switch runs `home-manager switch` (seconds
to minutes), and today the only signal is the notify-send toast
("Applying theme — rebuilding…"). Add a visible progress indicator so a
slow switch never reads as a failed selection — e.g. a spinner/progress
widget from `nomarchy-theme-sync` (it already brackets the rebuild) or a
Waybar/swaync element while the switch runs.
- **Theme-switch feedback:** ✓ the "rebuilding…" notification is now
persistent (timeout 0) and replaced in place by "applied ✓" / failure
via a synchronous tag, so a multi-minute switch never reads as a failed
selection. (An honest indeterminate indicator — HM gives no % — a
literal progress widget would be cosmetic; revisit only if wanted.)
- **Icon themes:** add `icon` to `theme-state.json`, have Stylix/GTK and
rofi (`show-icons`) consume it, and ensure the chosen icon theme is
pulled into the closure per active theme (a dark/light pair, e.g.

View File

@@ -59,10 +59,27 @@ def die(msg: str) -> "None":
sys.exit(1)
def notify(body: str) -> None:
if shutil.which("notify-send"):
subprocess.run(["notify-send", "-a", "Nomarchy", "Nomarchy", body],
capture_output=True)
# All Nomarchy theme notifications share this synchronous tag, so the
# notification daemon (swaync) REPLACES the previous one in place instead
# of stacking — the "rebuilding…" toast becomes the "applied ✓" toast.
NOTIFY_SYNC_TAG = "nomarchy-theme-sync"
def notify(body: str, summary: str = "Nomarchy", *,
persistent: bool = False, urgency: str = "normal") -> None:
"""Desktop notification. persistent (timeout 0) keeps it up for the
whole rebuild so a slow switch never reads as a failed selection;
the success/failure call replaces it via the synchronous tag."""
if shutil.which("notify-send") is None:
return
subprocess.run(
["notify-send", "-a", "Nomarchy",
"-u", urgency,
"-t", "0" if persistent else "5000",
"-h", f"string:x-canonical-private-synchronous:{NOTIFY_SYNC_TAG}",
summary, body],
capture_output=True,
)
# ─── State management ─────────────────────────────────────────────────────
@@ -145,10 +162,13 @@ def run_switch() -> None:
return
log(f"rebuilding: {' '.join(argv)}")
notify("Applying theme — rebuilding the desktop…")
# Persistent (timeout 0): stays up for the whole rebuild — replaced
# in place by the success/failure notification below — so a multi-
# minute switch never looks like it silently failed.
notify("Applying theme — rebuilding the desktop…", persistent=True)
result = subprocess.run(argv) # stream output to the caller's terminal
if result.returncode != 0:
notify("Theme rebuild FAILED — see terminal / journal")
notify("Theme rebuild FAILED — see terminal / journal", urgency="critical")
die("rebuild failed (state file already updated; fix and re-run)")
notify("Theme applied ✓")

14
todo.md
View File

@@ -1,14 +0,0 @@
# Items to do
## one item per commit in the repo
- Let's add some type of progress bar for when the user switch themes? That way we can have a visual feedback instead of the user thinking the selection failed
- Let's add icon themes and make sure each theme selects an icon theme to use (and that the icon theme is pulled for installation)
- Let's install starship or some other tool to make the terminal look nice. We can configure it nicely by default
- We can also add tools and set aliases, for example change cat for bat, grep for ripgrep, etc...
- We can install by default for the user applications to make it a complete desktop workstation, such as vscode, libreoffice, gimp, inkscape, texlivefull. Maybe we should also add a way for the user to "turn off" any of those apps if the user does not want them installed
- Let's tweak the Nomarchy plymouth theme. The logo is too dark and the constrast does not look good with the dark background
- When the machine hibernates the user already needs to type the luks password to resume it. However, the screen gets locked by hyprlock anyway and the user needs to enter the password twice
- Let's have a rofi menu item that shows all the current assigned keybindings
- We can assign SUPER+Space for rofi dmenu and SUPER+m for the main menu.