diff options
| -rw-r--r-- | notifications/Balloons.qml | 25 | ||||
| -rw-r--r-- | notifications/NotificationBalloon.qml | 20 |
2 files changed, 31 insertions, 14 deletions
diff --git a/notifications/Balloons.qml b/notifications/Balloons.qml index 28ffafb..9fa5a85 100644 --- a/notifications/Balloons.qml +++ b/notifications/Balloons.qml @@ -27,21 +27,20 @@ Scope { onTriggered: root.now = Date.now() } - // Which live notifications draw here. Suppression is deliberately here - // and not in the daemon: the drawer lists a notification DND chose not to - // pop, because a list the user opened is not an interruption. - readonly property var visible: (Notify.queue || []).filter(p => { - if (Notify.drawerOpen) return false; - if (p.expires !== 0 && root.now >= p.expires) return false; - if (Notify.snoozeUntil > root.now) return false; - if (Status.dnd && p.urgency !== "critical") return false; - return true; - }) + // The Repeater model is Notify.queue itself, so its identity only changes + // when the daemon rewrites the file, not on the 250ms tick. Expiry and + // snooze are the balloon's own business: the tick reassigns `now`, each + // balloon re-evaluates its visible binding and leaves the column at + // expiry. Rebuilding the model on the tick would recreate every delegate + // (reloading icons, resetting hover) four times a second. + readonly property var live: Notify.queue || [] PanelWindow { id: win - visible: root.visible.length > 0 + // Each balloon hides itself when it expires or is suppressed, so the + // column collapses to zero and the window follows it. + visible: column.implicitHeight > 0 screen: Quickshell.screens.find(s => s.name === "DP-1") ?? Quickshell.screens[0] anchors { bottom: true; right: true } margins { bottom: 12; right: 12 } @@ -60,8 +59,8 @@ Scope { spacing: 8 Repeater { - model: root.visible - NotificationBalloon { notification: modelData } + model: root.live + NotificationBalloon { notification: modelData; now: root.now } } } } diff --git a/notifications/NotificationBalloon.qml b/notifications/NotificationBalloon.qml index dc8072f..e3763da 100644 --- a/notifications/NotificationBalloon.qml +++ b/notifications/NotificationBalloon.qml @@ -16,7 +16,25 @@ import QtQuick Rectangle { id: b - required property var notification + // Neither property is `required` on purpose. A required property makes + // QML create the delegate in its own context, where `modelData` and + // `index` are not defined, so the Repeater's `notification: modelData` + // silently arrives undefined and every binding on it fails. + property var notification + property double now: 0 + + // Driven by the shell's tick. The balloon drops itself once its expiry + // passes, or while a suppression says so: the drawer and snooze withhold + // everything, DND withholds low and normal but still shows critical. The + // drawer lists a notification DND chose not to pop, because a list the + // user opened is not an interruption. + visible: { + if (Notify.drawerOpen) return false; + if (Notify.snoozeUntil > b.now) return false; + if (Status.dnd && b.notification.urgency !== "critical") return false; + if (b.notification.expires !== 0 && b.now >= b.notification.expires) return false; + return true; + } width: parent ? parent.width : 340 implicitHeight: texts.implicitHeight + 20 |
