diff --git a/README.md b/README.md index 924edcf..33eff9f 100644 --- a/README.md +++ b/README.md @@ -108,6 +108,7 @@ programs.nova-shell.modules = { power.enable = false; # if you enjoy living dangerously without a logout button lock.enable = false; # if you prefer your session unlocked and your secrets free lock.screenshot = false; # disable blurred desktop screenshot background + lock.notifications = false; # hide notification icons on the lock screen lock.mpris = false; # hide media controls on the lock screen lock.volume = false; # hide volume slider on the lock screen diff --git a/nix/hm-module.nix b/nix/hm-module.nix index 8b1879b..d5f5691 100644 --- a/nix/hm-module.nix +++ b/nix/hm-module.nix @@ -106,6 +106,11 @@ in default = true; description = "Show blurred desktop screenshot as lock screen background."; }; + notifications = lib.mkOption { + type = lib.types.bool; + default = true; + description = "Show notification app icons on the lock screen."; + }; mpris = lib.mkOption { type = lib.types.bool; default = true; diff --git a/shell/lock/LockSurface.qml b/shell/lock/LockSurface.qml index b5c8a0f..f9148af 100644 --- a/shell/lock/LockSurface.qml +++ b/shell/lock/LockSurface.qml @@ -6,6 +6,7 @@ import Quickshell.Services.Mpris import Quickshell.Services.Pipewire import "../services" as S import "../applets" as C +import "../modules" as M WlSessionLockSurface { id: root @@ -141,6 +142,74 @@ WlSessionLockSurface { } } + // Notification pills + Row { + anchors.horizontalCenter: parent.horizontalCenter + spacing: 6 + visible: (S.Modules.lock.notifications ?? true) && _notifGroups.length > 0 + + readonly property var _notifGroups: { + const notifs = M.NotifService.list.filter(n => n.state !== "dismissed"); + const groups = {}; + for (const n of notifs) { + const key = n.appIcon || n.appName || "unknown"; + if (!groups[key]) + groups[key] = { + icon: n.appIcon, + name: n.appName, + count: 0 + }; + groups[key].count++; + } + return Object.values(groups); + } + + Repeater { + model: parent._notifGroups + + delegate: Rectangle { + required property var modelData + width: _pillRow.implicitWidth + 12 + height: 24 + radius: 12 + color: Qt.rgba(S.Theme.base01.r, S.Theme.base01.g, S.Theme.base01.b, 0.7) + border.color: Qt.rgba(S.Theme.base03.r, S.Theme.base03.g, S.Theme.base03.b, 0.3) + border.width: 1 + + Row { + id: _pillRow + anchors.centerIn: parent + spacing: 4 + + Image { + anchors.verticalCenter: parent.verticalCenter + width: 14 + height: 14 + source: { + const icon = modelData.icon; + if (!icon) + return ""; + if (icon.startsWith("/")) + return icon; + return Quickshell.iconPath(icon) ?? ""; + } + sourceSize: Qt.size(14, 14) + visible: source !== "" + } + + Text { + anchors.verticalCenter: parent.verticalCenter + text: modelData.count > 1 ? modelData.count.toString() : "" + color: S.Theme.base04 + font.pixelSize: S.Theme.fontSize - 2 + font.family: S.Theme.fontFamily + visible: modelData.count > 1 + } + } + } + } + } + // Spacer Item { width: 1 diff --git a/shell/services/Modules.qml b/shell/services/Modules.qml index eab237b..20ceede 100644 --- a/shell/services/Modules.qml +++ b/shell/services/Modules.qml @@ -95,6 +95,7 @@ QtObject { property var lock: ({ enable: true, screenshot: true, + notifications: true, mpris: true, volume: true })