import QtQuick import QtQuick.Layouts import Quickshell.Services.Notifications import "../../config" as Cfg Item { id: root property string toastId: "" property string appName: "" property string summary: "" property string body: "" property int urgency: NotificationUrgency.Normal property string timeStr: "" property int timeout: 5000 property var t property var urgencyColor: function(u) { return "#ffffff" } property var urgencyIcon: function(u) { return "" } signal dismissed(string toastId) width: parent ? parent.width : 350 height: toastCard.height property real progressVal: 1.0 Timer { interval: root.timeout running: root.timeout > 0 repeat: false onTriggered: root.dismissed(root.toastId) } NumberAnimation on progressVal { from: 1.0; to: 0.0 duration: root.timeout running: root.urgency === NotificationUrgency.Low && root.timeout > 0 } opacity: 0 scale: 0.90 Component.onCompleted: { entranceOp.start() entranceSc.start() } NumberAnimation { id: entranceOp; target: root property: "opacity"; from: 0; to: 1 duration: 240; easing.type: Easing.OutCubic } NumberAnimation { id: entranceSc; target: root property: "scale"; from: 0.90; to: 1.0 duration: 240; easing.type: Easing.OutBack } Rectangle { id: toastCard width: parent.width height: toastContent.implicitHeight + (root.urgency === NotificationUrgency.Low ? 30 : 24) radius: 16 color: cardHover.hovered ? root.t.notifToastBgHover : root.t.notifToastBg border.color: root.urgency === NotificationUrgency.Critical ? root.t.notifUrgencyCritical : (cardHover.hovered ? root.t.notifBorderActive : root.t.notifToastBorder) border.width: Cfg.Config.popupBorderWidth layer.enabled: true Behavior on color { ColorAnimation { duration: 150; easing.type: Easing.OutCubic } } Behavior on border.color { ColorAnimation { duration: 150 } } HoverHandler { id: cardHover } TapHandler { onTapped: root.dismissed(root.toastId) } Rectangle { width: 4 height: Math.max(16, toastCard.height - 24) radius: 2 anchors { left: parent.left leftMargin: 10 verticalCenter: parent.verticalCenter } color: root.urgencyColor(root.urgency) } ColumnLayout { id: toastContent anchors { left: parent.left right: parent.right top: parent.top leftMargin: 24 rightMargin: 12 topMargin: 12 } spacing: 4 RowLayout { Layout.fillWidth: true spacing: 6 Text { text: root.urgencyIcon(root.urgency) color: root.urgencyColor(root.urgency) font.pixelSize: 12 Layout.alignment: Qt.AlignVCenter } Text { text: root.appName color: root.t.notifToastAppName font.pixelSize: 11 font.bold: true font.capitalization: Font.AllUppercase Layout.fillWidth: true elide: Text.ElideRight verticalAlignment: Text.AlignVCenter } Text { text: root.timeStr color: root.t.notifToastDim font.pixelSize: 10 verticalAlignment: Text.AlignVCenter } Rectangle { Layout.alignment: Qt.AlignVCenter width: 20; height: 20; radius: 10 color: closeHover.hovered ? root.t.notifHistoryHover : "transparent" Behavior on color { ColorAnimation { duration: 100 } } Text { anchors.centerIn: parent text: "✕" color: closeHover.hovered ? root.t.notifToastText : root.t.notifToastDim font.pixelSize: 10 } HoverHandler { id: closeHover; cursorShape: Qt.PointingHandCursor } TapHandler { onTapped: root.dismissed(root.toastId) } } } Text { text: root.summary color: root.t.notifToastText font.pixelSize: 14 font.bold: true Layout.fillWidth: true elide: Text.ElideRight textFormat: Text.PlainText visible: root.summary !== "" } Text { text: root.body color: root.t.notifToastDim font.pixelSize: 12 Layout.fillWidth: true wrapMode: Text.WordWrap maximumLineCount: 3 elide: Text.ElideRight textFormat: Text.PlainText visible: root.body !== "" Layout.bottomMargin: root.urgency === NotificationUrgency.Low ? 6 : 0 lineHeight: 1.15 } } Item { visible: root.urgency === NotificationUrgency.Low && root.timeout > 0 anchors { left: parent.left; right: parent.right; bottom: parent.bottom margins: 10; bottomMargin: 10 } height: 4 Rectangle { anchors.fill: parent radius: 2 color: root.t.notifProgressBg } Rectangle { width: parent.width * root.progressVal height: parent.height radius: 2 color: root.t.notifProgressFill } } } }