aboutsummaryrefslogtreecommitdiffstats
path: root/notifications/NotificationBalloon.qml
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-09-15 14:25:51 +0200
committerDanilo M. <danix@danix.xyz>2026-09-15 14:25:51 +0200
commitcb7c95ae7e14249cd9b6d8bba7923713a66eed39 (patch)
tree8fd70b27336167bd22caa370e6b482763270a5eb /notifications/NotificationBalloon.qml
parent9efe9458afdffe474944a04bc2f81864c0eac879 (diff)
downloadquickshell-cb7c95ae7e14249cd9b6d8bba7923713a66eed39.tar.gz
quickshell-cb7c95ae7e14249cd9b6d8bba7923713a66eed39.zip
fix(notifications): keep the balloon model stable across ticks
The Repeater model was a fresh filter of Notify.queue on every 250ms tick because the filter read now, so Qt Quick recreated every balloon delegate four times a second, reloading icons and resetting hover. Model is now Notify.queue itself, and each balloon drops itself at expiry through its own visible binding, driven by the shared tick. Removing required from the balloon's properties is part of the same fix: a required property makes QML create the delegate in its own context, where modelData and index are undefined, so notification: modelData silently arrived undefined once a live queue item was actually drawn.
Diffstat (limited to 'notifications/NotificationBalloon.qml')
-rw-r--r--notifications/NotificationBalloon.qml20
1 files changed, 19 insertions, 1 deletions
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