diff --git a/modules/notifications/NotiCard.qml b/modules/notifications/NotiCard.qml new file mode 100644 index 0000000..d10ac82 --- /dev/null +++ b/modules/notifications/NotiCard.qml @@ -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() : ''; + } + } +} diff --git a/modules/notifications/NotiCard.qml~ b/modules/notifications/NotiCard.qml~ new file mode 100644 index 0000000..168591a --- /dev/null +++ b/modules/notifications/NotiCard.qml~ @@ -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() : ''; + } + } +} diff --git a/modules/notifications/NotiPopup.qml b/modules/notifications/NotiPopup.qml new file mode 100644 index 0000000..b03803b --- /dev/null +++ b/modules/notifications/NotiPopup.qml @@ -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 + } + } + } +} diff --git a/modules/notifications/NotiPopup.qml~ b/modules/notifications/NotiPopup.qml~ new file mode 100644 index 0000000..ac509e8 --- /dev/null +++ b/modules/notifications/NotiPopup.qml~ @@ -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 + } + } +} diff --git a/modules/notifications/NotiServer.qml b/modules/notifications/NotiServer.qml new file mode 100644 index 0000000..db79793 --- /dev/null +++ b/modules/notifications/NotiServer.qml @@ -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; + } + } +} diff --git a/modules/notifications/NotiServer.qml~ b/modules/notifications/NotiServer.qml~ new file mode 100644 index 0000000..db79793 --- /dev/null +++ b/modules/notifications/NotiServer.qml~ @@ -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; + } + } +} diff --git a/shell.qml b/shell.qml index 52a3fd4..ac48f5a 100644 --- a/shell.qml +++ b/shell.qml @@ -1,9 +1,10 @@ import Quickshell import qs.modules.bar import qs.modules.wallpaper - +import qs.modules.notifications ShellRoot { Bar {} Wallpaper {} + NotiPopup {} }