192 lines
6.3 KiB
QML
192 lines
6.3 KiB
QML
import QtQuick
|
|
import QtQuick.Layouts
|
|
import Quickshell.Services.Notifications
|
|
|
|
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: 1
|
|
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
|
|
}
|
|
}
|
|
}
|
|
}
|