import QtQuick import QtQuick.Controls import QtQuick.Layouts import Quickshell import Quickshell.Services.Notifications import Quickshell.Wayland Item { id: root UiTokens { id: theme } property bool open: false property bool dnd: false property bool toastOpen: false property var latest: null property var settings readonly property int count: server.trackedNotifications ? server.trackedNotifications.values.length : 0 signal dismissed() NotificationServer { id: server keepOnReload: true onNotification: function(notification) { notification.tracked = true; root.latest = notification; if (!root.dnd) { root.toastOpen = true; toastTimer.restart(); } } } Timer { id: toastTimer interval: root.settings ? root.settings.notificationPopupDuration : 5000 repeat: false onTriggered: root.toastOpen = false } PanelWindow { visible: root.toastOpen && !root.open && root.latest !== null color: "transparent" anchors { top: true; bottom: true; left: true; right: true } exclusionMode: ExclusionMode.Ignore WlrLayershell.layer: WlrLayer.Overlay WlrLayershell.keyboardFocus: WlrKeyboardFocus.None WlrLayershell.namespace: "quickshell-notification-toast" Rectangle { width: Math.min(390, parent.width - 32) height: 112 anchors.top: parent.top x: root.settings && root.settings.notificationPosition === "top-left" ? 16 : parent.width - width - 16 radius: 16 color: "#181825" border.color: "#313244" border.width: 1 MouseArea { anchors.fill: parent onClicked: { root.toastOpen = false; root.open = true; } } ColumnLayout { anchors.fill: parent anchors.margins: 14 spacing: 3 RowLayout { Layout.fillWidth: true spacing: 8 Label { text: root.latest ? root.latest.appName : "" color: "#9399b2" font.pixelSize: 11 Layout.fillWidth: true elide: Text.ElideRight } CCButton { theme: theme text: "Close" onClicked: root.toastOpen = false } } Label { text: root.latest ? root.latest.summary : "" color: "#cdd6f4" font.pixelSize: 16 font.bold: true Layout.fillWidth: true elide: Text.ElideRight } Label { text: root.latest ? root.latest.body : "" color: "#9399b2" Layout.fillWidth: true elide: Text.ElideRight } } } } PanelWindow { visible: root.open color: "transparent" anchors { top: true; bottom: true; left: true; right: true } exclusionMode: ExclusionMode.Ignore WlrLayershell.layer: WlrLayer.Overlay WlrLayershell.keyboardFocus: root.open ? WlrKeyboardFocus.Exclusive : WlrKeyboardFocus.None WlrLayershell.namespace: "quickshell-notification-center" MouseArea { anchors.fill: parent onClicked: root.dismissed() } Rectangle { width: Math.min(430, parent.width - 32) height: Math.min(parent.height - 32, 700) anchors.top: parent.top anchors.right: parent.right anchors.margins: 16 radius: 20 color: "#11111b" border.color: "#313244" border.width: 1 z: 1 MouseArea { anchors.fill: parent onClicked: function(mouse) { mouse.accepted = true } } ColumnLayout { anchors.fill: parent anchors.margins: 18 spacing: 10 RowLayout { Layout.fillWidth: true Label { text: "Notifications" color: "#cdd6f4" font.pixelSize: 22 font.bold: true Layout.fillWidth: true } CCButton { theme: theme text: root.dnd ? "DND on" : "DND off" onClicked: root.dnd = !root.dnd } CCButton { theme: theme text: "Close" onClicked: root.dismissed() } } Label { visible: root.count === 0 text: "No notifications" color: "#9399b2" Layout.alignment: Qt.AlignHCenter Layout.topMargin: 18 } ScrollView { Layout.fillWidth: true Layout.fillHeight: true clip: true ColumnLayout { width: parent.width spacing: 8 Repeater { model: server.trackedNotifications delegate: Rectangle { required property var modelData Layout.fillWidth: true implicitHeight: notificationColumn.implicitHeight + 22 radius: 14 color: "#181825" ColumnLayout { id: notificationColumn anchors.fill: parent anchors.margins: 11 spacing: 3 RowLayout { Layout.fillWidth: true Label { text: modelData.appName color: "#9399b2" font.pixelSize: 11 Layout.fillWidth: true elide: Text.ElideRight } CCButton { theme: theme text: "x" onClicked: modelData.dismiss() } } Label { text: modelData.summary color: "#cdd6f4" font.pixelSize: 15 font.bold: true Layout.fillWidth: true wrapMode: Text.Wrap } Label { text: modelData.body color: "#9399b2" Layout.fillWidth: true wrapMode: Text.Wrap } } } } } } } } } }