Replace mako with quickshell-backed notification daemon

Adds first-party omarchy.notifications service plugin that hosts a
freedesktop notification server and renders popups + a history popup
inside the shell. Uninstalls mako and retargets every helper, keybind,
indicator, and migration entry to the new daemon.

Plugin (default/quickshell/omarchy-shell/plugins/notifications/):
- Service.qml: NotificationServer, popupModel + pendingModel + pastModel
  (two-tier history, see below), DND via PersistentProperties +
  cache-file backstop, image cache for /tmp screenshots, IpcHandler with
  toggleDnd/setDnd/isDnd/showHistory/clear/clearPending/markAllSeen/
  dismissAll/dismissOne/invokeLast/dismiss, per-theme override file
  ~/.config/omarchy/current/theme/notifications.json honoring
  borderColor/backgroundColor/textColor/countdownColor.
- components/NotificationCard.qml: theme-driven card (Color.foreground/
  background/border tokens from Commons/Color.qml), 32x32 icon slot,
  Nerd Font glyph fallback via omarchy-glyph hint, hero image strip
  for screenshot/image-path notifications, hover-pause progress bar,
  uses bar.fontFamily so all surfaces share one font.

Filtering and DND:
- transient hint and CLI-style senders (app_name in notify-send /
  omarchy-action) bypass history but still pop.
- DND only allows omarchy-action toasts and notify-send -u critical
  through; real-app urgency=critical (Discord, Slack, Vesktop) is
  silenced and lands in pending instead.
- Pending vs past split surfaced via tabs in the bar widget popup;
  past tab is auto-pruned at the 15-minute mark.
- Click-to-jump: notifications without a libnotify default action focus
  the matching Hyprland window via class lookup.

Shell host:
- shell.qml: generic first-party service loader (mirrors the existing
  noctalia-compat path) and an alias for the bar so plugins can read
  barSize / barHidden / position for anchoring.
- Commons/Color.qml: parses the theme's hyprland.conf for
  $activeBorderColor so notifications match Hyprland window borders;
  picks the explicit accent= key over the color4= alias.

Bar widget rebase (plugins/bar/widgets/notificationCenter.qml):
- Drops the chunk-1 stub server, binds count/dnd state to the service,
  hosts the history popup via PopupCard so it drops down from the
  notification glyph the same way Quick Settings does.
- Pending/Past tabs, dismiss-individual close X, mark-all-as-seen and
  clear-recent action buttons, theme-driven palette.

Quick Settings rework (plugins/bar/widgets/controlCenter.qml):
- DND tile binds directly to service.doNotDisturb for instant feedback.
- Drops the volume slider (already in audioPanel) and the no-op Theme
  tile; adds a Bluetooth toggle bound to Quickshell.Bluetooth.
- Bigger 44x44 wallet was scaled back to 32x32 for tighter rows.

Notification scripts (bin/omarchy-*):
- omarchy-notification-send: passes glyph as a custom hint instead of
  prepending to the summary; adds -a omarchy-action and -u urgency
  automatically; supports -e/--transient passthrough.
- User-action toasts in the capture / toggle / hyprland / default-*
  scripts and bindings/utilities.lua now tag themselves
  -a omarchy-action so DND treats them as intent-based bypass.
- omarchy-toggle-notification-silencing, omarchy-notification-dismiss,
  default/waybar/indicators/notification-silencing.sh, and the Hyprland
  comma-keybinds all route through omarchy-shell-ipc notifications.
- omarchy-capture-screenshot / -screenrecording set the image-path
  hint properly so the hero-image rendering kicks in.

Mako removal (migrations/1778743515.sh):
- pkill -x mako, systemctl --user stop mako.service, pacman -Rns mako
  (uninstalling deletes /usr/lib/systemd/user/mako.service so D-Bus
  activation can't respawn it). Removes ~/.config/mako/ and the legacy
  toggle file. Restarts quickshell so it claims the bus name.
- Drops mako from install/omarchy-base.packages, autostart.lua,
  install/config/theme.sh + toggles.sh, default/themed/mako.ini.tpl,
  default/mako/, the omarchy-menu Mako restart row, bin/omarchy
  GROUP_DESCRIPTIONS, the settings panel catalogue, and the
  default/omarchy-skill paths table.
- Removed scripts: bin/omarchy-restart-mako,
  bin/omarchy-style-corners-mako.
- bin/omarchy-style-corners summary updated; corner radius for the
  notification card reads ~/.local/state/omarchy/toggles/quickshell-menu.json
  alongside the rest of the shell.
This commit is contained in:
Ryan Hughes
2026-05-14 14:21:07 -04:00
parent a7f8f2495f
commit c101591284
47 changed files with 1780 additions and 413 deletions
@@ -17,6 +17,11 @@ QtObject {
property color background: "#101315"
property color accent: "#cacccc"
property color urgent: "#a55555"
// The theme's Hyprland active border color (`$activeBorderColor` in the
// theme's hyprland.conf). Most themes set this to the accent; some themes
// (e.g. aether, oodle) override it to a neutral. Streamed from the theme
// file alongside colors.toml so notification surfaces stay in sync.
property color border: accent
// Noctalia palette tokens. We map them onto our theme colors.
readonly property color mPrimary: accent
@@ -91,14 +96,32 @@ QtObject {
function loadTheme(raw) {
var lines = String(raw || "").split("\n")
var foundAccent = false
var color4Value = ""
for (var i = 0; i < lines.length; i++) {
var match = lines[i].match(/^\s*([A-Za-z0-9_-]+)\s*=\s*["']?(#[0-9A-Fa-f]{6})/)
if (!match) continue
if (match[1] === "foreground") foreground = match[2]
else if (match[1] === "background") background = match[2]
else if (match[1] === "color4" || match[1] === "accent") accent = match[2]
else if (match[1] === "red") urgent = match[2]
// Prefer the explicit `accent` key; only fall back to color4 when the
// theme doesn't define a separate accent. Aether/oodle/etc define both,
// and color4 appears later in the file so the old single-property
// approach was clobbering accent with color4 (#8274fd purple).
else if (match[1] === "accent") { accent = match[2]; foundAccent = true }
else if (match[1] === "color4") color4Value = match[2]
else if (match[1] === "red" || match[1] === "color1") urgent = match[2]
}
if (!foundAccent && color4Value.length > 0) accent = color4Value
}
// Parse `$activeBorderColor = rgb(XXXXXX)` from the theme's hyprland.conf.
function loadHyprlandTheme(raw) {
var match = String(raw || "").match(/\$activeBorderColor\s*=\s*rgba?\(([0-9A-Fa-f]{6,8})\)/)
if (!match) { border = accent; return }
var hex = match[1]
// rgba() in hyprland is AARRGGBB; strip the AA prefix and use the RGB.
if (hex.length === 8) hex = hex.substring(2)
border = "#" + hex
}
// `omarchy-theme-set` recreates the theme/ directory via rm+mv, which kills
@@ -116,6 +139,14 @@ QtObject {
path: Quickshell.env("HOME") + "/.config/omarchy/current/theme.name"
watchChanges: true
printErrors: false
onFileChanged: themeColorsFile.reload()
onFileChanged: { themeColorsFile.reload(); themeHyprlandFile.reload() }
}
property FileView themeHyprlandFile: FileView {
id: themeHyprlandFile
path: Quickshell.env("HOME") + "/.config/omarchy/current/theme/hyprland.conf"
watchChanges: true
printErrors: false
onLoaded: root.loadHyprlandTheme(text())
onFileChanged: reload()
}
}