nova-shell/shell/services/NotifItem.qml

76 lines
2.2 KiB
QML

import QtQuick
import Quickshell
import Quickshell.Services.Notifications
import "." as S
QtObject {
id: root
property bool popup: false
property string state: "visible" // "visible" | "dismissing" | "dismissed"
property var notification: null
property var id
property string summary
property string body
property string appName
property string appIcon
property string image
property var hints
property int urgency: NotificationUrgency.Normal
property var actions: []
property real time: Date.now()
// Resolved icon URL - checks image first, then resolves appIcon via XDG lookup
readonly property string resolvedIcon: {
if (image)
return image;
if (!appIcon)
return "";
if (appIcon.startsWith("/") || appIcon.startsWith("file://"))
return appIcon;
return Quickshell.iconPath(appIcon, "dialog-information");
}
// Expire timer — owned by this item, not dynamically created
readonly property Timer _expireTimer: Timer {
running: false
onTriggered: {
if (root.state === "visible")
root.popup = false;
}
}
// Relative time string — recomputed whenever NotifService._now ticks (single global 5s timer)
readonly property string timeStr: {
const diff = S.NotifService._now - time;
const m = Math.floor(diff / 60000);
if (m < 1)
return "now";
const h = Math.floor(m / 60);
if (h < 1)
return m + "m";
const d = Math.floor(h / 24);
return d > 0 ? d + "d" : h + "h";
}
// App closed the notification from its side — remove from our list while the object is still alive
readonly property Connections _notifConn: Connections {
target: root.notification
function onClosed() {
if (root.state !== "dismissed")
S.NotifService.dismiss(root.id);
}
}
function beginDismiss() {
if (state === "visible")
state = "dismissing";
}
function finishDismiss() {
state = "dismissed";
_expireTimer.running = false;
notification?.dismiss();
}
}