diff --git a/.config/quickshell/modules/notificationPopup/NotificationPopup.qml b/.config/quickshell/modules/notificationPopup/NotificationPopup.qml index f4373f14d..d9941f36f 100644 --- a/.config/quickshell/modules/notificationPopup/NotificationPopup.qml +++ b/.config/quickshell/modules/notificationPopup/NotificationPopup.qml @@ -33,76 +33,80 @@ Scope { } mask: Region { - item: columnLayout + item: listview.contentItem } color: "transparent" implicitWidth: Appearance.sizes.notificationPopupWidth - // Signal handlers to add/remove notifications - Connections { - target: Notifications - function onNotify(notification) { - if (GlobalStates.sidebarRightOpen) { - return - } - // notificationRepeater.model = [notification, ...notificationRepeater.model] - const notif = root.notifComponent.createObject(columnLayout, { - notificationObject: notification, - popup: true - }); - notificationWidgetList.unshift(notif) + ListView { // Scrollable window + id: listview + anchors.top: parent.top + anchors.bottom: parent.bottom + anchors.horizontalCenter: parent.horizontalCente + implicitWidth: parent.width - Appearance.sizes.elevationMargin * 2 - // Remove stuff from t he column, add back - for (let i = 0; i < notificationWidgetList.length; i++) { - if (notificationWidgetList[i].parent === columnLayout) { - notificationWidgetList[i].parent = null; - } - } + add: Transition { + animations: [ + Appearance.animation.elementMove.numberAnimation.createObject(this, { + properties: "opacity,scale", + from: 0, + to: 1, + }), + ] + } - // Add notification widgets to the column - for (let i = 0; i < notificationWidgetList.length; i++) { - if (notificationWidgetList[i].parent === null) { - notificationWidgetList[i].parent = columnLayout; - } - } + addDisplaced: Transition { + animations: [ + Appearance.animation.elementMove.numberAnimation.createObject(this, { + property: "y", + }), + Appearance.animation.elementMove.numberAnimation.createObject(this, { + properties: "opacity,scale", + to: 1, + }), + ] } - function onDiscard(id) { - for (let i = notificationWidgetList.length - 1; i >= 0; i--) { - const widget = notificationWidgetList[i]; - if (widget && widget.notificationObject && widget.notificationObject.id === id) { - widget.destroyWithAnimation(); - notificationWidgetList.splice(i, 1); - } - } + + displaced: Transition { + animations: [ + Appearance.animation.elementMove.numberAnimation.createObject(this, { + property: "y", + }), + ] } - function onTimeout(id) { - for (let i = notificationWidgetList.length - 1; i >= 0; i--) { - const widget = notificationWidgetList[i]; - if (widget && widget.notificationObject && widget.notificationObject.id === id) { - widget.destroyWithAnimation(); - notificationWidgetList.splice(i, 1); - } - } + move: Transition { + animations: [ + Appearance.animation.elementMove.numberAnimation.createObject(this, { + property: "y", + }), + ] } - function onDiscardAll() { - for (let i = notificationWidgetList.length - 1; i >= 0; i--) { - const widget = notificationWidgetList[i]; - if (widget && widget.notificationObject) { - widget.destroyWithAnimation(); - } - } - notificationWidgetList = []; - } - } - ColumnLayout { // Scrollable window content - id: columnLayout - anchors.horizontalCenter: parent.horizontalCenter - width: parent.width - Appearance.sizes.elevationMargin * 2 - spacing: 0 // The widgets themselves have margins for spacing + remove: Transition { + animations: [ + Appearance.animation.elementMove.numberAnimation.createObject(this, { + property: "x", + to: listview.width, + }), + Appearance.animation.elementMove.numberAnimation.createObject(this, { + property: "opacity", + to: 0, + }) + ] + } - // Notifications are added by the above signal handlers + model: ScriptModel { + values: Notifications.popupList.slice().reverse() + } + delegate: NotificationWidget { + required property var modelData + id: notificationWidget + popup: true + anchors.left: parent?.left + anchors.right: parent?.right + notificationObject: modelData + } } } diff --git a/.config/quickshell/services/Notifications.qml b/.config/quickshell/services/Notifications.qml index 0105d33f4..c2bcc1776 100644 --- a/.config/quickshell/services/Notifications.qml +++ b/.config/quickshell/services/Notifications.qml @@ -12,6 +12,7 @@ Singleton { id: root property var filePath: `${XdgDirectories.cache}/notifications/notifications.json` property var list: [] + property var popupList: [] // Quickshell's notification IDs starts at 1 on each run, while saved notifications // can already contain higher IDs. This is for avoiding id collisions property int idOffset @@ -53,6 +54,7 @@ Singleton { "urgency": notification.urgency.toString(), } root.list = [...root.list, newNotifObject]; + root.popupList = [...root.popupList, newNotifObject]; root.notify(newNotifObject); notifFileView.setText(JSON.stringify(root.list, null, 2)) } @@ -69,6 +71,7 @@ Singleton { if (notifServerIndex !== -1) { notifServer.trackedNotifications.values[notifServerIndex].dismiss() } + root.popupList = root.popupList.filter((notif) => notif.id !== id); root.discard(id); } @@ -83,6 +86,8 @@ Singleton { } function timeoutNotification(id) { + const index = root.list.findIndex((notif) => notif.id === id); + root.popupList = root.popupList.filter((notif) => notif.id !== id); root.timeout(id); } @@ -90,6 +95,7 @@ Singleton { root.list.forEach((notif) => { root.timeout(notif.id); }) + root.popupList = [] } function attemptInvokeAction(id, notifIdentifier) { @@ -100,7 +106,7 @@ Singleton { action.invoke() } // else console.log("Notification not found in server: " + id) - root.discard(id); + // root.discard(id); } function triggerListChange() {