diff options
| author | Danilo M. <danix@danix.xyz> | 2026-09-15 14:54:36 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-09-15 14:54:36 +0200 |
| commit | c0473d87565569202d548eba47279321e287990c (patch) | |
| tree | 2f869d1330da836addd8e373a81ee2e96ac3c376 | |
| parent | 708eeda25d3d6e47afaa75fbb77a162cb3c1ff09 (diff) | |
| download | quickshell-c0473d87565569202d548eba47279321e287990c.tar.gz quickshell-c0473d87565569202d548eba47279321e287990c.zip | |
fix(notifications): apply final review fixes
Mirror the balloon's right-click close-all on the drawer row: the spec says
the gestures are identical in both forms, and a right-click on a row
previously did nothing. The right-button branch precedes the live guard so it
behaves the same on history rows.
Stop importing the Status singleton into the notification shell. Referencing
it instantiated it, and its onPresentationChanged writes status.dnd and runs
breaktimer.sh, so a read-only consumer was writing state and shelling out on
every presentation toggle, and doubled the dndBeforePresentation race. Notify
now reads "/run/user/<uid>/status.dnd" directly through a FileView, the same
convention as the notifyd files; a missing file means off.
AGENTS.md named Drawer.qml as the drawer's reserved space; it is
desktop/NotificationList.qml.
| -rw-r--r-- | AGENTS.md | 2 | ||||
| -rw-r--r-- | desktop/NotificationRow.qml | 7 | ||||
| -rw-r--r-- | notifications/NotificationBalloon.qml | 2 | ||||
| l--------- | notifications/Status.qml | 1 | ||||
| -rw-r--r-- | shared/Notify.qml | 18 |
5 files changed, 26 insertions, 4 deletions
@@ -240,7 +240,7 @@ changing that component. The ones that generalise: is not an interruption. - **A notification appears as a balloon or in the drawer's reserved space, never both.** The drawer writes `notifyd/drawer` and the balloon shell reads - it; `Drawer.qml`'s reserved `Item` is the space. + it; `desktop/NotificationList.qml` is the space. - **The dead `waybar/modules/custom/notification.jsonc` and `waybar/scripts/notifications.py` still shell out to `dunstctl`.** They are not in the live waybar config; do not resurrect them. diff --git a/desktop/NotificationRow.qml b/desktop/NotificationRow.qml index f95f3b4..7aff362 100644 --- a/desktop/NotificationRow.qml +++ b/desktop/NotificationRow.qml @@ -26,8 +26,13 @@ Item { MouseArea { anchors.fill: parent + acceptedButtons: Qt.LeftButton | Qt.RightButton cursorShape: Qt.PointingHandCursor - onClicked: { + onClicked: mouse => { + if (mouse.button === Qt.RightButton) { + Notify.closeAll(); + return; + } if (!row.live) return; const acts = row.notification.actions || []; if (acts.length > 0 && !row.inert) Notify.actions(row.notification.id, acts); diff --git a/notifications/NotificationBalloon.qml b/notifications/NotificationBalloon.qml index e3763da..b8ce0f7 100644 --- a/notifications/NotificationBalloon.qml +++ b/notifications/NotificationBalloon.qml @@ -31,7 +31,7 @@ Rectangle { visible: { if (Notify.drawerOpen) return false; if (Notify.snoozeUntil > b.now) return false; - if (Status.dnd && b.notification.urgency !== "critical") return false; + if (Notify.dnd && b.notification.urgency !== "critical") return false; if (b.notification.expires !== 0 && b.now >= b.notification.expires) return false; return true; } diff --git a/notifications/Status.qml b/notifications/Status.qml deleted file mode 120000 index e7188a3..0000000 --- a/notifications/Status.qml +++ /dev/null @@ -1 +0,0 @@ -../shared/Status.qml
\ No newline at end of file diff --git a/shared/Notify.qml b/shared/Notify.qml index ff07575..897e50b 100644 --- a/shared/Notify.qml +++ b/shared/Notify.qml @@ -39,6 +39,14 @@ Singleton { // Epoch milliseconds; 0 means not snoozing. property double snoozeUntil: 0 + // Read from the status registry's own file rather than from the Status + // singleton. The renderers only read DND; referencing Status here would + // instantiate it, and its onPresentationChanged writes status.dnd and + // shells out to breaktimer.sh, side effects a read-only consumer must not + // trigger. The file is the interface, so reading it directly is the same + // value with none of the write side. + property bool dnd: false + function parseQueue() { try { root.queue = JSON.parse(queueFile.text() || "[]"); } catch (e) { root.queue = []; } @@ -109,6 +117,16 @@ Singleton { } FileView { + id: dndFile + path: (Quickshell.env("XDG_RUNTIME_DIR") || "/tmp") + "/status.dnd" + watchChanges: true + printErrors: false + onFileChanged: reload() + onLoaded: root.dnd = dndFile.text().trim() === "1" + onLoadFailed: root.dnd = false + } + + FileView { id: snoozeFile path: root.dir + "/snooze" watchChanges: true |
