pragma Singleton import QtQml import Quickshell import Quickshell.Services.Notifications Singleton { id: root property bool displayInhibited: false property alias trackedNotifications: server.trackedNotifications readonly property var groups: { function matchesGroupKey(notif, groupKey) { var matches = true; for (const prop in groupKey.test) { if (notif[prop] !== groupKey.test[prop]) { matches = false; break; } } return matches; } var groups = new Map(); var notifs = new Array(); for (const [ix, notif] of server.trackedNotifications.values.entries()) { var didGroup = false; for (const groupKey of root.groupKeys) { if (!matchesGroupKey(notif, groupKey)) continue; const key = JSON.stringify({ "key": groupKey, "values": Object.assign({}, ...(Array.from(groupKey["group-by"]).map(prop => { var res = {}; res[prop] = notif[prop]; return res; }))) }); if (!groups.has(key)) groups.set(key, new Array()); groups.get(key).push({ "ix": ix, "notif": notif }); didGroup = true; break; } if (!didGroup) notifs.push([{ "ix": ix, "notif": notif }]); } notifs.push(...groups.values()); notifs.sort((as, bs) => Math.min(...(as.map(o => o.ix))) - Math.min(...(bs.map(o => o.ix)))); return notifs.map(ns => ns.map(n => n.notif)); } property var groupKeys: [ { "test": { "appName": "Element" }, "group-by": [ "summary" ] } ]; Component { id: expirationTimer QtObject { id: timer required property QtObject parent required property int expirationTime property list data: [ Timer { running: !root.displayInhibited interval: timer.expirationTime onTriggered: timer.parent.expire() } ] } } NotificationServer { id: server bodySupported: true actionsSupported: true actionIconsSupported: true imageSupported: true bodyMarkupSupported: true bodyImagesSupported: true onNotification: notification => { var timeout = notification.expireTimeout * 1000; if (notification.appName == "poweralertd") timeout = 2000; if (timeout > 0) { Object.defineProperty(notification, "expirationTimer", { configurable: true, enumerable: true, writable: true }); notification.expirationTimer = expirationTimer.createObject(notification, { parent: notification, expirationTime: timeout }); } notification.tracked = true; } } }