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/Brightness.qml13
-rw-r--r--accounts/gkleen@sif/shell/quickshell/Services/InhibitorState.qml22
-rw-r--r--accounts/gkleen@sif/shell/quickshell/Services/MprisProxy.qml8
-rw-r--r--accounts/gkleen@sif/shell/quickshell/Services/NotificationManager.qml151
4 files changed, 191 insertions, 3 deletions
diff --git a/accounts/gkleen@sif/shell/quickshell/Services/Brightness.qml b/accounts/gkleen@sif/shell/quickshell/Services/Brightness.qml
index 87c7c05b..8318df50 100644
--- a/accounts/gkleen@sif/shell/quickshell/Services/Brightness.qml
+++ b/accounts/gkleen@sif/shell/quickshell/Services/Brightness.qml
@@ -23,14 +23,21 @@ Singleton {
23 return val; 23 return val;
24 } 24 }
25 25
26 Component.onCompleted: root.currBrightness = root.calcCurrBrightness()
27 Connections { 26 Connections {
28 target: currFile 27 target: currFile
29 function onLoaded() { root.currBrightness = root.calcCurrBrightness(); } 28 function onLoaded() {
29 const b = root.calcCurrBrightness();
30 if (typeof b !== 'undefined')
31 root.currBrightness = b;
32 }
30 } 33 }
31 Connections { 34 Connections {
32 target: maxFile 35 target: maxFile
33 function onLoaded() { root.currBrightness = root.calcCurrBrightness(); } 36 function onLoaded() {
37 const b = root.calcCurrBrightness();
38 if (typeof b !== 'undefined')
39 root.currBrightness = b;
40 }
34 } 41 }
35 42
36 onCurrBrightnessChanged: { 43 onCurrBrightnessChanged: {
diff --git a/accounts/gkleen@sif/shell/quickshell/Services/InhibitorState.qml b/accounts/gkleen@sif/shell/quickshell/Services/InhibitorState.qml
new file mode 100644
index 00000000..fe48fd7f
--- /dev/null
+++ b/accounts/gkleen@sif/shell/quickshell/Services/InhibitorState.qml
@@ -0,0 +1,22 @@
1pragma Singleton
2
3import Quickshell
4import Custom as Custom
5
6Singleton {
7 id: inhibitorState
8
9 property bool waylandIdleInhibited: false
10 property alias lidSwitchInhibited: lidSwitchInhibitor.enabled
11
12 Custom.SystemdInhibitor {
13 id: lidSwitchInhibitor
14
15 enabled: false
16
17 what: Custom.SystemdInhibitorParams.HandleLidSwitch
18 who: "quickshell"
19 why: "User request"
20 mode: Custom.SystemdInhibitorParams.BlockWeak
21 }
22}
diff --git a/accounts/gkleen@sif/shell/quickshell/Services/MprisProxy.qml b/accounts/gkleen@sif/shell/quickshell/Services/MprisProxy.qml
new file mode 100644
index 00000000..e3ab9755
--- /dev/null
+++ b/accounts/gkleen@sif/shell/quickshell/Services/MprisProxy.qml
@@ -0,0 +1,8 @@
1pragma Singleton
2
3import Quickshell
4import Quickshell.Services.Mpris
5
6Scope {
7 property list<var> players: Mpris.players.values
8}
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}