130 lines
3.7 KiB
QML
130 lines
3.7 KiB
QML
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
|
|
}
|
|
}
|