dots/shell/notifications/ActiveToast.qml

215 lines
7 KiB
QML

import QtQuick
import QtQuick.Layouts
import Quickshell
import Quickshell.Widgets
import Quickshell.Services.Notifications
import qs
import qs.widgets
Item {
id: root
required property var notification
signal expired(Notification notification)
signal closed(Notification notification)
width: parent.width
height: Math.min(row.implicitHeight + 30, 400)
StyledRectangle {
id: container
radius: 10
color: ShellSettings.colors.surface_translucent
anchors.fill: parent
Item {
id: timerController
property int totalDuration: 5000
property int remainingTime: totalDuration
property bool isRunning: false
property real lastTime: 0
Timer {
id: internalTimer
interval: 16
repeat: true
running: timerController.isRunning
onTriggered: {
var currentTime = Date.now();
if (timerController.lastTime > 0) {
var delta = currentTime - timerController.lastTime;
timerController.remainingTime -= delta;
if (timerController.remainingTime <= 0) {
timerController.isRunning = false;
root.expired(root.notification);
}
}
timerController.lastTime = currentTime;
}
}
function start() {
if (!isRunning) {
lastTime = Date.now();
isRunning = true;
}
}
function pause() {
isRunning = false;
lastTime = 0;
}
Component.onCompleted: {
start();
}
}
MouseArea {
id: notificationArea
hoverEnabled: true
anchors.fill: parent
onContainsMouseChanged: {
progressAnimation.paused = containsMouse;
if (containsMouse) {
timerController.pause();
} else {
timerController.start();
}
}
}
RowLayout {
id: row
spacing: 5
anchors {
fill: parent
margins: 15
}
ColumnLayout {
Layout.fillWidth: true
RowLayout {
id: topRow
spacing: 10
Layout.fillWidth: true
IconImage {
visible: root.notification.appIcon != ""
source: Quickshell.iconPath(root.notification.appIcon)
implicitSize: 24
}
RowLayout {
Layout.fillWidth: true
Text {
id: appName
text: root.notification.appName
color: ShellSettings.colors.active
font.pointSize: 11
font.bold: true
elide: Text.ElideRight
maximumLineCount: 1
// Layout.preferredWidth: implicitWidth
// Layout.maximumWidth: topRow.width * 0.3
}
Text {
id: summaryText
text: root.notification.summary
color: ShellSettings.colors.active
font.pointSize: 11
elide: Text.ElideRight
maximumLineCount: 1
Layout.fillWidth: true
}
}
Item {
id: closeButton
width: 24
height: 24
Layout.alignment: Qt.AlignTop
Canvas {
id: progressCircle
anchors.fill: parent
antialiasing: true
property real progress: 1.0
onProgressChanged: requestPaint()
onPaint: {
var ctx = getContext("2d");
ctx.reset();
var centerX = width / 2;
var centerY = height / 2;
var radius = Math.min(width, height) / 2 - 2;
ctx.beginPath();
ctx.arc(centerX, centerY, radius, -Math.PI / 2, -Math.PI / 2 + 2 * Math.PI * progress);
ctx.strokeStyle = ShellSettings.colors.highlight
ctx.lineWidth = 2;
ctx.stroke();
}
}
NumberAnimation {
id: progressAnimation
target: progressCircle
property: "progress"
from: 1.0
to: 0.0
duration: 5000
running: true
easing.type: Easing.Linear
}
Rectangle {
id: closeButtonBg
anchors.centerIn: parent
width: 16
height: 16
color: "#FF474D"
radius: 10
visible: closeButtonArea.containsMouse
}
MouseArea {
id: closeButtonArea
hoverEnabled: true
anchors.fill: parent
onPressed: root.closed(root.notification)
}
IconImage {
source: "image://icon/window-close"
implicitSize: 16
anchors.centerIn: parent
}
}
}
ColumnLayout {
Layout.fillWidth: true
Text {
id: bodyText
text: root.notification.body
color: ShellSettings.colors.active
font.pointSize: 11
wrapMode: Text.Wrap
elide: Text.ElideRight
maximumLineCount: 10
Layout.fillWidth: true
}
}
}
}
}
}