import QtQuick import Quickshell import Quickshell.Services.Notifications import "." as M import "../services" as S import "../applets" as C M.BarModule { id: root spacing: S.Theme.moduleSpacing tooltip: S.NotifService.count > 0 ? "Notifications: " + S.NotifService.count + (S.NotifService.dnd ? " (DND)" : "") : (S.NotifService.dnd ? "Do not disturb" : "No notifications") panelNamespace: "nova-notifications" panelTitle: "Notifications" panelContentWidth: 350 titleActionsComponent: Component { Row { spacing: 8 // DND toggle Text { text: S.NotifService.dnd ? "\uDB82\uDE93" : "\uDB80\uDC9C" color: S.NotifService.dnd ? S.Theme.base09 : S.Theme.base04 font.pixelSize: S.Theme.fontSize font.family: S.Theme.iconFontFamily anchors.verticalCenter: parent.verticalCenter HoverHandler { cursorShape: Qt.PointingHandCursor } TapHandler { onTapped: S.NotifService.toggleDnd() } } // Clear all Text { text: "\uF1F8" color: _clearHover.hovered ? S.Theme.base08 : S.Theme.base04 font.pixelSize: S.Theme.fontSize font.family: S.Theme.iconFontFamily anchors.verticalCenter: parent.verticalCenter visible: S.NotifService.count > 0 HoverHandler { id: _clearHover cursorShape: Qt.PointingHandCursor } TapHandler { onTapped: if (root._notifApplet) root._notifApplet.cascadeDismiss() } } } } panelComponent: Component { C.NotifApplet { width: parent.width contentWidth: root.panelContentWidth accentColor: root.accentColor Component.onCompleted: root._notifApplet = this Component.onDestruction: root._notifApplet = null } } property var _notifApplet: null readonly property bool hasUrgent: S.NotifService.list.some(n => n.urgency === NotificationUrgency.Critical && n.state !== "dismissed") M.BarIcon { icon: { if (S.NotifService.dnd) return S.NotifService.count > 0 ? "\uDB80\uDCA0" : "\uDB82\uDE93"; return S.NotifService.count > 0 ? "\uDB84\uDD6B" : "\uDB80\uDC9C"; } color: S.NotifService.dnd ? S.Theme.base04 : root.accentColor anchors.verticalCenter: parent.verticalCenter } M.BarLabel { id: countLabel label: S.NotifService.count > 0 ? String(S.NotifService.count) + (root.hasUrgent ? "!" : "") : "" color: root.hasUrgent ? S.Theme.base08 : root.accentColor anchors.verticalCenter: parent.verticalCenter transform: Scale { id: countScale origin.x: countLabel.width / 2 origin.y: countLabel.height / 2 xScale: 1 yScale: 1 } SequentialAnimation { id: popAnim NumberAnimation { target: countScale properties: "xScale,yScale" to: 1.4 duration: 100 easing.type: Easing.OutQuad } NumberAnimation { target: countScale properties: "xScale,yScale" to: 1.0 duration: 200 easing.type: Easing.OutElastic } } } Connections { target: S.NotifService function onCountChanged() { if (S.NotifService.count > 0 && !S.Theme.reducedMotion) popAnim.start(); } } // Right-click DND quick toggle TapHandler { acceptedButtons: Qt.RightButton onTapped: S.NotifService.toggleDnd() } }