diff options
| author | Danilo M. <danix@danix.xyz> | 2026-09-15 14:25:51 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-09-15 14:25:51 +0200 |
| commit | cb7c95ae7e14249cd9b6d8bba7923713a66eed39 (patch) | |
| tree | 8fd70b27336167bd22caa370e6b482763270a5eb /notifications/Balloons.qml | |
| parent | 9efe9458afdffe474944a04bc2f81864c0eac879 (diff) | |
| download | quickshell-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/Balloons.qml')
| -rw-r--r-- | notifications/Balloons.qml | 25 |
1 files changed, 12 insertions, 13 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 } } } } |
