From f189e304a8f719efa3354c68dc9e2792bcab9f5e Mon Sep 17 00:00:00 2001 From: Kris Date: Mon, 2 Mar 2026 20:02:54 +0200 Subject: [PATCH] a --- CONSTANTS.txt | 2 +- Shell/Notifications/NotificationCard.qml | 103 ++++++++++++++++++---- Shell/Notifications/NotificationTheme.qml | 4 +- 3 files changed, 91 insertions(+), 18 deletions(-) diff --git a/CONSTANTS.txt b/CONSTANTS.txt index 818f836..91bc9d0 100644 --- a/CONSTANTS.txt +++ b/CONSTANTS.txt @@ -80,7 +80,7 @@ notifications: timeouts: fallback default ms: 5000 - fallback low ms: 4500 + fallback low ms: 1000 fallback normal ms: 5000 fallback critical ms: 8000 diff --git a/Shell/Notifications/NotificationCard.qml b/Shell/Notifications/NotificationCard.qml index 392e436..32ff0ad 100644 --- a/Shell/Notifications/NotificationCard.qml +++ b/Shell/Notifications/NotificationCard.qml @@ -27,15 +27,54 @@ Item { readonly property string notifBody: notifObject ? String(notifObject.body || "") : "" readonly property string notifAppName: notifObject ? String(notifObject.appName || "") : "" readonly property string notifAppIcon: notifObject ? String(notifObject.appIcon || "") : "" + readonly property string notifDesktopEntry: { + if (!notifObject || !notifObject.hints) + return ""; + const value = notifObject.hints["desktop-entry"]; + return value === undefined || value === null ? "" : String(value); + } readonly property string notifImage: notifObject ? String(notifObject.image || "") : "" readonly property bool isExpanded: forceExpanded || contextOpen - readonly property string appIconSource: { - if (!notifAppIcon || notifAppIcon.length === 0) + function resolveIconSource(iconName) { + const normalized = String(iconName || "").trim(); + if (normalized.length === 0) return ""; - if (notifAppIcon.indexOf("/") >= 0 || notifAppIcon.indexOf("file://") === 0) - return notifAppIcon; - return Quickshell.iconPath(notifAppIcon); + if (normalized.indexOf("/") >= 0 || normalized.indexOf("file://") === 0) + return normalized; + return String(Quickshell.iconPath(normalized) || ""); + } + + readonly property string appIconSource: { + const candidates = []; + const desktopEntry = notifDesktopEntry.trim(); + const appName = notifAppName.trim(); + const appIcon = notifAppIcon.trim(); + + if (desktopEntry.length > 0) { + candidates.push(desktopEntry); + if (desktopEntry.endsWith(".desktop")) + candidates.push(desktopEntry.slice(0, desktopEntry.length - 8)); + } + + if (appName.length > 0) { + candidates.push(appName); + const normalizedAppName = appName.toLowerCase(); + candidates.push(normalizedAppName); + candidates.push(normalizedAppName.replace(/\s+/g, "-")); + candidates.push(normalizedAppName.replace(/\s+/g, "")); + } + + if (appIcon.length > 0) + candidates.push(appIcon); + + for (let i = 0; i < candidates.length; i++) { + const resolved = resolveIconSource(candidates[i]); + if (resolved.length > 0) + return resolved; + } + + return ""; } readonly property string customImageSource: notifImage @@ -82,7 +121,7 @@ Item { const rawTimeout = Number(notifObject.expireTimeout); if (Number.isFinite(rawTimeout) && rawTimeout > 0) { const normalizedTimeout = rawTimeout > 100 ? Math.round(rawTimeout) : Math.round(rawTimeout * 1000); - return Math.max(theme ? theme.minimumTimeoutMs : 4500, normalizedTimeout); + return Math.max(theme ? theme.minimumTimeoutMs : 2000, normalizedTimeout); } const urgency = notifObject.urgency; @@ -144,18 +183,50 @@ Item { id: enterAnimation running: !peekMode - PropertyAction { target: root; property: "opacity"; value: 0 } - PropertyAction { target: root; property: "x"; value: 20 } + PropertyAction { + target: root + property: "opacity" + value: 0 + } + PropertyAction { + target: root + property: "x" + value: 20 + } ParallelAnimation { - NumberAnimation { target: root; property: "opacity"; to: 1; duration: theme ? theme.enterMs : 170; easing.type: Easing.OutCubic } - NumberAnimation { target: root; property: "x"; to: 0; duration: theme ? theme.enterMs : 170; easing.type: Easing.OutCubic } + NumberAnimation { + target: root + property: "opacity" + to: 1 + duration: theme ? theme.enterMs : 170 + easing.type: Easing.OutCubic + } + NumberAnimation { + target: root + property: "x" + to: 0 + duration: theme ? theme.enterMs : 170 + easing.type: Easing.OutCubic + } } } ParallelAnimation { id: closeAnimation - NumberAnimation { target: root; property: "opacity"; to: 0; duration: theme ? theme.fadeMs : 120; easing.type: Easing.InCubic } - NumberAnimation { target: root; property: "x"; to: width; duration: theme ? theme.exitMs : 140; easing.type: Easing.InCubic } + NumberAnimation { + target: root + property: "opacity" + to: 0 + duration: theme ? theme.fadeMs : 120 + easing.type: Easing.InCubic + } + NumberAnimation { + target: root + property: "x" + to: width + duration: theme ? theme.exitMs : 140 + easing.type: Easing.InCubic + } onFinished: root.closeFinished(root.notificationId, root.closeReason) } @@ -218,8 +289,8 @@ Item { anchors.fill: parent visible: root.primaryIconSource.length === 0 color: "#000000" - border.width: 1 - border.color: theme ? theme.panelBorder : "#ffffff" + border.width: 0 + border.color: "transparent" radius: 0 antialiasing: false } @@ -318,7 +389,9 @@ Item { radius: 0 antialiasing: false - HoverHandler { id: actionHover } + HoverHandler { + id: actionHover + } Text { anchors.centerIn: parent diff --git a/Shell/Notifications/NotificationTheme.qml b/Shell/Notifications/NotificationTheme.qml index 93c9f75..e902442 100644 --- a/Shell/Notifications/NotificationTheme.qml +++ b/Shell/Notifications/NotificationTheme.qml @@ -35,10 +35,10 @@ QtObject { readonly property int dragDismissThreshold: 140 - readonly property int fallbackLowTimeoutMs: 4500 + readonly property int fallbackLowTimeoutMs: 1000 readonly property int fallbackNormalTimeoutMs: 5000 readonly property int fallbackCriticalTimeoutMs: 8000 - readonly property int minimumTimeoutMs: 4500 + readonly property int minimumTimeoutMs: 1000 readonly property int enterMs: 170 readonly property int exitMs: 140