148 lines
4.1 KiB
QML
148 lines
4.1 KiB
QML
import QtQuick
|
|
import QtMultimedia
|
|
import Quickshell
|
|
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)
|
|
}
|
|
}
|
|
|
|
property ObjectModel notifications: ObjectModel {}
|
|
property int notificationCount: 0
|
|
property var lastNotification: null
|
|
property bool hasCritical: false
|
|
|
|
readonly property string soundDir: Config.configDir + "/assets/sounds"
|
|
|
|
property var _dismissTimes: ({})
|
|
|
|
function onNotificationReceived(notification) {
|
|
notifications.append(notification)
|
|
notificationCount = notifications.count
|
|
lastNotification = notification
|
|
if (notification.urgency === NotificationUrgency.Critical)
|
|
hasCritical = true
|
|
|
|
playSound(notification.urgency)
|
|
scheduleDismiss(notification)
|
|
}
|
|
|
|
function playSound(urgency) {
|
|
var path
|
|
var vol
|
|
switch (urgency) {
|
|
case NotificationUrgency.Low:
|
|
path = soundDir + "/notification-low.oga"
|
|
vol = 0.35
|
|
break
|
|
case NotificationUrgency.Critical:
|
|
path = soundDir + "/notification-critical.oga"
|
|
vol = 1.0
|
|
break
|
|
default:
|
|
path = soundDir + "/notification-normal.oga"
|
|
vol = 0.7
|
|
break
|
|
}
|
|
|
|
if (player.hasAudio) player.stop()
|
|
player.source = "file://" + path
|
|
audioOutput.volume = vol
|
|
player.play()
|
|
}
|
|
|
|
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) {
|
|
for (var i = 0; i < notifications.count; i++) {
|
|
if (notifications.get(i).id === notification.id) {
|
|
notifications.remove(i)
|
|
break
|
|
}
|
|
}
|
|
notificationCount = notifications.count
|
|
delete _dismissTimes[notification.id]
|
|
if (notificationCount === 0) {
|
|
hasCritical = false
|
|
lastNotification = null
|
|
} else {
|
|
lastNotification = notifications.get(0)
|
|
hasCritical = false
|
|
for (var j = 0; j < notifications.count; j++) {
|
|
if (notifications.get(j).urgency === NotificationUrgency.Critical) {
|
|
hasCritical = true
|
|
break
|
|
}
|
|
}
|
|
}
|
|
notification.tracked = false
|
|
}
|
|
|
|
function dismissById(nid) {
|
|
for (var i = 0; i < notifications.count; i++) {
|
|
var n = notifications.get(i)
|
|
if (n.id === nid) {
|
|
dismissNotification(n)
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
function dismissAll() {
|
|
while (notifications.count > 0) {
|
|
var n = notifications.get(0)
|
|
dismissNotification(n)
|
|
}
|
|
}
|
|
|
|
Timer {
|
|
id: refreshTimer
|
|
interval: 1000
|
|
repeat: true
|
|
onTriggered: {
|
|
var now = Date.now() / 1000
|
|
var toDismiss = []
|
|
for (var i = 0; i < notifications.count; i++) {
|
|
var n = notifications.get(i)
|
|
var t = _dismissTimes[n.id]
|
|
if (t !== undefined && now >= t)
|
|
toDismiss.push(n)
|
|
}
|
|
for (var j = 0; j < toDismiss.length; j++)
|
|
dismissNotification(toDismiss[j])
|
|
if (notifications.count === 0)
|
|
running = false
|
|
}
|
|
}
|
|
|
|
MediaPlayer {
|
|
id: player
|
|
audioOutput: AudioOutput {
|
|
id: audioOutput
|
|
}
|
|
}
|
|
}
|