quickshell: add notification toast popup
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
2ec4f400c6
commit
18ccb266c3
1 changed files with 155 additions and 0 deletions
|
|
@ -467,6 +467,7 @@ in
|
||||||
keepOnReload: true
|
keepOnReload: true
|
||||||
onNotification: (notification) => {
|
onNotification: (notification) => {
|
||||||
notification.tracked = true;
|
notification.tracked = true;
|
||||||
|
notifToast.show(notification);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1659,6 +1660,160 @@ in
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Notification toast popup
|
||||||
|
PopupWindow {
|
||||||
|
id: notifToast
|
||||||
|
property var currentNotif: null
|
||||||
|
property bool open: false
|
||||||
|
|
||||||
|
function show(notification) {
|
||||||
|
currentNotif = notification;
|
||||||
|
visible = true;
|
||||||
|
open = true;
|
||||||
|
_toastTimer.restart();
|
||||||
|
}
|
||||||
|
|
||||||
|
function dismiss() {
|
||||||
|
open = false;
|
||||||
|
_toastCloseDelay.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
anchor.window: bar
|
||||||
|
anchor.rect.x: bar.width / 2 - 160
|
||||||
|
anchor.rect.y: bar.height
|
||||||
|
anchor.edges: Edges.Top | Edges.Left
|
||||||
|
anchor.gravity: Edges.Bottom | Edges.Right
|
||||||
|
visible: false
|
||||||
|
width: 320
|
||||||
|
height: toastContent.height + 2
|
||||||
|
color: "transparent"
|
||||||
|
|
||||||
|
Timer {
|
||||||
|
id: _toastTimer
|
||||||
|
interval: 5000
|
||||||
|
onTriggered: notifToast.dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
|
Timer {
|
||||||
|
id: _toastCloseDelay
|
||||||
|
interval: 230
|
||||||
|
onTriggered: { notifToast.visible = false; notifToast.open = false; }
|
||||||
|
}
|
||||||
|
|
||||||
|
HoverHandler {
|
||||||
|
onHoveredChanged: {
|
||||||
|
if (hovered) _toastTimer.stop();
|
||||||
|
else _toastTimer.restart();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: toastContent
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.topMargin: 2
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
width: 316
|
||||||
|
height: toastCol.height + 16
|
||||||
|
radius: 8
|
||||||
|
color: "#E6${c.base00}"
|
||||||
|
clip: true
|
||||||
|
|
||||||
|
transform: Translate {
|
||||||
|
y: notifToast.open ? 0 : -(toastContent.height + 10)
|
||||||
|
Behavior on y {
|
||||||
|
NumberAnimation { duration: 220; easing.type: Easing.OutCubic }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
opacity: notifToast.open ? 1.0 : 0.0
|
||||||
|
Behavior on opacity {
|
||||||
|
NumberAnimation { duration: 200; easing.type: Easing.OutCubic }
|
||||||
|
}
|
||||||
|
|
||||||
|
Column {
|
||||||
|
id: toastCol
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: toastDismiss.left
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.margins: 8
|
||||||
|
spacing: 2
|
||||||
|
|
||||||
|
Text {
|
||||||
|
width: parent.width
|
||||||
|
text: notifToast.currentNotif ? (notifToast.currentNotif.summary || notifToast.currentNotif.appName) : ""
|
||||||
|
color: "#${c.base05}"
|
||||||
|
font.family: "FiraMono Nerd Font"
|
||||||
|
font.pixelSize: 12
|
||||||
|
font.weight: Font.Medium
|
||||||
|
elide: Text.ElideRight
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
width: parent.width
|
||||||
|
text: notifToast.currentNotif ? (notifToast.currentNotif.body || "") : ""
|
||||||
|
color: "#${c.base04}"
|
||||||
|
font.family: "FiraMono Nerd Font"
|
||||||
|
font.pixelSize: 11
|
||||||
|
elide: Text.ElideRight
|
||||||
|
maximumLineCount: 3
|
||||||
|
wrapMode: Text.Wrap
|
||||||
|
visible: text !== ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// Action buttons
|
||||||
|
Row {
|
||||||
|
spacing: 4
|
||||||
|
visible: notifToast.currentNotif && notifToast.currentNotif.actions.length > 0
|
||||||
|
Repeater {
|
||||||
|
model: notifToast.currentNotif ? notifToast.currentNotif.actions : []
|
||||||
|
Rectangle {
|
||||||
|
required property var modelData
|
||||||
|
width: toastActionText.width + 12
|
||||||
|
height: toastActionText.height + 6
|
||||||
|
radius: 4
|
||||||
|
color: toastActionMa.containsMouse ? "#${c.base02}" : "#${c.base01}"
|
||||||
|
border.width: 1
|
||||||
|
border.color: "#${c.base02}"
|
||||||
|
Text {
|
||||||
|
id: toastActionText
|
||||||
|
anchors.centerIn: parent
|
||||||
|
text: modelData.text
|
||||||
|
color: "#${c.base05}"
|
||||||
|
font.family: "FiraMono Nerd Font"
|
||||||
|
font.pixelSize: 10
|
||||||
|
}
|
||||||
|
MouseArea {
|
||||||
|
id: toastActionMa
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
onClicked: { modelData.invoke(); notifToast.dismiss(); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dismiss X
|
||||||
|
Text {
|
||||||
|
id: toastDismiss
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.margins: 8
|
||||||
|
text: "\u{f0156}"
|
||||||
|
color: toastDismissMa.containsMouse ? "#${c.base05}" : "#${c.base03}"
|
||||||
|
font.family: "FiraMono Nerd Font"
|
||||||
|
font.pixelSize: 13
|
||||||
|
MouseArea {
|
||||||
|
id: toastDismissMa
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
onClicked: { notifToast.currentNotif.dismiss(); notifToast.dismiss(); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
'';
|
'';
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue