nixos/quickshell/NotificationItem.qml

174 lines
6 KiB
QML

import QtQuick
import QtQuick.Layouts
Item {
id: root
required property int nid
required property string appName
required property string summary
required property string body
required property string appIcon
required property string image
required property string desktopEntry
required property int urgency
required property var timestamp
signal dismissed()
implicitHeight: inner.implicitHeight + 16
height: implicitHeight
Rectangle {
id: bg
anchors.fill: parent
anchors.leftMargin: 4
anchors.rightMargin: 4
anchors.topMargin: 2
anchors.bottomMargin: 2
color: itemClick.containsMouse ? Theme.bg1 : "transparent"
radius: Theme.radius
Behavior on color { ColorAnimation { duration: 100 } }
RowLayout {
id: inner
// Right margin reserves space so content does not overlap the close button
anchors.left: parent.left
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
anchors.leftMargin: 8
anchors.rightMargin: 32
spacing: 8
Rectangle {
width: 34
height: 34
radius: 17
color: root.urgency === 2 ? Theme.redN
: root.urgency === 0 ? Theme.bg3
: Theme.blueN
Layout.alignment: Qt.AlignVCenter
Image {
id: iconImg
anchors.fill: parent
anchors.margins: 5
source: {
if (root.image) return root.image
if (!root.appIcon) return ""
if (root.appIcon.startsWith("/")) return root.appIcon
return Quickshell.iconPath(root.appIcon, true) || ""
}
fillMode: Image.PreserveAspectFit
visible: status === Image.Ready && source !== ""
smooth: true
}
Text {
anchors.centerIn: parent
visible: !iconImg.visible
text: root.appName.charAt(0).toUpperCase()
color: Theme.fg
font.pixelSize: Theme.fontSize
font.family: Theme.font
font.bold: true
}
}
ColumnLayout {
Layout.fillWidth: true
spacing: 2
RowLayout {
Layout.fillWidth: true
spacing: 6
Text {
text: root.summary.length > 0 ? root.summary : root.appName
color: Theme.text
font.pixelSize: Theme.fontSize
font.family: Theme.font
font.bold: true
elide: Text.ElideRight
Layout.fillWidth: true
}
Text {
text: NotificationsState.formatTime(root.timestamp)
color: Theme.subtle
font.pixelSize: Theme.fontSizeSmall
font.family: Theme.font
}
}
Text {
visible: root.body.length > 0
text: root.body
textFormat: Text.StyledText
color: Theme.fg2
font.pixelSize: Theme.fontSizeSmall
font.family: Theme.font
wrapMode: Text.WordWrap
maximumLineCount: 2
elide: Text.ElideRight
Layout.fillWidth: true
}
Text {
visible: root.summary.length > 0
text: root.appName
color: Theme.muted
font.pixelSize: Theme.fontSizeSmall - 1
font.family: Theme.font
}
}
}
Rectangle {
id: closeArea
width: 20
height: 20
radius: 10
anchors.top: parent.top
anchors.right: parent.right
anchors.topMargin: 5
anchors.rightMargin: 5
color: closeBtn.containsMouse ? Theme.bg3 : "transparent"
Behavior on color { ColorAnimation { duration: 100 } }
Text {
anchors.centerIn: parent
text: "✕"
color: closeBtn.containsMouse ? Theme.fg : Theme.subtle
font.pixelSize: 10
opacity: closeBtn.containsMouse ? 1.0 : 0.5
Behavior on color { ColorAnimation { duration: 100 } }
Behavior on opacity { NumberAnimation { duration: 100 } }
}
MouseArea {
id: closeBtn
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: root.dismissed()
}
}
// Does not extend to the right edge to avoid overlapping the close button
MouseArea {
id: itemClick
anchors.fill: parent
anchors.rightMargin: 28
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
NotificationsState.invokeDefault(root.nid, root.desktopEntry || root.appName)
root.dismissed()
}
}
}
}