add notifications

This commit is contained in:
lucy 2026-08-23 22:02:34 +02:00
commit 3e9fb9f5d1
7 changed files with 305 additions and 1 deletions

View file

@ -0,0 +1,91 @@
import Quickshell
import Quickshell.Widgets
import QtQuick.Layouts
import QtQuick
import qs
import qs.settings
import qs.widgets
WrapperRectangle {
id: root
required property var notification
required property ShellScreen nScreen
property alias timerStart: dismissTimer
implicitWidth: nScreen.width / 6
implicitHeight: 100
radius: Config.rounding
anchors.right: parent.right
color: Colors.barBg
clip: true
Timer {
id: dismissTimer
interval: 5000
repeat: false
onTriggered: root.notification.dismiss()
}
child: WrapperMouseArea {
id: mouseHandler
child: RowLayout {
spacing: 10
IconImage {
id: appIcon
Layout.leftMargin: 8
visible: root.notification?.image ? true : false
source: root.notification?.image ? root.notification.image : ''
implicitSize: 64
}
ColumnLayout {
Layout.alignment: Qt.AlignLeft
Layout.fillWidth: true
Layout.preferredWidth: 0
Layout.fillHeight: true
Layout.leftMargin: appIcon.visible ? 0 : 16
RowLayout {
Layout.alignment: Qt.AlignTop
MaterialIcon {
text: "\ue7f7"
}
StyledText {
id: appId
text: root.notification?.appName ? root.notification.appName : ''
opacity: 0.4
}
}
ColumnLayout {
spacing: 0
Layout.rightMargin: 40
StyledText {
id: title
Layout.bottomMargin: 0
Layout.topMargin: 5
Layout.alignment: Qt.AlignBottom
Layout.fillWidth: true
text: root.notification?.summary == null ? '' : root.notification.summary
elide: Text.ElideRight
}
StyledText {
id: body
Layout.alignment: Qt.AlignBottom
text: root.notification?.body ? root.notification.body : ''
elide: Text.ElideRight
maximumLineCount: 1
Layout.fillWidth: true
opacity: 0.6
}
}
}
}
acceptedButtons: Qt.LeftButton
cursorShape: Qt.PointingHandCursor
hoverEnabled: true
onEntered: {
root.color = Colors.base03;
}
onExited: {
root.color = Colors.base01;
}
onClicked: {
root.notification ? root.notification.dismiss() : '';
}
}
}

View file

@ -0,0 +1,92 @@
import Quickshell
import Quickshell.Widgets
import QtQuick.Layouts
import QtQuick
import qs
import qs.settings
import qs.widgets
WrapperRectangle {
id: root
required property var notification
required property ShellScreen nScreen
implicitWidth: nScreen.width / 6
implicitHeight: 100
radius: Config.rounding
anchors.right: parent?.right
color: Colors.barBg
clip: true
Timer {
id: dismissTimer
running: true
interval: 5000
repeat: false
onTriggered: root.notification?.dismiss()
}
child: WrapperMouseArea {
id: mouseHandler
child: RowLayout {
spacing: 10
IconImage {
id: appIcon
Layout.leftMargin: 8
visible: root.notification?.image ? true : false
source: root.notification?.image ? root.notification.image : ''
implicitSize: 64
}
ColumnLayout {
Layout.alignment: Qt.AlignLeft
Layout.fillWidth: true
Layout.preferredWidth: 0
Layout.fillHeight: true
Layout.leftMargin: appIcon.visible ? 0 : 16
RowLayout {
Layout.alignment: Qt.AlignTop
MaterialIcon {
text: "\ue7f7"
font.pixelSize: 12
}
StyledText {
id: appId
text: root.notification?.appName ? root.notification.appName : ''
opacity: 0.4
}
}
ColumnLayout {
spacing: 0
Layout.rightMargin: 40
StyledText {
id: title
Layout.bottomMargin: 0
Layout.topMargin: 5
Layout.alignment: Qt.AlignBottom
Layout.fillWidth: true
text: root.notification?.summary == null ? '' : root.notification.summary
elide: Text.ElideRight
}
StyledText {
id: body
Layout.alignment: Qt.AlignBottom
text: root.notification?.body ? root.notification.body : ''
elide: Text.ElideRight
maximumLineCount: 1
Layout.fillWidth: true
opacity: 0.6
}
}
}
}
acceptedButtons: Qt.LeftButton
cursorShape: Qt.PointingHandCursor
hoverEnabled: true
onEntered: {
root.color = Colors.base03;
}
onExited: {
root.color = Colors.base01;
}
onClicked: {
root.notification ? root.notification.dismiss() : '';
}
}
}

View file

@ -0,0 +1,38 @@
pragma ComponentBehavior: Bound
import Quickshell
import QtQuick
import Quickshell.Wayland
import qs.settings
import Quickshell.Hyprland
Variants {
model: Quickshell.screens
delegate: WlrLayershell {
required property ShellScreen modelData
id: notiPopup
exclusionMode: ExclusionMode.Ignore
layer: WlrLayer.Overlay
screen: modelData
anchors {
top: true
right: true
}
margins.top: Config.barHeight + 8 + (Config.floating ? 10 : 0)
margins.right: 8
implicitHeight: notiList.contentHeight
implicitWidth: modelData.width / 6
color: 'transparent'
visible: NotiServer.notifications.values.length > 0
ListView {
id: notiList
anchors.fill: parent
model: NotiServer.notifications
spacing: 6
delegate: NotiCard {
required property var modelData
nScreen: notiPopup.screen
notification: modelData
}
}
}
}

View file

@ -0,0 +1,46 @@
pragma ComponentBehavior: Bound
import Quickshell
import QtQuick
import Quickshell.Wayland
import qs.settings
import Quickshell.Hyprland
WlrLayershell {
id: notiPopup
property ShellScreen activeScreen: getActiveScreen()
function getActiveScreen() {
let current = Quickshell.screens[0];
for (let i = 0; i < Quickshell.screens.length; i++) {
current = Quickshell.screens[i];
if (Hyprland.monitorFor(current) == Hyprland.focusedMonitor) {
return current;
}
}
return current;
}
exclusionMode: ExclusionMode.Ignore
layer: WlrLayer.Overlay
screen: activeScreen
anchors {
top: true
right: true
}
margins.top: Config.barHeight + 8 + (Config.floating ? 10 : 0)
margins.right: 8
implicitHeight: notiList.contentHeight
implicitWidth: activeScreen.width / 6
color: 'transparent'
visible: NotiServer.notifications.values.length > 0
ListView {
id: notiList
anchors.fill: parent
model: NotiServer.notifications
spacing: 6
delegate: NotiCard {
required property var modelData
nScreen: notiPopup.activeScreen
notification: modelData
}
}
}

View file

@ -0,0 +1,18 @@
pragma Singleton
import Quickshell
import Quickshell.Services.Notifications
import QtQuick
Singleton {
id: root
property alias notifications: server.trackedNotifications
NotificationServer {
id: server
imageSupported: true
bodyImagesSupported: true
onNotification: notification => {
notification.tracked = true;
}
}
}

View file

@ -0,0 +1,18 @@
pragma Singleton
import Quickshell
import Quickshell.Services.Notifications
import QtQuick
Singleton {
id: root
property alias notifications: server.trackedNotifications
NotificationServer {
id: server
imageSupported: true
bodyImagesSupported: true
onNotification: notification => {
notification.tracked = true;
}
}
}