move NotifService and NotifItem to services/, keep notification UI in modules/

This commit is contained in:
Damocles 2026-04-18 00:26:14 +02:00
parent a17a365b81
commit d20fdf8fa0
8 changed files with 33 additions and 36 deletions

View file

@ -6,7 +6,6 @@ import Quickshell.Services.Mpris
import Quickshell.Services.Pipewire import Quickshell.Services.Pipewire
import "../services" as S import "../services" as S
import "../applets" as C import "../applets" as C
import "../modules" as M
WlSessionLockSurface { WlSessionLockSurface {
id: root id: root
@ -149,7 +148,7 @@ WlSessionLockSurface {
visible: (S.Modules.lock.notifications ?? true) && _notifGroups.length > 0 visible: (S.Modules.lock.notifications ?? true) && _notifGroups.length > 0
readonly property var _notifGroups: { readonly property var _notifGroups: {
const notifs = M.NotifService.list.filter(n => n.state !== "dismissed"); const notifs = S.NotifService.list.filter(n => n.state !== "dismissed");
const groups = {}; const groups = {};
for (const n of notifs) { for (const n of notifs) {
const key = n.appIcon || n.appName || "unknown"; const key = n.appIcon || n.appName || "unknown";

View file

@ -33,8 +33,8 @@ M.HoverPanel {
// DND toggle // DND toggle
Text { Text {
text: M.NotifService.dnd ? "\uDB82\uDE93" : "\uDB80\uDC9C" text: S.NotifService.dnd ? "\uDB82\uDE93" : "\uDB80\uDC9C"
color: M.NotifService.dnd ? S.Theme.base09 : S.Theme.base04 color: S.NotifService.dnd ? S.Theme.base09 : S.Theme.base04
font.pixelSize: S.Theme.fontSize font.pixelSize: S.Theme.fontSize
font.family: S.Theme.iconFontFamily font.family: S.Theme.iconFontFamily
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
@ -42,7 +42,7 @@ M.HoverPanel {
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: M.NotifService.toggleDnd() onClicked: S.NotifService.toggleDnd()
} }
} }
@ -53,7 +53,7 @@ M.HoverPanel {
font.pixelSize: S.Theme.fontSize font.pixelSize: S.Theme.fontSize
font.family: S.Theme.iconFontFamily font.family: S.Theme.iconFontFamily
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
visible: M.NotifService.count > 0 visible: S.NotifService.count > 0
MouseArea { MouseArea {
id: clearArea id: clearArea
@ -88,7 +88,7 @@ M.HoverPanel {
// Group notifications by appName, sorted by max urgency desc then most recent time desc // Group notifications by appName, sorted by max urgency desc then most recent time desc
readonly property var _groups: { readonly property var _groups: {
const map = {}; const map = {};
for (const n of M.NotifService.list) { for (const n of S.NotifService.list) {
const key = n.appName || ""; const key = n.appName || "";
if (!map[key]) if (!map[key])
map[key] = { map[key] = {
@ -167,14 +167,14 @@ M.HoverPanel {
} }
function _cascadeDismiss() { function _cascadeDismiss() {
if (M.NotifService.list.length === 0) if (S.NotifService.list.length === 0)
return; return;
const ids = M.NotifService.list.map(n => n.id); const ids = S.NotifService.list.map(n => n.id);
_startCascade(_getVisibleNotifDelegates(), ids); _startCascade(_getVisibleNotifDelegates(), ids);
} }
function _cascadeGroupDismiss(appName) { function _cascadeGroupDismiss(appName) {
const ids = M.NotifService.list.filter(n => n.appName === appName).map(n => n.id); const ids = S.NotifService.list.filter(n => n.appName === appName).map(n => n.id);
if (ids.length === 0) if (ids.length === 0)
return; return;
_startCascade(_getVisibleNotifDelegates(appName), ids); _startCascade(_getVisibleNotifDelegates(appName), ids);
@ -184,7 +184,7 @@ M.HoverPanel {
const ids = _pendingDismissIds; const ids = _pendingDismissIds;
_pendingDismissIds = []; _pendingDismissIds = [];
for (const id of ids) for (const id of ids)
M.NotifService.dismiss(id); S.NotifService.dismiss(id);
} }
property Component _cascadeTimer: Component { property Component _cascadeTimer: Component {
@ -467,7 +467,7 @@ M.HoverPanel {
ScriptAction { ScriptAction {
script: { script: {
if (notifDelegate._notif && !notifDelegate._skipDismiss) if (notifDelegate._notif && !notifDelegate._skipDismiss)
M.NotifService.dismiss(notifDelegate._notif.id); S.NotifService.dismiss(notifDelegate._notif.id);
} }
} }
} }
@ -476,7 +476,7 @@ M.HoverPanel {
// Empty state // Empty state
Text { Text {
visible: M.NotifService.count === 0 visible: S.NotifService.count === 0
width: menuWindow.contentWidth width: menuWindow.contentWidth
height: 48 height: 48
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignHCenter

View file

@ -10,7 +10,7 @@ PanelWindow {
required property var screen required property var screen
visible: M.NotifService.popups.length > 0 && !S.NiriIpc.overviewOpen visible: S.NotifService.popups.length > 0 && !S.NiriIpc.overviewOpen
color: "transparent" color: "transparent"
WlrLayershell.layer: WlrLayer.Overlay WlrLayershell.layer: WlrLayer.Overlay
@ -34,7 +34,7 @@ PanelWindow {
property var _knownIds: ({}) property var _knownIds: ({})
Repeater { Repeater {
model: M.NotifService.popups.slice(0, S.Modules.notifications.maxPopups || 4) model: S.NotifService.popups.slice(0, S.Modules.notifications.maxPopups || 4)
delegate: Item { delegate: Item {
id: popupItem id: popupItem
@ -74,7 +74,7 @@ PanelWindow {
} }
Connections { Connections {
target: M.NotifService target: S.NotifService
function onPopupExpiring(notifId) { function onPopupExpiring(notifId) {
if (notifId === popupItem.modelData.id) if (notifId === popupItem.modelData.id)
popupItem.animateDismiss(false); popupItem.animateDismiss(false);
@ -152,7 +152,7 @@ PanelWindow {
easing.type: Easing.OutCubic easing.type: Easing.OutCubic
} }
ScriptAction { ScriptAction {
script: popupItem._fullDismiss ? M.NotifService.dismiss(popupItem.modelData.id) : M.NotifService.dismissPopup(popupItem.modelData.id) script: popupItem._fullDismiss ? S.NotifService.dismiss(popupItem.modelData.id) : S.NotifService.dismissPopup(popupItem.modelData.id)
} }
} }

View file

@ -8,28 +8,28 @@ M.BarSection {
id: root id: root
spacing: S.Theme.moduleSpacing spacing: S.Theme.moduleSpacing
tooltip: { tooltip: {
const parts = [M.NotifService.count + " notification" + (M.NotifService.count !== 1 ? "s" : "")]; const parts = [S.NotifService.count + " notification" + (S.NotifService.count !== 1 ? "s" : "")];
if (M.NotifService.dnd) if (S.NotifService.dnd)
parts.push("Do not disturb"); parts.push("Do not disturb");
return parts.join("\n"); return parts.join("\n");
} }
required property var bar required property var bar
readonly property bool hasUrgent: M.NotifService.list.some(n => n.urgency === NotificationUrgency.Critical && n.state !== "dismissed") readonly property bool hasUrgent: S.NotifService.list.some(n => n.urgency === NotificationUrgency.Critical && n.state !== "dismissed")
M.BarIcon { M.BarIcon {
icon: { icon: {
if (M.NotifService.dnd) if (S.NotifService.dnd)
return M.NotifService.count > 0 ? "\uDB80\uDCA0" : "\uDB82\uDE93"; return S.NotifService.count > 0 ? "\uDB80\uDCA0" : "\uDB82\uDE93";
return M.NotifService.count > 0 ? "\uDB84\uDD6B" : "\uDB80\uDC9C"; return S.NotifService.count > 0 ? "\uDB84\uDD6B" : "\uDB80\uDC9C";
} }
color: M.NotifService.dnd ? S.Theme.base04 : root.accentColor color: S.NotifService.dnd ? S.Theme.base04 : root.accentColor
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
M.BarLabel { M.BarLabel {
id: countLabel id: countLabel
label: M.NotifService.count > 0 ? String(M.NotifService.count) + (root.hasUrgent ? "!" : "") : "" label: S.NotifService.count > 0 ? String(S.NotifService.count) + (root.hasUrgent ? "!" : "") : ""
color: root.hasUrgent ? S.Theme.base08 : root.accentColor color: root.hasUrgent ? S.Theme.base08 : root.accentColor
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
@ -61,9 +61,9 @@ M.BarSection {
} }
Connections { Connections {
target: M.NotifService target: S.NotifService
function onCountChanged() { function onCountChanged() {
if (M.NotifService.count > 0) if (S.NotifService.count > 0)
popAnim.start(); popAnim.start();
} }
} }
@ -77,7 +77,7 @@ M.BarSection {
} }
TapHandler { TapHandler {
acceptedButtons: Qt.RightButton acceptedButtons: Qt.RightButton
onTapped: M.NotifService.toggleDnd() onTapped: S.NotifService.toggleDnd()
} }
LazyLoader { LazyLoader {

View file

@ -31,8 +31,6 @@ PowerProfileModule 1.0 PowerProfileModule.qml
IdleInhibitorModule 1.0 IdleInhibitorModule.qml IdleInhibitorModule 1.0 IdleInhibitorModule.qml
NotificationsModule 1.0 NotificationsModule.qml NotificationsModule 1.0 NotificationsModule.qml
ProcessList 1.0 ProcessList.qml ProcessList 1.0 ProcessList.qml
singleton NotifService 1.0 NotifService.qml
NotifItem 1.0 NotifItem.qml
NotifPopup 1.0 NotifPopup.qml NotifPopup 1.0 NotifPopup.qml
NotifCenter 1.0 NotifCenter.qml NotifCenter 1.0 NotifCenter.qml
NotifCard 1.0 NotifCard.qml NotifCard 1.0 NotifCard.qml

View file

@ -1,7 +1,6 @@
import QtQuick import QtQuick
import Quickshell.Services.Notifications import Quickshell.Services.Notifications
import "." as M import "." as S
import "../services" as S
QtObject { QtObject {
id: root id: root
@ -32,7 +31,7 @@ QtObject {
// Relative time string recomputed whenever NotifService._now ticks (single global 5s timer) // Relative time string recomputed whenever NotifService._now ticks (single global 5s timer)
readonly property string timeStr: { readonly property string timeStr: {
const diff = M.NotifService._now - time; const diff = S.NotifService._now - time;
const m = Math.floor(diff / 60000); const m = Math.floor(diff / 60000);
if (m < 1) if (m < 1)
return "now"; return "now";
@ -48,7 +47,7 @@ QtObject {
target: root.notification target: root.notification
function onClosed() { function onClosed() {
if (root.state !== "dismissed") if (root.state !== "dismissed")
M.NotifService.dismiss(root.id); S.NotifService.dismiss(root.id);
} }
} }

View file

@ -3,8 +3,7 @@ pragma Singleton
import QtQuick import QtQuick
import Quickshell import Quickshell
import Quickshell.Services.Notifications import Quickshell.Services.Notifications
import "." as M import "." as S
import "../services" as S
QtObject { QtObject {
id: root id: root

View file

@ -4,3 +4,5 @@ singleton SystemStats 1.0 SystemStats.qml
singleton Modules 1.0 Modules.qml singleton Modules 1.0 Modules.qml
singleton NiriIpc 1.0 NiriIpc.qml singleton NiriIpc 1.0 NiriIpc.qml
singleton PowerProfileService 1.0 PowerProfileService.qml singleton PowerProfileService 1.0 PowerProfileService.qml
singleton NotifService 1.0 NotifService.qml
NotifItem 1.0 NotifItem.qml