This commit is contained in:
Your Name
2026-07-17 19:57:48 +00:00
parent f11ddfb7fe
commit 880ee3974f
9 changed files with 649 additions and 2 deletions
@@ -0,0 +1,147 @@
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
}
}
}