Files
illogical-impulse/.config/quickshell/modules/common/widgets/NotificationWidget.qml
T
2025-04-19 21:38:33 +02:00

252 lines
9.7 KiB
QML

import "root:/modules/common"
import "root:/services"
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Quickshell
import Quickshell.Widgets
import Quickshell.Services.Notifications
import "./notification_utils.js" as NotificationUtils
Item {
id: root
property var notificationObject
property bool expanded: false
property bool enableAnimation: true
property int notificationListSpacing: 5
property bool ready: false
Layout.fillWidth: true
clip: true
// implicitHeight: notificationRowLayout.implicitHeight
implicitHeight: ready ? notificationRowLayout.implicitHeight + notificationListSpacing : 0
Behavior on implicitHeight {
enabled: enableAnimation
NumberAnimation {
duration: Appearance.animation.elementDecelFast.duration
easing.type: Appearance.animation.elementDecelFast.type
}
}
Component.onCompleted: {
root.ready = true
}
function fancyDestroy() {
implicitHeight = 0
notificationRowWrapper.anchors.top = undefined
notificationRowWrapper.anchors.bottom = root.bottom
destroyTimer.start()
}
Timer {
id: destroyTimer
interval: Appearance.animation.elementDecelFast.duration
repeat: false
onTriggered: {
root.destroy()
}
}
MouseArea { // Middle click to close
anchors.fill: parent
acceptedButtons: Qt.MiddleButton | Qt.RightButton
onClicked: (mouse) => {
if (mouse.button == Qt.MiddleButton)
Notifications.discardNotification(notificationObject.id);
else if (mouse.button == Qt.RightButton)
root.expanded = !root.expanded;
}
}
// Background
Rectangle {
anchors.fill: parent
anchors.topMargin: notificationListSpacing
color: (notificationObject.urgency == NotificationUrgency.Critical) ?
Appearance.mix(Appearance.m3colors.m3secondaryContainer, Appearance.colors.colLayer2, 0.35) : Appearance.colors.colLayer2
radius: Appearance.rounding.normal
}
Item {
id: notificationRowWrapper
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
implicitHeight: notificationRowLayout.implicitHeight + notificationListSpacing
RowLayout {
id: notificationRowLayout
anchors.left: parent.left
anchors.right: parent.right
// anchors.top: parent.top
anchors.bottom: parent.bottom
Rectangle { // App icon
id: iconRectangle
implicitWidth: 47
implicitHeight: 47
Layout.leftMargin: 10
Layout.topMargin: 10
Layout.bottomMargin: 10
Layout.alignment: Qt.AlignTop
Layout.fillWidth: false
radius: Appearance.rounding.full
color: Appearance.m3colors.m3secondaryContainer
MaterialSymbol {
visible: notificationObject.appIcon == ""
text: (notificationObject.urgency == NotificationUrgency.Critical) ? "release_alert" :
NotificationUtils.guessMessageType(notificationObject.summary)
anchors.fill: parent
color: (notificationObject.urgency == NotificationUrgency.Critical) ?
Appearance.mix(Appearance.m3colors.m3onSecondary, Appearance.m3colors.m3onSecondaryContainer, 0.1) :
Appearance.m3colors.m3onSecondaryContainer
font.pixelSize: 27
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
IconImage {
visible: notificationObject.appIcon != ""
anchors.centerIn: parent
implicitSize: 33
asynchronous: true
source: Quickshell.iconPath(notificationObject.appIcon)
}
}
ColumnLayout { // Notification content
spacing: 0
Layout.fillWidth: true
RowLayout { // Row of summary, time and expand button
Layout.topMargin: 10
Layout.leftMargin: 10
Layout.rightMargin: 10
Layout.fillWidth: true
StyledText { // Summary
Layout.fillWidth: true
horizontalAlignment: Text.AlignLeft
font.pixelSize: Appearance.font.pixelSize.normal
color: Appearance.colors.colOnLayer2
text: notificationObject.summary
wrapMode: expanded ? Text.Wrap : Text.NoWrap
elide: Text.ElideRight
}
Item { Layout.fillWidth: true }
StyledText { // Time
id: notificationTimeText
Layout.fillWidth: false
wrapMode: Text.Wrap
horizontalAlignment: Text.AlignLeft
font.pixelSize: Appearance.font.pixelSize.smaller
color: Appearance.m3colors.m3outline
text: NotificationUtils.getFriendlyNotifTimeString(notificationObject.time)
Connections {
target: DateTime
function onTimeChanged() {
notificationTimeText.text = NotificationUtils.getFriendlyNotifTimeString(notificationObject.time)
}
}
}
Button { // Expand button
Layout.alignment: Qt.AlignVCenter
id: expandButton
implicitWidth: 22
implicitHeight: 22
PointingHandInteraction{}
onClicked: {
root.enableAnimation = true
root.expanded = !root.expanded
}
background: Rectangle {
anchors.fill: parent
radius: Appearance.rounding.full
color: (expandButton.down) ? Appearance.colors.colLayer2Active : (expandButton.hovered ? Appearance.colors.colLayer2Hover : Appearance.transparentize(Appearance.colors.colLayer2, 1))
Behavior on color {
ColorAnimation {
duration: Appearance.animation.elementDecel.duration
easing.type: Appearance.animation.elementDecel.type
}
}
}
contentItem: MaterialSymbol {
anchors.centerIn: parent
text: expanded ? "keyboard_arrow_up" : "keyboard_arrow_down"
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
font.pixelSize: Appearance.font.pixelSize.normal
color: Appearance.colors.colOnLayer2
}
}
}
StyledText { // Notification body
Layout.fillWidth: true
Layout.leftMargin: 10
Layout.rightMargin: 10
Layout.bottomMargin: 10
clip: true
wrapMode: expanded ? Text.Wrap : Text.NoWrap
elide: Text.ElideRight
font.pixelSize: Appearance.font.pixelSize.small
horizontalAlignment: Text.AlignLeft
color: Appearance.m3colors.m3outline
// textFormat: Text.MarkdownText
text: notificationObject.body
}
Flickable {
Layout.fillWidth: true
Layout.topMargin: -5
Layout.leftMargin: 10
Layout.rightMargin: 10
Layout.bottomMargin: 10
visible: expanded
implicitHeight: actionRowLayout.implicitHeight
contentWidth: actionRowLayout.implicitWidth
RowLayout { // Actions
id: actionRowLayout
Repeater {
id: actionRepeater
model: notificationObject.actions
NotificationActionButton {
Layout.fillWidth: true
buttonText: modelData.text
urgency: notificationObject.urgency
onClicked: {
Notifications.attemptInvokeAction(notificationObject.id, modelData.identifier);
}
}
}
NotificationActionButton {
Layout.fillWidth: true
buttonText: "Close"
urgency: notificationObject.urgency
onClicked: {
Notifications.discardNotification(notificationObject.id);
}
}
}
}
}
}
}
}