diff --git a/NotificationsWidget.qml b/NotificationsWidget.qml index 676fc49..335d534 100644 --- a/NotificationsWidget.qml +++ b/NotificationsWidget.qml @@ -74,7 +74,7 @@ Item { onClicked: mouse => { if (mouse.button === Qt.RightButton) { - NotificationService.notificationsMuted = !NotificationService.notificationsMuted + NotificationService.manualNotificationsMuted = !NotificationService.manualNotificationsMuted return; } root.createWindow = !root.createWindow; diff --git a/Services/NotificationService.qml b/Services/NotificationService.qml index 0fde000..bdadb00 100644 --- a/Services/NotificationService.qml +++ b/Services/NotificationService.qml @@ -8,14 +8,16 @@ import qs.Widgets import qs.Services Singleton { - id: notificationRoot + id: root readonly property var notificationServer: notificationServer - readonly property var trackedNotifications: notificationServer.trackedNotifications readonly property var notificationsNumber: notificationServer.trackedNotifications.values.length + readonly property var maxShown: 3 - property bool notificationsMuted: HyprlandService.hasFullscreen || HyprlandService.isScreencasting - property ListModel globalList: ListModel {} + property bool receivingLock: false + property bool manualNotificationsMuted: false + property bool notificationsMuted: HyprlandService.hasFullscreen || HyprlandService.isScreencasting || root.manualNotificationsMuted + property ListModel trackedNotifications: ListModel {} NotificationServer { id: notificationServer @@ -25,23 +27,31 @@ Singleton { Connections { target: notificationServer function onNotification(notif) { - if(notif.transient) return; - if (notif.body === "MediaOngoingActivity") - return; + if(notif.transient || notif.body === "MediaOngoingActivity") + return; + notif.tracked = true; - notificationRoot.addNotification(globalList, notif); + root.addNotification(trackedNotifications, notif); if (notif.lastGeneration) - return; + return; // Use the refactored helper - notificationRoot.addNotification(notificationList, notif); + if(notificationList.count < root.maxShown && !root.receivingLock ) { + root.addNotification(notificationList, notif) + } else { + root.receivingLock = true + root.addNotification(pendingList, notif) + } } } ListModel { id: notificationList } + ListModel { + id: pendingList + } /** * @param {ListModel} model @@ -75,7 +85,7 @@ Singleton { // Avoid duplicates for (let i = 0; i < model.count; i++) { if (model.get(i).notif === notif) - return; + return; } model.append({ @@ -87,24 +97,54 @@ Singleton { }); } - // function notificationDismiss(notif) { - // removeNotification(notificationList, notif); - // removeNotification(globalList, notif); - // notif.dismiss(); - // } - function notificationDismiss(notif) { - removeNotification(notificationList, notif); - removeNotification(globalList, notif); + let pendingIdx = -1 + + for (let i = 0; i < pendingList.count; i++) { + if (pendingList.get(i).notif === notif) { + pendingIdx = i + break + } + } + + if (pendingIdx >= 0) { + pendingList.remove(pendingIdx, 1) + } else { + removeNotification(notificationList, notif) + } + + removeNotification(trackedNotifications, notif) if (notif && typeof notif.dismiss === "function") - notif.dismiss(); // dismiss first + notif.dismiss() + tryShowNext() + } + + function timeoutNotification(notif) { + + removeNotification(notificationList, notif) + + tryShowNext() + } + + function tryShowNext() { + let filled = false + + while (notificationList.count < root.maxShown && pendingList.count > 0) { + const nextNotif = pendingList.get(0).notif + pendingList.remove(0, 1) + addNotification(notificationList, nextNotif) + filled = true + } + + // Only lock if there are still more pending than fit onscreen + root.receivingLock = pendingList.count > 0 } LazyLoader { id: popupLoader - active: notificationList.count && !notificationRoot.notificationsMuted + active: notificationList.count && !root.notificationsMuted component: PanelWindow { id: notificationWindow @@ -136,17 +176,17 @@ Singleton { notification: modelData implicitWidth: listView.width - + startTimer: NotificationUrgency.toString(notification?.urgency) === "Critical"? false: true timerDuration: 5000 onDismissed: { if (notification && typeof notification.dismiss === "function") - notificationRoot.notificationDismiss(notification); + root.notificationDismiss(notification); } onTimedout: { - notificationRoot.removeNotification(notificationList, notification) + root.timeoutNotification(notification) } } diff --git a/Widgets/NotificationWindow.qml b/Widgets/NotificationWindow.qml index ab9f684..b6ddaac 100644 --- a/Widgets/NotificationWindow.qml +++ b/Widgets/NotificationWindow.qml @@ -21,8 +21,6 @@ PopupWindow { visible: true signal clear - mask: Region { item: listView } - MouseArea { anchors.fill: parent onClicked: notificationRoot.clear() @@ -57,7 +55,7 @@ PopupWindow { anchors.fill: parent onClicked: { while (NotificationService.notificationsNumber != 0) { - NotificationService.trackedNotifications.values[0].dismiss(); + NotificationService.notificationDismiss(NotificationService.trackedNotifications.get(0).notif) } } } @@ -71,7 +69,7 @@ PopupWindow { id: listView Layout.fillWidth: true Layout.fillHeight: true - model: NotificationService.globalList + model: NotificationService.trackedNotifications clip: true spacing: 5 leftMargin: 10