right sidebar: cleaner notification implementation

This commit is contained in:
end-4
2025-05-22 13:35:38 +02:00
parent 1261d5033e
commit cfc8cc30b6
2 changed files with 74 additions and 84 deletions
@@ -21,7 +21,6 @@ Item {
property bool expanded: false property bool expanded: false
property bool enableAnimation: true property bool enableAnimation: true
property int notificationListSpacing: 5 property int notificationListSpacing: 5
property bool ready: false
property int defaultTimeoutValue: 5000 property int defaultTimeoutValue: 5000
property var notificationXAnimation: Appearance.animation.elementMoveEnter property var notificationXAnimation: Appearance.animation.elementMoveEnter
@@ -29,18 +28,9 @@ Item {
Layout.fillWidth: true Layout.fillWidth: true
clip: !popup clip: !popup
implicitHeight: ready ? notificationColumnLayout.implicitHeight + notificationListSpacing : 0 implicitHeight: notificationColumnLayout.implicitHeight + notificationListSpacing
Behavior on implicitHeight {
enabled: enableAnimation
NumberAnimation {
duration: Appearance.animation.elementMoveFast.duration
easing.type: Appearance.animation.elementMoveFast.type
easing.bezierCurve: Appearance.animation.elementMoveFast.bezierCurve
}
}
Component.onCompleted: { Component.onCompleted: {
root.ready = true
if (popup) timeoutTimer.start() if (popup) timeoutTimer.start()
} }
@@ -89,7 +79,6 @@ Item {
onTriggered: { onTriggered: {
notificationRowWrapper.anchors.top = undefined notificationRowWrapper.anchors.top = undefined
notificationRowWrapper.anchors.bottom = root.bottom notificationRowWrapper.anchors.bottom = root.bottom
implicitHeight = 0
destroyTimer2.start() destroyTimer2.start()
} }
} }
@@ -99,7 +88,7 @@ Item {
interval: Appearance.animation.elementMoveFast.duration interval: Appearance.animation.elementMoveFast.duration
repeat: false repeat: false
onTriggered: { onTriggered: {
root.destroy() Notifications.discardNotification(notificationObject.id);
} }
} }
@@ -109,7 +98,7 @@ Item {
acceptedButtons: Qt.LeftButton | Qt.MiddleButton | Qt.RightButton acceptedButtons: Qt.LeftButton | Qt.MiddleButton | Qt.RightButton
onClicked: (mouse) => { onClicked: (mouse) => {
if (mouse.button == Qt.MiddleButton) if (mouse.button == Qt.MiddleButton)
Notifications.discardNotification(notificationObject.id); root.destroyWithAnimation()
else if (mouse.button == Qt.RightButton) else if (mouse.button == Qt.RightButton)
root.toggleExpanded() root.toggleExpanded()
} }
@@ -141,7 +130,7 @@ Item {
if (mouse.button === Qt.LeftButton) { if (mouse.button === Qt.LeftButton) {
if (notificationRowWrapper.x > dragConfirmThreshold) { if (notificationRowWrapper.x > dragConfirmThreshold) {
root.notificationXAnimation = Appearance.animation.elementMoveEnter root.notificationXAnimation = Appearance.animation.elementMoveEnter
Notifications.discardNotification(notificationObject.id); root.destroyWithAnimation()
} else { } else {
// Animate back if not far enough // Animate back if not far enough
root.notificationXAnimation = Appearance.animation.elementMoveFast root.notificationXAnimation = Appearance.animation.elementMoveFast
@@ -583,7 +572,7 @@ Item {
(contentItem.implicitWidth + leftPadding + rightPadding) (contentItem.implicitWidth + leftPadding + rightPadding)
onClicked: { onClicked: {
Notifications.discardNotification(notificationObject.id); root.destroyWithAnimation()
} }
contentItem: MaterialSymbol { contentItem: MaterialSymbol {
@@ -5,67 +5,14 @@ import Qt5Compat.GraphicalEffects
import QtQuick import QtQuick
import QtQuick.Controls import QtQuick.Controls
import QtQuick.Layouts import QtQuick.Layouts
import Quickshell
import Quickshell.Widgets import Quickshell.Widgets
Item { Item {
id: root id: root
property Component notifComponent: NotificationWidget {}
property list<NotificationWidget> notificationWidgetList: []
// Signal handlers to add/remove notifications ListView { // Scrollable window
Connections { id: listview
target: Notifications
function onInitDone() {
// notificationRepeater.model = Notifications.list.slice().reverse()
Notifications.list.slice().reverse().forEach((notification) => {
const notif = root.notifComponent.createObject(columnLayout, { notificationObject: notification });
notificationWidgetList.push(notif)
})
}
function onNotify(notification) {
// notificationRepeater.model = [notification, ...notificationRepeater.model]
const notif = root.notifComponent.createObject(columnLayout, { notificationObject: notification });
notificationWidgetList.unshift(notif)
// 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 notification widgets to the column
for (let i = 0; i < notificationWidgetList.length; i++) {
if (notificationWidgetList[i].parent === null) {
notificationWidgetList[i].parent = columnLayout;
}
}
}
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);
}
}
}
function onDiscardAll() {
for (let i = notificationWidgetList.length - 1; i >= 0; i--) {
const widget = notificationWidgetList[i];
if (widget && widget.notificationObject) {
widget.destroyWithAnimation();
}
}
notificationWidgetList = [];
}
}
Flickable { // Scrollable window
id: flickable
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
anchors.top: parent.top anchors.top: parent.top
@@ -76,28 +23,82 @@ Item {
layer.enabled: true layer.enabled: true
layer.effect: OpacityMask { layer.effect: OpacityMask {
maskSource: Rectangle { maskSource: Rectangle {
width: flickable.width width: listview.width
height: flickable.height height: listview.height
radius: Appearance.rounding.normal radius: Appearance.rounding.normal
} }
} }
ColumnLayout { // Scrollable window content add: Transition {
id: columnLayout animations: [
anchors.left: parent.left Appearance.animation.elementMove.numberAnimation.createObject(this, {
anchors.right: parent.right properties: "opacity,scale",
spacing: 0 // The widgets themselves have margins for spacing from: 0,
to: 1,
}),
]
}
// Notifications are added by the above signal handlers addDisplaced: Transition {
animations: [
Appearance.animation.elementMove.numberAnimation.createObject(this, {
property: "y",
}),
Appearance.animation.elementMove.numberAnimation.createObject(this, {
properties: "opacity,scale",
to: 1,
}),
]
}
displaced: Transition {
animations: [
Appearance.animation.elementMove.numberAnimation.createObject(this, {
property: "y",
}),
]
}
move: Transition {
animations: [
Appearance.animation.elementMove.numberAnimation.createObject(this, {
property: "y",
}),
]
}
remove: Transition {
animations: [
Appearance.animation.elementMove.numberAnimation.createObject(this, {
property: "x",
to: listview.width,
}),
Appearance.animation.elementMove.numberAnimation.createObject(this, {
property: "opacity",
to: 0,
})
]
}
model: ScriptModel {
values: Notifications.list.slice().reverse()
}
delegate: NotificationWidget {
required property var modelData
id: notificationWidget
// anchors.horizontalCenter: parent.horizontalCenter
anchors.left: parent?.left
anchors.right: parent?.right
Layout.fillWidth: true
notificationObject: modelData
} }
} }
// Placeholder when list is empty // Placeholder when list is empty
Item { Item {
anchors.fill: flickable anchors.fill: listview
visible: opacity > 0 visible: opacity > 0
opacity: (root.notificationWidgetList.length === 0) ? 1 : 0 opacity: (Notifications.list.length === 0) ? 1 : 0
Behavior on opacity { Behavior on opacity {
NumberAnimation { NumberAnimation {
@@ -137,9 +138,9 @@ Item {
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
text: `${notificationWidgetList.length} notification${notificationWidgetList.length > 1 ? "s" : ""}` text: `${Notifications.list.length} notifications`
opacity: notificationWidgetList.length > 0 ? 1 : 0 opacity: Notifications.list.length > 0 ? 1 : 0
visible: opacity > 0 visible: opacity > 0
Behavior on opacity { Behavior on opacity {
animation: Appearance.animation.elementMove.numberAnimation.createObject(this) animation: Appearance.animation.elementMove.numberAnimation.createObject(this)