import QtQuick import Quickshell import Quickshell.Io import Quickshell.Services.Notifications import "../../config" Item { id: root NotificationServer { id: notificationServer imageSupported: true actionsSupported: true bodyMarkupSupported: false onNotification: (notification) => { notification.tracked = true root.onNotificationReceived(notification) } } readonly property ObjectModel notifications: notificationServer.trackedNotifications property int notificationCount: 0 property var lastNotification: null property bool hasCritical: false readonly property string soundDir: Config.configDir + "/assets/sounds" property var _trackedIds: ({}) property var _dismissTimes: ({}) function onNotificationReceived(notification) { _trackedIds[notification.id] = true notificationCount = Object.keys(_trackedIds).length lastNotification = notification if (notification.urgency === NotificationUrgency.Critical) hasCritical = true playSound(notification.urgency) scheduleDismiss(notification) } function playSound(urgency) { var path switch (urgency) { case NotificationUrgency.Low: path = soundDir + "/notification-low.oga" break case NotificationUrgency.Critical: path = soundDir + "/notification-critical.oga" break default: path = soundDir + "/notification-normal.oga" break } soundProc.command = [ "sh", "-c", "pw-play \"" + path + "\" 2>/dev/null || paplay \"" + path + "\" 2>/dev/null || ffplay -nodisp -autoexit \"" + path + "\" 2>/dev/null" ] soundProc.running = true } function scheduleDismiss(notification) { var timeout = notification.expireTimeout if (timeout <= 0) { if (notification.urgency === NotificationUrgency.Critical) timeout = 60 else timeout = 5 } _dismissTimes[notification.id] = Date.now() / 1000 + timeout if (!refreshTimer.running) refreshTimer.running = true } function dismissNotification(notification) { delete _trackedIds[notification.id] delete _dismissTimes[notification.id] notificationCount = Object.keys(_trackedIds).length notification.tracked = false refreshMetadata() } function refreshMetadata() { hasCritical = false lastNotification = null for (var i = 0; i < notifications.count; i++) { var n = notifications.get(i) if (_trackedIds[n.id]) { lastNotification = n if (n.urgency === NotificationUrgency.Critical) hasCritical = true } } if (notificationCount === 0) { hasCritical = false lastNotification = null } } Timer { id: refreshTimer interval: 1000 repeat: true onTriggered: { var now = Date.now() / 1000 for (var id in _dismissTimes) { if (_dismissTimes[id] <= now) { for (var i = 0; i < notifications.count; i++) { var n = notifications.get(i) if (n.id.toString() === id) { dismissNotification(n) break } } } } if (Object.keys(_trackedIds).length === 0) running = false } } Process { id: soundProc running: false } }