aboutsummaryrefslogtreecommitdiffstats
path: root/notifications
diff options
context:
space:
mode:
Diffstat (limited to 'notifications')
-rw-r--r--notifications/Balloons.qml25
-rw-r--r--notifications/NotificationBalloon.qml20
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