summaryrefslogtreecommitdiff
path: root/accounts/gkleen@sif/shell/quickshell/Services
diff options
context:
space:
mode:
Diffstat (limited to 'accounts/gkleen@sif/shell/quickshell/Services')
-rw-r--r--accounts/gkleen@sif/shell/quickshell/Services/NotificationManager.qml151
1 files changed, 151 insertions, 0 deletions
diff --git a/accounts/gkleen@sif/shell/quickshell/Services/NotificationManager.qml b/accounts/gkleen@sif/shell/quickshell/Services/NotificationManager.qml
new file mode 100644
index 00000000..001ffcf5
--- /dev/null
+++ b/accounts/gkleen@sif/shell/quickshell/Services/NotificationManager.qml
@@ -0,0 +1,151 @@
1pragma Singleton
2
3import QtQml
4import Quickshell
5import Quickshell.Services.Notifications
6
7Singleton {
8 id: root
9
10 readonly property bool active: !lockscreenActive && !displayInhibited
11 property bool lockscreenActive: false
12 property bool displayInhibited: false
13 property alias trackedNotifications: server.trackedNotifications
14 readonly property var groups: {
15 function matchesGroupKey(notif, groupKey) {
16 var matches = true;
17 for (const prop in groupKey.test) {
18 if (notif[prop] !== groupKey.test[prop]) {
19 matches = false;
20 break;
21 }
22 }
23 return matches;
24 }
25
26 var groups = new Map();
27 var notifs = new Array();
28 for (const [ix, notif] of server.trackedNotifications.values.entries()) {
29 var didGroup = false;
30 for (const groupKey of root.groupKeys) {
31 if (!matchesGroupKey(notif, groupKey))
32 continue;
33
34 const key = JSON.stringify({
35 "key": groupKey,
36 "values": Object.assign({}, ...(Array.from(groupKey["group-by"]).map(prop => {
37 var res = {};
38 res[prop] = notif[prop];
39 return res;
40 })))
41 });
42 if (!groups.has(key))
43 groups.set(key, new Array());
44 groups.get(key).push({ "ix": ix, "notif": notif });
45 didGroup = true;
46 break;
47 }
48
49 if (!didGroup)
50 notifs.push([{ "ix": ix, "notif": notif }]);
51 }
52 notifs.push(...groups.values());
53 notifs.sort((as, bs) => Math.min(...(as.map(o => o.ix))) - Math.min(...(bs.map(o => o.ix))));
54 return notifs.map(ns => ns.map(n => n.notif));
55 }
56
57 property var groupKeys: [
58 { "test": { "appName": "Element" }, "group-by": [ "summary" ] }
59 ];
60
61 property var history: []
62
63 Component {
64 id: expirationTimer
65
66 QtObject {
67 id: timer
68
69 required property QtObject parent
70 required property int expirationTime
71 property list<QtObject> data: [
72 Timer {
73 running: root.active
74 interval: timer.expirationTime
75 onTriggered: timer.parent.expire()
76 }
77 ]
78 }
79 }
80
81 Component {
82 id: notificationLock
83
84 RetainableLock {}
85 }
86
87 readonly property SystemClock clock: SystemClock {
88 precision: SystemClock.Minutes
89 }
90
91 function formatTime(time) {
92 const now = root.clock.date;
93 const diff = now - time;
94 const minutes = Math.ceil(diff / 60000);
95 const hours = Math.floor(minutes / 60);
96
97 if (hours < 1) {
98 if (minutes < 1)
99 return "now";
100 if (minutes == 1)
101 return "1 minute";
102 return `${minutes} minutes`;
103 }
104
105 const nowDate = new Date(now.getFullYear(), now.getMonth(), now.getDate())
106 const timeDate = new Date(time.getFullYear(), time.getMonth(), time.getDate())
107 const days = Math.floor((nowDate - timeDate) / (1000 * 86400))
108
109 const timeStr = time.toLocaleTimeString(Qt.locale(), "HH:mm");
110
111 if (days === 0)
112 return timeStr;
113 if (days === 1)
114 return `yesterday ${timeStr}`;
115
116 const dateStr = time.toLocaleTimeString(Qt.locale(), "YYYY-MM-DD");
117 return `${dateStr} ${timeStr}`;
118 }
119
120 NotificationServer {
121 id: server
122
123 bodySupported: true
124 actionsSupported: true
125 actionIconsSupported: true
126 imageSupported: true
127 bodyMarkupSupported: true
128 bodyImagesSupported: true
129
130 onNotification: notification => {
131 var timeout = notification.expireTimeout * 1000;
132 if (notification.appName == "poweralertd")
133 timeout = 2000;
134 if (timeout > 0) {
135 Object.defineProperty(notification, "expirationTimer", { configurable: true, enumerable: true, writable: true });
136 notification.expirationTimer = expirationTimer.createObject(notification, { parent: notification, expirationTime: timeout });
137 }
138 Object.defineProperty(notification, "receivedTime", { configurable: true, enumerable: true, writable: true });
139 notification.receivedTime = root.clock.date;
140 notification.closed.connect((reason) => server.onNotificationClosed(notification, reason));
141 notification.tracked = true;
142 }
143
144 function onNotificationClosed(notification, reason) {
145 root.history.push({
146 lock: notificationLock.createObject(root, { locked: true, object: notification }),
147 notification: notification
148 });
149 }
150 }
151}