From dbcb8efd1e9598404d049013204c6b7b57c6a3d9 Mon Sep 17 00:00:00 2001 From: Bernardo Magri Date: Sun, 14 Jun 2026 21:01:11 +0100 Subject: [PATCH] feat(dnd): swaync Do-Not-Disturb toggle + Waybar bell indicator MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds a Do-Not-Disturb story on top of swaync: - Waybar `custom/notification` module via `swaync-client -swb` — streams the notification count + DND state (no polling). Left-click toggles the panel, right-click toggles DND; bell-off glyph + muted color when DND is on, accent when notifications are waiting. - `nomarchy-menu dnd` toggle in the root picker and bound to SUPER+CTRL+D (so it shows in the SUPER+? cheatsheet). Turning DND off confirms with a toast; turning it on is silent — notifications are suppressed and the bell-off icon is the cue. Co-Authored-By: Claude Opus 4.8 --- docs/ROADMAP.md | 10 +++++++--- modules/home/keybinds.nix | 1 + modules/home/rofi.nix | 12 +++++++++++- modules/home/waybar.nix | 34 ++++++++++++++++++++++++++++++++-- 4 files changed, 51 insertions(+), 6 deletions(-) diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index 5e5587f..f73b9e6 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -236,9 +236,13 @@ how to override it. Items marked ✓ are shipped. bind (`hyprctl switchxkblayout` / xkb `grp:` options) and a Waybar indicator for the active layout. Natural follow-on to the LUKS-keymap work — keep the system (console/initrd) and session layouts in sync. -- **Do-Not-Disturb:** a swaync DND toggle (`swaync-client -dn`) wired into - the menu and a Waybar indicator, to silence notifications for - presentations/focus. +- ✓ **Do-Not-Disturb:** swaync DND toggle wired into the menu + (`nomarchy-menu dnd`, in the picker, SUPER+CTRL+D) and a Waybar bell + indicator (`custom/notification` via `swaync-client -swb`: shows the + notification count + DND state, left-click toggles the panel, + right-click toggles DND). Turning DND off confirms with a toast; turning + it on is silent (notifications are suppressed — the bell-off glyph is the + cue). - **Snapshot browse/restore UX:** snapper already takes BTRFS timeline snapshots (`nomarchy.system.snapper`); surface them from the desktop — a rofi menu (or btrfs-assistant) to browse/diff/restore and boot-from- diff --git a/modules/home/keybinds.nix b/modules/home/keybinds.nix index 7b60b1c..a42a852 100644 --- a/modules/home/keybinds.nix +++ b/modules/home/keybinds.nix @@ -47,6 +47,7 @@ { mods = "$mod CTRL"; key = "B"; action = "exec, nomarchy-menu bluetooth"; desc = "Bluetooth"; } { mods = "$mod CTRL"; key = "S"; action = "exec, nomarchy-menu capture"; desc = "Screenshot / capture"; } { mods = "$mod CTRL"; key = "A"; action = "exec, nomarchy-menu ask"; desc = "Ask Claude"; } + { mods = "$mod CTRL"; key = "D"; action = "exec, nomarchy-menu dnd"; desc = "Do Not Disturb toggle"; } # Focus { mods = "$mod"; key = "H"; action = "movefocus, l"; desc = "Focus left"; } diff --git a/modules/home/rofi.nix b/modules/home/rofi.nix index 39b5f0d..4f8c6c4 100644 --- a/modules/home/rofi.nix +++ b/modules/home/rofi.nix @@ -164,6 +164,14 @@ let [ -n "$q" ] || exit 0 exec ${cfg.terminal} -e npx --yes @anthropic-ai/claude-code@latest "$q" ;; + dnd) + # Toggle swaync Do-Not-Disturb (-d prints the new state). With DND + # on, notifications are suppressed — the Waybar bell-off icon is the + # cue — so only confirm with a toast when turning it back off. + [ "$(swaync-client -d)" = "false" ] \ + && notify-send "Do Not Disturb off" "Notifications resumed." + exit 0 ;; + "") entries=( "󰀻 Apps" @@ -178,6 +186,7 @@ let "󰄄 Capture" "󰋖 Keybindings" "󰭹 Ask Claude" + "󰂛 Do Not Disturb" ) # Power-profile picker only when this is a laptop (battery present) # running power-profiles-daemon — matches the Waybar indicator's @@ -201,12 +210,13 @@ let *Capture*) exec "$0" capture ;; *Keybindings*) exec "$0" keybinds ;; *Ask*) exec "$0" ask ;; + *"Do Not Disturb"*) exec "$0" dnd ;; *"Power profile"*) exec "$0" power-profile ;; *Power*) exec "$0" power ;; esac ;; *) - echo "usage: nomarchy-menu [power|power-profile|theme|clipboard|calc|files|emoji|web|network|bluetooth|capture|keybinds|ask]" >&2 + echo "usage: nomarchy-menu [power|power-profile|theme|clipboard|calc|files|emoji|web|network|bluetooth|capture|keybinds|ask|dnd]" >&2 exit 64 ;; esac ''; diff --git a/modules/home/waybar.nix b/modules/home/waybar.nix index 0cf1f59..5a670ce 100644 --- a/modules/home/waybar.nix +++ b/modules/home/waybar.nix @@ -66,7 +66,7 @@ let modules-left = [ "hyprland/workspaces" "hyprland/window" ]; modules-center = [ "clock" ]; - modules-right = [ "tray" "pulseaudio" "network" "cpu" "memory" "custom/powerprofile" "battery" ]; + modules-right = [ "tray" "pulseaudio" "network" "cpu" "memory" "custom/powerprofile" "battery" "custom/notification" ]; "hyprland/workspaces" = { format = "{icon}"; @@ -118,6 +118,31 @@ let on-click = "${powerProfileCycle}"; }; + # swaync notification bell + Do-Not-Disturb state. `-swb` streams JSON + # (text/tooltip/class) on every change, so it tracks count and DND with + # no polling. Left-click toggles the panel; right-click toggles DND. + # The `dnd-*` classes (bell-off glyph) are styled muted below. + "custom/notification" = { + exec = "swaync-client -swb"; + return-type = "json"; + exec-if = "which swaync-client"; + format = "{icon}"; + format-icons = { + none = "󰂜"; + notification = "󰂚"; + dnd-none = "󰂛"; + dnd-notification = "󰂛"; + inhibited-none = "󰂜"; + inhibited-notification = "󰂚"; + dnd-inhibited-none = "󰂛"; + dnd-inhibited-notification = "󰂛"; + }; + on-click = "swaync-client -t -sw"; + on-click-right = "swaync-client -d -sw"; + tooltip = true; + escape = true; + }; + tray.spacing = 8; }; @@ -164,11 +189,16 @@ let font-weight: bold; } - #tray, #pulseaudio, #network, #cpu, #memory, #custom-powerprofile, #battery { + #tray, #pulseaudio, #network, #cpu, #memory, #custom-powerprofile, #battery, #custom-notification { color: @subtext; padding: 0 10px; } + /* notifications waiting → accent; Do-Not-Disturb → muted bell-off */ + #custom-notification.notification { color: @accent; } + #custom-notification.dnd-none, + #custom-notification.dnd-notification { color: @muted; } + #pulseaudio.muted { color: @muted; } #battery.warning { color: @warn; } #battery.critical { color: @bad; }