Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d4c5dfc135 | ||
|
|
880ee3974f |
+22
@@ -105,6 +105,28 @@ download \
|
|||||||
"$SCRIPT_DIR/modules/jl/assets/correct.svg" \
|
"$SCRIPT_DIR/modules/jl/assets/correct.svg" \
|
||||||
"correct.svg"
|
"correct.svg"
|
||||||
|
|
||||||
|
# ----------------------------
|
||||||
|
# Notification sounds
|
||||||
|
# ----------------------------
|
||||||
|
echo
|
||||||
|
info "Preparing notification sounds..."
|
||||||
|
mkdir -p "$SCRIPT_DIR/assets/sounds"
|
||||||
|
|
||||||
|
download \
|
||||||
|
"https://raw.githubusercontent.com/deepin-community/sound-theme-freedesktop/master/stereo/dialog-information.oga" \
|
||||||
|
"$SCRIPT_DIR/assets/sounds/notification-low.oga" \
|
||||||
|
"notification-low.oga"
|
||||||
|
|
||||||
|
download \
|
||||||
|
"https://raw.githubusercontent.com/deepin-community/sound-theme-freedesktop/master/stereo/dialog-warning.oga" \
|
||||||
|
"$SCRIPT_DIR/assets/sounds/notification-normal.oga" \
|
||||||
|
"notification-normal.oga"
|
||||||
|
|
||||||
|
download \
|
||||||
|
"https://raw.githubusercontent.com/deepin-community/sound-theme-freedesktop/master/stereo/bell.oga" \
|
||||||
|
"$SCRIPT_DIR/assets/sounds/notification-critical.oga" \
|
||||||
|
"notification-critical.oga"
|
||||||
|
|
||||||
# ----------------------------
|
# ----------------------------
|
||||||
# Nerd Font
|
# Nerd Font
|
||||||
# ----------------------------
|
# ----------------------------
|
||||||
|
|||||||
@@ -3,10 +3,13 @@ import Quickshell
|
|||||||
import Quickshell.Hyprland
|
import Quickshell.Hyprland
|
||||||
import "./widgets"
|
import "./widgets"
|
||||||
import "../../config"
|
import "../../config"
|
||||||
|
import "../notifications"
|
||||||
|
|
||||||
PanelWindow {
|
PanelWindow {
|
||||||
id: panel
|
id: panel
|
||||||
|
|
||||||
|
required property var manager
|
||||||
|
|
||||||
color: "transparent"
|
color: "transparent"
|
||||||
|
|
||||||
anchors.top: true
|
anchors.top: true
|
||||||
@@ -47,6 +50,8 @@ PanelWindow {
|
|||||||
|
|
||||||
WindowInfo {}
|
WindowInfo {}
|
||||||
|
|
||||||
|
NotificationIndicator {manager: panel.manager}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Row { // bar widgets center
|
Row { // bar widgets center
|
||||||
|
|||||||
@@ -4,11 +4,14 @@ import Quickshell
|
|||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: bar_root
|
id: bar_root
|
||||||
|
|
||||||
|
required property var manager
|
||||||
|
|
||||||
Repeater { // Bars
|
Repeater { // Bars
|
||||||
model: Quickshell.screens
|
model: Quickshell.screens
|
||||||
delegate: Loader {
|
delegate: Loader {
|
||||||
active: true // loads object
|
active: true // loads object
|
||||||
sourceComponent: Bar {screen: modelData} // creates instance of bar component
|
sourceComponent: Bar {screen: modelData; manager: root.manager} // creates instance of bar component
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,154 @@
|
|||||||
|
import QtQuick
|
||||||
|
import Quickshell
|
||||||
|
import Quickshell.Services.Notifications
|
||||||
|
import "../../config"
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: card
|
||||||
|
|
||||||
|
required property var notification
|
||||||
|
required property var manager
|
||||||
|
|
||||||
|
width: parent.width
|
||||||
|
height: Math.max(64, cardContent.height + 24)
|
||||||
|
radius: Config.radius
|
||||||
|
|
||||||
|
property var urgency: notification.urgency
|
||||||
|
property bool isCritical: urgency === NotificationUrgency.Critical
|
||||||
|
|
||||||
|
color: {
|
||||||
|
if (isCritical) return Qt.alpha(Colors.errorContainer, 0.95)
|
||||||
|
if (urgency === NotificationUrgency.Low) return Qt.alpha(Colors.surfaceContainerHigh, 0.95)
|
||||||
|
return Qt.alpha(Colors.primaryContainer, 0.95)
|
||||||
|
}
|
||||||
|
|
||||||
|
border {
|
||||||
|
width: Config.border_width
|
||||||
|
color: {
|
||||||
|
if (isCritical) return Colors.error
|
||||||
|
if (urgency === NotificationUrgency.Low) return Colors.outline
|
||||||
|
return Colors.primaryContainer_fg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NumberAnimation on opacity {
|
||||||
|
id: fadeInAnim
|
||||||
|
from: 0
|
||||||
|
to: 1
|
||||||
|
duration: 200
|
||||||
|
easing.type: Easing.OutCubic
|
||||||
|
}
|
||||||
|
|
||||||
|
NumberAnimation on x {
|
||||||
|
id: slideInAnim
|
||||||
|
from: parent ? parent.width : 100
|
||||||
|
to: 0
|
||||||
|
duration: 300
|
||||||
|
easing.type: Easing.OutCubic
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
fadeInAnim.start()
|
||||||
|
slideInAnim.start()
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
acceptedButtons: Qt.LeftButton
|
||||||
|
onClicked: {
|
||||||
|
manager.dismissNotification(notification)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Row {
|
||||||
|
id: cardContent
|
||||||
|
anchors {
|
||||||
|
top: parent.top
|
||||||
|
left: parent.left
|
||||||
|
right: parent.right
|
||||||
|
margins: 12
|
||||||
|
}
|
||||||
|
spacing: 10
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: iconContainer
|
||||||
|
width: 28
|
||||||
|
height: 28
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
|
||||||
|
Image {
|
||||||
|
id: notifIcon
|
||||||
|
anchors.fill: parent
|
||||||
|
source: notification.appIcon ? "file://" + notification.appIcon : ""
|
||||||
|
sourceSize.width: 28
|
||||||
|
sourceSize.height: 28
|
||||||
|
asynchronous: true
|
||||||
|
visible: status === Image.Ready
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
text: "\uF0F3"
|
||||||
|
font.pixelSize: 16
|
||||||
|
font.family: Config.font
|
||||||
|
visible: !notifIcon.visible
|
||||||
|
color: Colors.primary_fg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Column {
|
||||||
|
id: textColumn
|
||||||
|
width: parent.width - iconContainer.width - parent.spacing - 20
|
||||||
|
spacing: 3
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
|
||||||
|
Text {
|
||||||
|
id: summaryText
|
||||||
|
width: parent.width
|
||||||
|
text: notification.summary || notification.appName || "Notification"
|
||||||
|
font.pixelSize: 13
|
||||||
|
font.bold: true
|
||||||
|
font.family: Config.font
|
||||||
|
color: {
|
||||||
|
if (isCritical) return Colors.error
|
||||||
|
if (urgency === NotificationUrgency.Low) return Colors.secondaryContainer_fg
|
||||||
|
return Colors.primary
|
||||||
|
}
|
||||||
|
elide: Text.ElideRight
|
||||||
|
maximumLineCount: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
id: bodyText
|
||||||
|
width: parent.width
|
||||||
|
text: notification.body || ""
|
||||||
|
visible: text !== ""
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
font.pixelSize: 11
|
||||||
|
font.family: Config.font
|
||||||
|
color: isCritical ? Colors.errorContainer_fg : Colors.surface_fg
|
||||||
|
maximumLineCount: 2
|
||||||
|
elide: Text.ElideRight
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
text: "\u00D7"
|
||||||
|
font.pixelSize: 16
|
||||||
|
font.bold: true
|
||||||
|
color: isCritical ? Colors.error : Colors.secondary
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
opacity: 0.6
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
hoverEnabled: true
|
||||||
|
onClicked: {
|
||||||
|
manager.dismissNotification(notification)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,233 @@
|
|||||||
|
import QtQuick
|
||||||
|
import Quickshell
|
||||||
|
import Quickshell.Services.Notifications
|
||||||
|
import "../../config"
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: indicator
|
||||||
|
|
||||||
|
required property var manager
|
||||||
|
|
||||||
|
height: bar.height
|
||||||
|
width: indicatorRow.width + Config.spacing_fun(height) * 2
|
||||||
|
|
||||||
|
hoverEnabled: true
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
|
||||||
|
property bool popupOpen: false
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
popupOpen = !popupOpen
|
||||||
|
if (popupOpen) {
|
||||||
|
notifPopup.visible = true
|
||||||
|
} else {
|
||||||
|
notifPopup.visible = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
anchors.fill: parent
|
||||||
|
color: indicator.containsMouse || popupOpen ? Colors.tertiaryContainer : "transparent"
|
||||||
|
radius: Config.radius_fun(indicator.height)
|
||||||
|
border.width: (indicator.containsMouse || popupOpen) ? Config.border_width : 0
|
||||||
|
border.color: (indicator.containsMouse || popupOpen) ? Colors.tertiaryContainer_fg : "transparent"
|
||||||
|
|
||||||
|
Row {
|
||||||
|
id: indicatorRow
|
||||||
|
anchors.centerIn: parent
|
||||||
|
spacing: Config.spacing_fun(indicator.height) / 2
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: iconWrap
|
||||||
|
width: Config.iconSize(indicator.height)
|
||||||
|
height: Config.iconSize(indicator.height)
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
|
||||||
|
Image {
|
||||||
|
id: notifIcon
|
||||||
|
anchors.fill: parent
|
||||||
|
source: (manager.lastNotification && manager.lastNotification.appIcon)
|
||||||
|
? "file://" + manager.lastNotification.appIcon : ""
|
||||||
|
sourceSize.width: Config.iconSize(indicator.height)
|
||||||
|
sourceSize.height: Config.iconSize(indicator.height)
|
||||||
|
asynchronous: true
|
||||||
|
visible: status === Image.Ready
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
text: "\uF0F3"
|
||||||
|
font.pixelSize: Config.iconSize(indicator.height)
|
||||||
|
font.family: Config.font
|
||||||
|
visible: !notifIcon.visible
|
||||||
|
color: indicator.containsMouse ? Colors.tertiary : Colors.secondary
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: countBadge
|
||||||
|
width: Math.max(badgeText.width + 6, 16)
|
||||||
|
height: 16
|
||||||
|
radius: 8
|
||||||
|
visible: manager.notificationCount > 0
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
color: manager.hasCritical ? Colors.error : Colors.primary
|
||||||
|
|
||||||
|
Text {
|
||||||
|
id: badgeText
|
||||||
|
anchors.centerIn: parent
|
||||||
|
text: manager.notificationCount > 99 ? "99+" : manager.notificationCount.toString()
|
||||||
|
font.pixelSize: Config.font_size_tiny(indicator.height)
|
||||||
|
font.family: Config.font
|
||||||
|
font.bold: true
|
||||||
|
color: manager.hasCritical ? Colors.error_fg : Colors.primary_fg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: criticalDot
|
||||||
|
width: 8
|
||||||
|
height: 8
|
||||||
|
radius: 4
|
||||||
|
visible: manager.hasCritical
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
color: Colors.error
|
||||||
|
|
||||||
|
SequentialAnimation on opacity {
|
||||||
|
loops: Animation.Infinite
|
||||||
|
PropertyAnimation { from: 1.0; to: 0.4; duration: 800 }
|
||||||
|
PropertyAnimation { from: 0.4; to: 1.0; duration: 800 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PopupWindow {
|
||||||
|
id: notifPopup
|
||||||
|
visible: indicator.popupOpen
|
||||||
|
color: "transparent"
|
||||||
|
|
||||||
|
anchor {
|
||||||
|
item: indicator
|
||||||
|
edges: Edges.Top | Edges.Left
|
||||||
|
gravity: Edges.Bottom | Edges.Right
|
||||||
|
adjustment: PopupAdjustment.FlipY | PopupAdjustment.SlideX
|
||||||
|
onAnchoring: {
|
||||||
|
anchor.rect.x = (indicator.width - notifPopup.width) / 2
|
||||||
|
anchor.rect.y = indicator.height + 4
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
implicitWidth: 280
|
||||||
|
implicitHeight: Math.max(60, popupContent.height + 24)
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
anchors.fill: parent
|
||||||
|
color: Qt.alpha(Colors.primaryContainer, 0.95)
|
||||||
|
radius: Config.radius
|
||||||
|
border {
|
||||||
|
width: Config.border_width
|
||||||
|
color: Colors.primaryContainer_fg
|
||||||
|
}
|
||||||
|
|
||||||
|
Column {
|
||||||
|
id: popupContent
|
||||||
|
width: parent.width
|
||||||
|
anchors {
|
||||||
|
top: parent.top
|
||||||
|
left: parent.left
|
||||||
|
right: parent.right
|
||||||
|
margins: 12
|
||||||
|
}
|
||||||
|
spacing: 8
|
||||||
|
|
||||||
|
Text {
|
||||||
|
text: "Notifications"
|
||||||
|
font.pixelSize: Config.font_size_small(indicator.height)
|
||||||
|
font.family: Config.font
|
||||||
|
font.bold: true
|
||||||
|
color: Colors.primary
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
visible: manager.notificationCount > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
model: manager.notifications
|
||||||
|
|
||||||
|
delegate: Rectangle {
|
||||||
|
width: parent.width
|
||||||
|
height: delegateText.height + 10
|
||||||
|
radius: Config.small_radius
|
||||||
|
color: Qt.alpha(Colors.surfaceContainerHighest, 0.5)
|
||||||
|
|
||||||
|
property var notif: modelData
|
||||||
|
|
||||||
|
Row {
|
||||||
|
anchors {
|
||||||
|
left: parent.left
|
||||||
|
right: parent.right
|
||||||
|
margins: 6
|
||||||
|
verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
spacing: 6
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
width: 6
|
||||||
|
height: 24
|
||||||
|
radius: 3
|
||||||
|
color: {
|
||||||
|
if (notif.urgency === NotificationUrgency.Critical) return Colors.error
|
||||||
|
if (notif.urgency === NotificationUrgency.Low) return Colors.outline
|
||||||
|
return Colors.primary
|
||||||
|
}
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
Column {
|
||||||
|
width: parent.width - 24
|
||||||
|
spacing: 2
|
||||||
|
|
||||||
|
Text {
|
||||||
|
id: delegateText
|
||||||
|
width: parent.width
|
||||||
|
text: notif.summary || notif.appName || "Notification"
|
||||||
|
font.pixelSize: Config.labelSize(indicator.height)
|
||||||
|
font.family: Config.font
|
||||||
|
font.bold: true
|
||||||
|
color: Colors.surface_fg
|
||||||
|
elide: Text.ElideRight
|
||||||
|
maximumLineCount: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
width: parent.width
|
||||||
|
text: notif.body || ""
|
||||||
|
visible: text !== ""
|
||||||
|
font.pixelSize: Config.font_size_tiny(indicator.height)
|
||||||
|
font.family: Config.font
|
||||||
|
color: Colors.surfaceVariant_fg
|
||||||
|
elide: Text.ElideRight
|
||||||
|
maximumLineCount: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
text: "No notifications"
|
||||||
|
font.pixelSize: Config.font_size_small(indicator.height)
|
||||||
|
font.family: Config.font
|
||||||
|
color: Colors.secondary
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
visible: manager.notificationCount === 0
|
||||||
|
height: 30
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onVisibleChanged: {
|
||||||
|
if (!visible) indicator.popupOpen = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,129 @@
|
|||||||
|
import QtQuick
|
||||||
|
import Quickshell
|
||||||
|
import Quickshell.Io
|
||||||
|
import Quickshell.Services.Notifications
|
||||||
|
import "../../config"
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
NotificationServer {
|
||||||
|
id: notificationServer
|
||||||
|
|
||||||
|
imageSupported: true
|
||||||
|
actionsSupported: true
|
||||||
|
bodyMarkupSupported: false
|
||||||
|
|
||||||
|
onNotification: (notification) => {
|
||||||
|
notification.tracked = true
|
||||||
|
root.onNotificationReceived(notification)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
readonly property ObjectModel notifications: notificationServer.trackedNotifications
|
||||||
|
|
||||||
|
property int notificationCount: 0
|
||||||
|
property var lastNotification: null
|
||||||
|
property bool hasCritical: false
|
||||||
|
|
||||||
|
readonly property string soundDir: Config.configDir + "/assets/sounds"
|
||||||
|
|
||||||
|
property var _trackedIds: ({})
|
||||||
|
property var _dismissTimes: ({})
|
||||||
|
|
||||||
|
function onNotificationReceived(notification) {
|
||||||
|
_trackedIds[notification.id] = true
|
||||||
|
notificationCount = Object.keys(_trackedIds).length
|
||||||
|
lastNotification = notification
|
||||||
|
if (notification.urgency === NotificationUrgency.Critical)
|
||||||
|
hasCritical = true
|
||||||
|
|
||||||
|
playSound(notification.urgency)
|
||||||
|
scheduleDismiss(notification)
|
||||||
|
}
|
||||||
|
|
||||||
|
function playSound(urgency) {
|
||||||
|
var path
|
||||||
|
switch (urgency) {
|
||||||
|
case NotificationUrgency.Low:
|
||||||
|
path = soundDir + "/notification-low.oga"
|
||||||
|
break
|
||||||
|
case NotificationUrgency.Critical:
|
||||||
|
path = soundDir + "/notification-critical.oga"
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
path = soundDir + "/notification-normal.oga"
|
||||||
|
break
|
||||||
|
}
|
||||||
|
soundProc.command = [
|
||||||
|
"sh", "-c",
|
||||||
|
"pw-play \"" + path + "\" 2>/dev/null || paplay \"" + path + "\" 2>/dev/null || ffplay -nodisp -autoexit \"" + path + "\" 2>/dev/null"
|
||||||
|
]
|
||||||
|
soundProc.running = true
|
||||||
|
}
|
||||||
|
|
||||||
|
function scheduleDismiss(notification) {
|
||||||
|
var timeout = notification.expireTimeout
|
||||||
|
if (timeout <= 0) {
|
||||||
|
if (notification.urgency === NotificationUrgency.Critical)
|
||||||
|
timeout = 60
|
||||||
|
else
|
||||||
|
timeout = 5
|
||||||
|
}
|
||||||
|
_dismissTimes[notification.id] = Date.now() / 1000 + timeout
|
||||||
|
if (!refreshTimer.running)
|
||||||
|
refreshTimer.running = true
|
||||||
|
}
|
||||||
|
|
||||||
|
function dismissNotification(notification) {
|
||||||
|
delete _trackedIds[notification.id]
|
||||||
|
delete _dismissTimes[notification.id]
|
||||||
|
notificationCount = Object.keys(_trackedIds).length
|
||||||
|
notification.tracked = false
|
||||||
|
refreshMetadata()
|
||||||
|
}
|
||||||
|
|
||||||
|
function refreshMetadata() {
|
||||||
|
hasCritical = false
|
||||||
|
lastNotification = null
|
||||||
|
for (var i = 0; i < notifications.count; i++) {
|
||||||
|
var n = notifications.get(i)
|
||||||
|
if (_trackedIds[n.id]) {
|
||||||
|
lastNotification = n
|
||||||
|
if (n.urgency === NotificationUrgency.Critical)
|
||||||
|
hasCritical = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (notificationCount === 0) {
|
||||||
|
hasCritical = false
|
||||||
|
lastNotification = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Timer {
|
||||||
|
id: refreshTimer
|
||||||
|
interval: 1000
|
||||||
|
repeat: true
|
||||||
|
onTriggered: {
|
||||||
|
var now = Date.now() / 1000
|
||||||
|
for (var id in _dismissTimes) {
|
||||||
|
if (_dismissTimes[id] <= now) {
|
||||||
|
for (var i = 0; i < notifications.count; i++) {
|
||||||
|
var n = notifications.get(i)
|
||||||
|
if (n.id.toString() === id) {
|
||||||
|
dismissNotification(n)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Object.keys(_trackedIds).length === 0)
|
||||||
|
running = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Process {
|
||||||
|
id: soundProc
|
||||||
|
running: false
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
import QtQuick
|
||||||
|
import Quickshell
|
||||||
|
import Quickshell.Hyprland
|
||||||
|
import Quickshell.Wayland
|
||||||
|
import Quickshell.Services.Notifications
|
||||||
|
import "../../config"
|
||||||
|
|
||||||
|
Variants {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
required property var manager
|
||||||
|
|
||||||
|
model: Quickshell.screens
|
||||||
|
|
||||||
|
delegate: PanelWindow {
|
||||||
|
id: popupWindow
|
||||||
|
screen: modelData
|
||||||
|
color: "transparent"
|
||||||
|
|
||||||
|
anchors.top: true
|
||||||
|
anchors.right: true
|
||||||
|
|
||||||
|
width: 380
|
||||||
|
height: Math.min(implicitHeight, screen.height * 0.6)
|
||||||
|
|
||||||
|
WlrLayershell.layer: WlrLayer.Overlay
|
||||||
|
WlrLayershell.namespace: "notification-popup"
|
||||||
|
|
||||||
|
margins {
|
||||||
|
top: 8
|
||||||
|
right: 8
|
||||||
|
}
|
||||||
|
|
||||||
|
readonly property var hyprMonitor: Hyprland.monitorFor(screen)
|
||||||
|
visible: hyprMonitor === Hyprland.focusedMonitor
|
||||||
|
|
||||||
|
implicitHeight: contentColumn.height
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: Hyprland
|
||||||
|
function onFocusedMonitorChanged() {
|
||||||
|
popupWindow.visible = popupWindow.hyprMonitor === Hyprland.focusedMonitor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: root.manager.notifications
|
||||||
|
function onCountChanged() {
|
||||||
|
popupWindow.visible = popupWindow.hyprMonitor === Hyprland.focusedMonitor
|
||||||
|
&& root.manager.notifications.count > 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Column {
|
||||||
|
id: contentColumn
|
||||||
|
width: parent.width
|
||||||
|
spacing: 8
|
||||||
|
topPadding: 4
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
model: root.manager.notifications
|
||||||
|
|
||||||
|
delegate: NotificationCard {
|
||||||
|
width: contentColumn.width
|
||||||
|
notification: modelData
|
||||||
|
manager: root.manager
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
NotificationManager 1.0 NotificationManager.qml
|
||||||
|
NotificationPopup 1.0 NotificationPopup.qml
|
||||||
|
NotificationIndicator 1.0 NotificationIndicator.qml
|
||||||
|
NotificationCard 1.0 NotificationCard.qml
|
||||||
@@ -3,17 +3,24 @@
|
|||||||
import Quickshell //for PanelWindow
|
import Quickshell //for PanelWindow
|
||||||
import Quickshell.Hyprland
|
import Quickshell.Hyprland
|
||||||
import QtQuick //for Text
|
import QtQuick //for Text
|
||||||
|
import Quickshell.Services.Notifications
|
||||||
import "./modules/bar"
|
import "./modules/bar"
|
||||||
import "./modules/wp"
|
import "./modules/wp"
|
||||||
import "./modules/wlogout"
|
import "./modules/wlogout"
|
||||||
import "./modules/jl"
|
import "./modules/jl"
|
||||||
import "./modules/background"
|
import "./modules/background"
|
||||||
|
import "./modules/notifications"
|
||||||
|
|
||||||
ShellRoot {
|
ShellRoot {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
|
// Notifications
|
||||||
|
NotificationManager { id: notificationManager }
|
||||||
|
|
||||||
|
NotificationPopup { manager: notificationManager }
|
||||||
|
|
||||||
// Bar
|
// Bar
|
||||||
BarLoader {}
|
BarLoader { manager: notificationManager }
|
||||||
|
|
||||||
//Wallpaper picker
|
//Wallpaper picker
|
||||||
WallpaperPickerLoader {}
|
WallpaperPickerLoader {}
|
||||||
|
|||||||
Reference in New Issue
Block a user