Add notifications and notification center

This commit is contained in:
2026-01-22 13:38:54 -08:00
parent 7e93b4afa1
commit add0b3d66f
5 changed files with 351 additions and 3 deletions

152
Notifs.qml Normal file
View File

@@ -0,0 +1,152 @@
import Quickshell
import Quickshell.Services.Notifications
import QtQuick
import QtQuick.Effects
PanelWindow {
id: root
visible: false
anchors {
top: true
right: true
}
color: "transparent"
aboveWindows: true
implicitWidth: 500
implicitHeight: 200
focusable: false
property var font: { family: "Comfortaa" }
Component {
id: notifPopup
Rectangle {
id: notifRect
required property var modelData
y: {
let res = 0;
for (let i = 0; notifsList.children[i] && notifsList.children[i] != this; i++) {
if (!notifsList.children[i].exiting) res += notifsList.children[i].height + 10;
}
return res;
}
Behavior on y { NumberAnimation {
duration: 300
easing.type: Easing.InOutCubic
}}
property bool exiting: false
width: parent?.width ?? 0
height: notifContent.childrenRect.height + 32
radius: 20
color: "#181818"
RectangularShadow {
z: -1
anchors.fill: parent
blur: 12
radius: parent.radius
}
Image {
id: notifIcon
anchors {
verticalCenter: parent.verticalCenter
left: parent.left
leftMargin: 12
}
width: 40
height: 40
source: Quickshell.iconPath(modelData.appIcon, true)
}
Column {
id: notifContent
anchors {
left: parent.left
right: parent.right
top: parent.top
topMargin: 16
leftMargin: 16 + (notifIcon.source == "" ? 0 : 44)
rightMargin: 16
}
spacing: 6
Text {
anchors {
left: parent.left
right: parent.right
}
color: "white"
font.family: "Comfortaa"
font.pixelSize: 16
text: modelData.summary
elide: Text.ElideRight
wrapMode: Text.Wrap
maximumLineCount: 2
}
Text {
anchors {
left: parent.left
right: parent.right
}
color: "white"
font.family: "Comfortaa"
font.pixelSize: 12
text: modelData.body
elide: Text.ElideRight
wrapMode: Text.Wrap
maximumLineCount: 4
}
}
NumberAnimation on x {
running: root.visible
from: root.width
to: 0
duration: 300
easing.type: Easing.OutBack
easing.overshoot: 0.8
}
NumberAnimation on x {
id: exitAnim
running: false
to: parent.parent.width
duration: 300
easing.type: Easing.InCubic
onStarted: exiting = true
onFinished: {
if (notifsList.children.length === 1) {
root.visible = false
root.implicitHeight = 200;
}
notifRect.destroy();
}
}
Timer {
running: true
repeat: false
interval: 5000
onTriggered: exitAnim.start()
}
Component.onCompleted: {
let sumHeight = 40;
for (const notif of notifsList.children) {
sumHeight += notif.height + 6;
}
root.implicitHeight = Math.max(root.implicitHeight, sumHeight);
}
}
}
Item {
id: notifsList
anchors {
fill: parent
margins: 12
leftMargin: 64
}
}
function notify(notif) {
if (notif.lastGeneration) return
root.visible = true;
notifPopup.createObject(notifsList, {modelData: notif});
}
}