import QtQuick import Quickshell import "../../config" import QtQuick.Layouts Rectangle { id: root //TODO: urgency, expireTimeoutText, ... required property var notification required property var screen property real duration: 5000 // Expected in milliseconds (e.g., 5000 for 5s) signal dismissed(var notification, bool dismiss) implicitWidth: Math.min(iconColumn.width+contentColumn.width+2*Config.spacing, screen.width/5) implicitHeight: Math.max(iconColumn.height, contentColumn.height)+Config.spacing+Config.spacing color: Qt.alpha(Colors.primaryContainer, 0.75) border.width: Config.border_width border.color: Colors.primary MouseArea { id: mouseArea anchors.fill: parent hoverEnabled: true onClicked: { dismissed(root.notification, true) } // Row { // spacing: 10 // Rectangle { // width: 80 // height: 80 // border.width: 2 // color: "transparent" // Image { // anchors.centerIn: parent // width: 64 // height: 64 // source: "image://icon/org.mozilla.Thunderbird" // fillMode: Image.PreserveAspectFit // } // Component.onCompleted: { // print("Signal:", Quickshell.iconPath("signal-desktop")) // print("Thunderbird:", Quickshell.iconPath("org.mozilla.Thunderbird")) // print("Signal exists:", // Quickshell.hasThemeIcon("signal-desktop")) // print("Thunderbird exists:", // Quickshell.hasThemeIcon("org.mozilla.Thunderbird")) // } // } // Rectangle { // width: 80 // height: 80 // border.width: 2 // color: "transparent" // Image { // anchors.centerIn: parent // width: 64 // height: 64 // source: Quickshell.iconPath("org.mozilla.Thunderbird") // fillMode: Image.PreserveAspectFit // } // } // Rectangle { // width: 80 // height: 80 // border.width: 2 // color: "transparent" // Image { // anchors.centerIn: parent // width: 64 // height: 64 // source: "/usr/share/icons/hicolor/128x128/apps/org.mozilla.Thunderbird.png" // fillMode: Image.PreserveAspectFit // } // } // } Row { id: contentRow anchors.fill: parent anchors.margins: 10 spacing: Config.spacing // Left side: icon + icon information Column { id: iconColumn height: Math.max(iconImage.height+summaryText.height+3*Config.spacing, contentColumn.height)+Config.spacing width: iconImage.width spacing: Config.spacing Image { id: iconImage width: screen.width/22 height: iconImage.width source: (notification.appIcon != "" ? Quickshell.iconPath(notification.appIcon) : notification.image) fillMode: Image.PreserveAspectFit asynchronous: true } Text { id: summaryText Layout.fillWidth: true width: iconImage.width text: root.notification?.summary ?? "" font.family: Config.font font.pixelSize: 22 color: Colors.primary wrapMode: Text.Wrap horizontalAlignment: Text.AlignHCenter } } // Right side: notification information Column { id: contentColumn width: Math.max(bodyText.width + Config.spacing, iconColumn.width) spacing: Config.spacing Text { id: bodyText text: root.notification?.body ?? "" width: Math.min(implicitWidth, iconColumn.width*2) font.family: Config.font font.pixelSize: 22 color: Colors.primary wrapMode: Text.Wrap } // Text { // id: appNameText // width: parent.width // text: root.notification?.id + ": " + // (root.notification?.appName ?? "") // font.family: Config.font // font.pixelSize: 18 // color: Colors.primary // elide: Text.ElideRight // } // Text { // id: inlineReplyPlaceholderText // width: parent.width // text: "inlineReplyPlaceholder: " + (root.notification?.inlineReplyPlaceholder ?? "") // font.family: Config.font // font.pixelSize: 16 // color: Colors.primary // wrapMode: Text.Wrap // } // Text { // id: iconPathText // width: parent.width // text: "iconPath: " + (root.notification?.iconPath ?? "") // font.family: Config.font // font.pixelSize: 16 // color: Colors.primary // wrapMode: Text.Wrap // } // Text { // id: expireTimeoutText // width: parent.width // text: "expireTimeout: " + // (root.notification?.expireTimeout ?? "") // font.family: Config.font // font.pixelSize: 16 // color: Colors.primary // wrapMode: Text.Wrap // } // Text { // id: residentText // width: parent.width // text: "resident: " + (root.notification?.resident ?? "") // font.family: Config.font // font.pixelSize: 16 // color: Colors.primary // wrapMode: Text.Wrap // } // Text { // id: urgencyText // width: parent.width // text: "urgency: " + (root.notification?.urgency ?? "") // font.family: Config.font // font.pixelSize: 16 // color: Colors.primary // wrapMode: Text.Wrap // } // Text { // id: desktopEntryText // width: parent.width // text: "desktopEntry: " + // (root.notification?.desktopEntry ?? "") // font.family: Config.font // font.pixelSize: 16 // color: Colors.primary // wrapMode: Text.Wrap // } // Text { // id: hintsText // width: parent.width // text: "hints: " + (root.notification?.hints ?? "") // font.family: Config.font // font.pixelSize: 16 // color: Colors.primary // wrapMode: Text.Wrap // } // Text { // id: transientText // width: parent.width // text: "transient: " + (root.notification?.transient ?? "") // font.family: Config.font // font.pixelSize: 16 // color: Colors.primary // wrapMode: Text.Wrap // } // Text { // id: hasInlineReplyText // width: parent.width // text: "hasInlineReply: " + // (root.notification?.hasInlineReply ?? "") // font.family: Config.font // font.pixelSize: 16 // color: Colors.primary // wrapMode: Text.Wrap // } // Text { // id: hasActionIconsText // width: parent.width // text: "hasActionIcons: " + // (root.notification?.hasActionIcons ?? "") // font.family: Config.font // font.pixelSize: 16 // color: Colors.primary // wrapMode: Text.Wrap // } } } } // Timeout progress bar Rectangle { id: progressBar anchors.bottom: parent.bottom anchors.left: parent.left height: Math.min(10, 0.1 * root.height) color: Colors.primary property real progress: 1.0 width: root.width * progress NumberAnimation on progress { id: anim running: root.duration > 0 from: 1.0 to: 0.0 // If your duration property comes in seconds (e.g., 5), change to: (root.duration * 1000) duration: root.duration paused: mouseArea.containsMouse onFinished: root.dismissed(root.notification, false) } } Component.onCompleted: { if(Config.debug == "Notification"){ console.log("\x1b[31m[NotificationBody]:"+"\x1b[0m") console.log("\x1b[31m\t"+"inlineReplyPlaceholder: " + notification.inlineReplyPlaceholder +"\x1b[0m") console.log("\x1b[31m\t"+"body: " + notification.body+"\x1b[0m") console.log("\x1b[31m\t"+"lastGeneration: " + notification.lastGeneration+"\x1b[0m") console.log("\x1b[31m\t"+"appName: " + notification.appName+"\x1b[0m") console.log("\x1b[31m\t"+"image: " + notification.image+"\x1b[0m") console.log("\x1b[31m\t"+"expireTimeout: " + notification.expireTimeout+"\x1b[0m") console.log("\x1b[31m\t"+"resident: " + notification.resident+"\x1b[0m") console.log("\x1b[31m\t"+"id: " + notification.id+"\x1b[0m") console.log("\x1b[31m\t"+"actions: " + notification.actions+"\x1b[0m") console.log("\x1b[31m\t"+"urgency: " + notification.urgency+"\x1b[0m") console.log("\x1b[31m\t"+"appIcon: " + notification.appIcon + " | " + Quickshell.iconPath(notification.appIcon)+"\x1b[0m") console.log("\x1b[31m\t"+"desktopEntry: " + notification.desktopEntry+"\x1b[0m") console.log("\x1b[31m\t"+"hints: " + notification.hints+"\x1b[0m") for (const item of Object.keys(notification.hints)) { console.log("\x1b[31m\t"+"hints-"+ item +": " + notification.hints[item]+"\x1b[0m") } console.log("\x1b[31m\t"+"summary: " + notification.summary+"\x1b[0m") console.log("\x1b[31m\t"+"transient: " + notification.transient+"\x1b[0m") console.log("\x1b[31m\t"+"hasInlineReply: " + notification.hasInlineReply+"\x1b[0m") console.log("\x1b[31m\t"+"hasActionIcons: " + notification.hasActionIcons+"\x1b[0m") console.log("\x1b[31m\t"+"image.source: " + iconImage.source+"\x1b[0m") } } }