forked from Shinonome/dots-hyprland
notifications: timeout, prevent some warnings when dismissing notif
This commit is contained in:
@@ -21,7 +21,7 @@ import Quickshell.Services.Notifications
|
||||
Item { // Notification group area
|
||||
id: root
|
||||
property var notificationGroup
|
||||
property var notifications: notificationGroup.notifications
|
||||
property var notifications: notificationGroup?.notifications ?? []
|
||||
property int notificationCount: notifications.length
|
||||
property bool multipleNotifications: notificationCount > 1
|
||||
property bool expanded: false
|
||||
@@ -60,7 +60,9 @@ Item { // Notification group area
|
||||
}
|
||||
onFinished: () => {
|
||||
root.notifications.forEach((notif) => {
|
||||
Notifications.discardNotification(notif.id);
|
||||
Qt.callLater(() => {
|
||||
Notifications.discardNotification(notif.id);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -153,16 +155,16 @@ Item { // Notification group area
|
||||
NotificationAppIcon { // Icons
|
||||
Layout.alignment: Qt.AlignTop
|
||||
Layout.fillWidth: false
|
||||
image: root.multipleNotifications ? "" : notificationGroup.notifications[0].image
|
||||
appIcon: notificationGroup.appIcon
|
||||
summary: notificationGroup.notifications[root.notificationCount - 1].summary
|
||||
image: root?.multipleNotifications ? "" : notificationGroup?.notifications[0]?.image ?? ""
|
||||
appIcon: notificationGroup?.appIcon
|
||||
summary: notificationGroup?.notifications[root.notificationCount - 1]?.summary
|
||||
}
|
||||
|
||||
ColumnLayout { // Content
|
||||
Layout.fillWidth: true
|
||||
spacing: expanded ?
|
||||
((root.multipleNotifications &&
|
||||
notificationGroup.notifications[root.notificationCount - 1].image != "") ? 35 :
|
||||
notificationGroup?.notifications[root.notificationCount - 1].image != "") ? 35 :
|
||||
5) : 0
|
||||
Behavior on spacing {
|
||||
animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this)
|
||||
@@ -176,9 +178,9 @@ Item { // Notification group area
|
||||
|
||||
StyledText {
|
||||
id: appName
|
||||
text: topRow.showAppName ?
|
||||
notificationGroup.appName :
|
||||
notificationGroup.notifications[0].summary
|
||||
text: (topRow.showAppName ?
|
||||
notificationGroup?.appName :
|
||||
notificationGroup?.notifications[0]?.summary) || ""
|
||||
font.pixelSize: topRow.showAppName ?
|
||||
topRow.fontSize :
|
||||
Appearance.font.pixelSize.small
|
||||
@@ -188,7 +190,7 @@ Item { // Notification group area
|
||||
}
|
||||
StyledText {
|
||||
id: timeText
|
||||
text: " • " + NotificationUtils.getFriendlyNotifTimeString(notificationGroup.time)
|
||||
text: " • " + NotificationUtils.getFriendlyNotifTimeString(notificationGroup?.time)
|
||||
font.pixelSize: topRow.fontSize
|
||||
color: Appearance.colors.colSubtext
|
||||
Layout.alignment: Qt.AlignRight
|
||||
|
||||
@@ -60,6 +60,7 @@ function findSuitableMaterialSymbol(summary = "") {
|
||||
* @returns { string }
|
||||
*/
|
||||
const getFriendlyNotifTimeString = (timestamp) => {
|
||||
if (!timestamp) return '';
|
||||
const messageTime = new Date(timestamp);
|
||||
const now = new Date();
|
||||
const oneMinuteAgo = new Date(now.getTime() - 60000);
|
||||
|
||||
@@ -11,11 +11,67 @@ import Qt.labs.platform
|
||||
|
||||
Singleton {
|
||||
id: root
|
||||
component Notif: QtObject {
|
||||
required property int id
|
||||
property Notification notification
|
||||
property list<var> actions: notification?.actions.map((action) => ({
|
||||
"identifier": action.identifier,
|
||||
"text": action.text,
|
||||
})) ?? []
|
||||
property bool popup: false
|
||||
property string appIcon: notification?.appIcon ?? ""
|
||||
property string appName: notification?.appName ?? ""
|
||||
property string body: notification?.body ?? ""
|
||||
property string image: notification?.image ?? ""
|
||||
property string summary: notification?.summary ?? ""
|
||||
property double time
|
||||
property string urgency: notification?.urgency.toString() ?? "normal"
|
||||
property Timer timer
|
||||
}
|
||||
|
||||
function notifToJSON(notif) {
|
||||
return {
|
||||
"id": notif.id,
|
||||
"actions": notif.actions,
|
||||
"appIcon": notif.appIcon,
|
||||
"appName": notif.appName,
|
||||
"body": notif.body,
|
||||
"image": notif.image,
|
||||
"summary": notif.summary,
|
||||
"time": notif.time,
|
||||
"urgency": notif.urgency,
|
||||
}
|
||||
}
|
||||
function notifToString(notif) {
|
||||
return JSON.stringify(notifToJSON(notif), null, 2);
|
||||
}
|
||||
|
||||
component NotifTimer: Timer {
|
||||
required property int id
|
||||
interval: 5000
|
||||
running: true
|
||||
onTriggered: () => {
|
||||
root.timeoutNotification(id);
|
||||
destroy()
|
||||
}
|
||||
}
|
||||
property var filePath: `${XdgDirectories.cache}/notifications/notifications.json`
|
||||
property var list: []
|
||||
property var popupList: []
|
||||
property list<Notif> list: []
|
||||
property var popupList: list.filter((notif) => notif.popup);
|
||||
property bool popupInhibited: GlobalStates?.sidebarRightOpen ?? false
|
||||
property var latestTimeForApp: ({})
|
||||
Component {
|
||||
id: notifComponent
|
||||
Notif {}
|
||||
}
|
||||
Component {
|
||||
id: notifTimerComponent
|
||||
NotifTimer {}
|
||||
}
|
||||
|
||||
function stringifyList(list) {
|
||||
return JSON.stringify(list.map((notif) => notifToJSON(notif)), null, 2);
|
||||
}
|
||||
|
||||
onListChanged: {
|
||||
// Update latest time for each app
|
||||
@@ -85,29 +141,25 @@ Singleton {
|
||||
|
||||
onNotification: (notification) => {
|
||||
notification.tracked = true
|
||||
const newNotifObject = {
|
||||
const newNotifObject = notifComponent.createObject(root, {
|
||||
"id": notification.id + root.idOffset,
|
||||
"actions": notification.actions.map((action) => {
|
||||
return {
|
||||
"identifier": action.identifier,
|
||||
"text": action.text,
|
||||
}
|
||||
}),
|
||||
"appIcon": notification.appIcon,
|
||||
"appName": notification.appName,
|
||||
"body": notification.body,
|
||||
"image": notification.image,
|
||||
"summary": notification.summary,
|
||||
"notification": notification,
|
||||
"time": Date.now(),
|
||||
"urgency": notification.urgency.toString(),
|
||||
}
|
||||
});
|
||||
root.list = [...root.list, newNotifObject];
|
||||
// console.log(root.popupInhibited)
|
||||
|
||||
// Popup
|
||||
if (!root.popupInhibited) {
|
||||
root.popupList = [...root.popupList, newNotifObject];
|
||||
newNotifObject.popup = true;
|
||||
newNotifObject.timer = notifTimerComponent.createObject(root, {
|
||||
"id": newNotifObject.id,
|
||||
"interval": notification.expireTimeout < 0 ? 5000 : notification.expireTimeout,
|
||||
});
|
||||
}
|
||||
|
||||
root.notify(newNotifObject);
|
||||
notifFileView.setText(JSON.stringify(root.list, null, 2))
|
||||
// console.log(notifToString(newNotifObject));
|
||||
notifFileView.setText(stringifyList(root.list));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,20 +168,19 @@ Singleton {
|
||||
const notifServerIndex = notifServer.trackedNotifications.values.findIndex((notif) => notif.id + root.idOffset === id);
|
||||
if (index !== -1) {
|
||||
root.list.splice(index, 1);
|
||||
notifFileView.setText(JSON.stringify(root.list, null, 2))
|
||||
notifFileView.setText(stringifyList(root.list));
|
||||
triggerListChange()
|
||||
}
|
||||
if (notifServerIndex !== -1) {
|
||||
notifServer.trackedNotifications.values[notifServerIndex].dismiss()
|
||||
}
|
||||
root.popupList = root.popupList.filter((notif) => notif.id !== id);
|
||||
root.discard(id);
|
||||
}
|
||||
|
||||
function discardAllNotifications() {
|
||||
root.list = []
|
||||
triggerListChange()
|
||||
notifFileView.setText(JSON.stringify(root.list, null, 2))
|
||||
notifFileView.setText(stringifyList(root.list));
|
||||
notifServer.trackedNotifications.values.forEach((notif) => {
|
||||
notif.dismiss()
|
||||
})
|
||||
@@ -138,15 +189,18 @@ Singleton {
|
||||
|
||||
function timeoutNotification(id) {
|
||||
const index = root.list.findIndex((notif) => notif.id === id);
|
||||
root.popupList = root.popupList.filter((notif) => notif.id !== id);
|
||||
if (root.list[index] != null)
|
||||
root.list[index].popup = false;
|
||||
root.timeout(id);
|
||||
}
|
||||
|
||||
function timeoutAll() {
|
||||
root.list.forEach((notif) => {
|
||||
root.popupList.forEach((notif) => {
|
||||
root.timeout(notif.id);
|
||||
})
|
||||
root.popupList = []
|
||||
root.popupList.forEach((notif) => {
|
||||
notif.popup = false;
|
||||
});
|
||||
}
|
||||
|
||||
function attemptInvokeAction(id, notifIdentifier) {
|
||||
@@ -177,7 +231,19 @@ Singleton {
|
||||
path: filePath
|
||||
onLoaded: {
|
||||
const fileContents = notifFileView.text()
|
||||
root.list = JSON.parse(fileContents)
|
||||
root.list = JSON.parse(fileContents).map((notif) => {
|
||||
return notifComponent.createObject(root, {
|
||||
"id": notif.id,
|
||||
"actions": notif.actions,
|
||||
"appIcon": notif.appIcon,
|
||||
"appName": notif.appName,
|
||||
"body": notif.body,
|
||||
"image": notif.image,
|
||||
"summary": notif.summary,
|
||||
"time": notif.time,
|
||||
"urgency": notif.urgency,
|
||||
});
|
||||
});
|
||||
// Find largest id
|
||||
let maxId = 0
|
||||
root.list.forEach((notif) => {
|
||||
@@ -192,7 +258,7 @@ Singleton {
|
||||
if(error == FileViewError.FileNotFound) {
|
||||
console.log("[Notifications] File not found, creating new file.")
|
||||
root.list = []
|
||||
notifFileView.setText(JSON.stringify(root.list))
|
||||
notifFileView.setText(stringifyList(root.list));
|
||||
} else {
|
||||
console.log("[Notifications] Error loading file: " + error)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user