import QtQuick import QtQuick.Layouts import Quickshell.Services.Notifications import "../../config.js" as Config Rectangle { id: root required property var notification signal activated() property bool dismissing: false Layout.fillWidth: true implicitHeight: body.implicitHeight + 20 radius: Config.blockRadius color: Config.barBackground border.width: 1 border.color: Config.notificationBorder x: dismissing ? Config.notificationSlideDistance : 0 opacity: dismissing ? 0 : 1 Component.onCompleted: { x = Config.notificationSlideDistance opacity = 0 enterAnimation.start() if (notification.urgency !== NotificationUrgency.Critical) dismissTimer.start() } Timer { id: dismissTimer interval: Config.notificationTimeout repeat: false onTriggered: { dismiss() } } function dismiss() { if (dismissing) return dismissTimer.stop() dismissing = true exitAnimation.start() } SequentialAnimation { id: enterAnimation ParallelAnimation { NumberAnimation { target: root property: "x" from: Config.notificationSlideDistance to: 0 duration: Config.notificationAnimationDuration easing.type: Easing.OutCubic } NumberAnimation { target: root property: "opacity" from: 0 to: 1 duration: Config.notificationAnimationDuration easing.type: Easing.OutCubic } } } SequentialAnimation { id: exitAnimation ParallelAnimation { NumberAnimation { target: root property: "x" to: Config.notificationSlideDistance duration: Config.notificationAnimationDuration easing.type: Easing.InCubic } NumberAnimation { target: root property: "opacity" to: 0 duration: Config.notificationAnimationDuration easing.type: Easing.InCubic } } ScriptAction { script: root.notification.expire() } } ColumnLayout { id: body anchors.fill: parent anchors.margins: 10 spacing: 6 RowLayout { Layout.fillWidth: true Image { visible: root.notification.appIcon !== "" source: root.notification.appIcon sourceSize.width: 24 sourceSize.height: 24 Layout.preferredWidth: 24 Layout.preferredHeight: 24 fillMode: Image.PreserveAspectFit asynchronous: true } Text { Layout.fillWidth: true text: root.notification.appName || "Notification" color: Config.textPrimary font.family: Config.fontFamily font.pixelSize: 12 font.bold: true elide: Text.ElideRight } Text { text: "×" color: "#6c7086" font.family: Config.fontFamily font.pixelSize: 18 font.bold: true MouseArea { anchors.fill: parent cursorShape: Qt.PointingHandCursor onClicked: { root.dismiss() } } } } Text { Layout.fillWidth: true text: root.notification.summary color: Config.textPrimary font.family: Config.fontFamily font.pixelSize: Config.fontSize font.bold: true wrapMode: Text.Wrap } Text { visible: root.notification.body !== "" Layout.fillWidth: true text: root.notification.body color: Config.textSecondary font.family: Config.fontFamily font.pixelSize: 12 wrapMode: Text.Wrap maximumLineCount: 4 elide: Text.ElideRight } Rectangle { Layout.fillWidth: true Layout.preferredHeight: 3 radius: 2 gradient: Gradient { GradientStop { position: 0.0 color: Config.accentGreen } GradientStop { position: 0.33 color: Config.accentYellow } GradientStop { position: 0.66 color: Config.accentOrange } GradientStop { position: 1.0 color: Config.accentRed } } } } MouseArea { anchors.fill: parent cursorShape: Qt.PointingHandCursor onClicked: { root.activated() } } MouseArea { anchors.right: parent.right anchors.top: parent.top width: 36 height: 36 z: 10 cursorShape: Qt.PointingHandCursor onClicked: { root.dismiss() } } }