diff --git a/dots/.config/quickshell/ii/modules/common/functions/NotificationUtils.qml b/dots/.config/quickshell/ii/modules/common/functions/NotificationUtils.qml
index 8a336e8ad..d6adcc0f6 100644
--- a/dots/.config/quickshell/ii/modules/common/functions/NotificationUtils.qml
+++ b/dots/.config/quickshell/ii/modules/common/functions/NotificationUtils.qml
@@ -84,4 +84,28 @@ Singleton {
// Older dates
return Qt.formatDateTime(messageTime, "MMMM dd");
}
+
+ function processNotificationBody(body, appName) {
+ let processedBody = body
+
+ // Clean Chromium-based browsers notifications - remove first line
+ if (appName) {
+ const lowerApp = appName.toLowerCase()
+ const chromiumBrowsers = [
+ "brave", "chrome", "chromium", "vivaldi", "opera", "microsoft edge"
+ ]
+
+ if (chromiumBrowsers.some(name => lowerApp.includes(name))) {
+ const lines = body.split('\n\n')
+
+ if (lines.length > 1 && lines[0].startsWith(' lowerApp.includes(name))) {
- const lines = body.split('\n\n')
-
- if (lines.length > 1 && lines[0].startsWith('")
+ return NotificationUtils.processNotificationBody(notificationObject.body, notificationObject.appName || notificationObject.summary).replace(/\n/g, "
")
}
}
}
ColumnLayout { // Expanded content
+ id: expandedContentColumn
Layout.fillWidth: true
opacity: root.expanded ? 1 : 0
visible: opacity > 0
@@ -218,8 +197,8 @@ Item { // Notification item area
elide: Text.ElideRight
textFormat: Text.RichText
text: {
- return `` +
- `${processNotificationBody(notificationObject.body, notificationObject.appName || notificationObject.summary).replace(/\n/g, "
")}`
+ return `` +
+ `${NotificationUtils.processNotificationBody(notificationObject.body, notificationObject.appName || notificationObject.summary).replace(/\n/g, "
")}`
}
onLinkActivated: (link) => {
@@ -293,6 +272,8 @@ Item { // Notification item area
id: actionRepeater
model: notificationObject.actions
NotificationActionButton {
+ id: notifAction
+ required property var modelData
Layout.fillWidth: true
buttonText: modelData.text
urgency: notificationObject.urgency
diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/StartButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/StartButton.qml
index f4a15cc00..5ec96eeb4 100644
--- a/dots/.config/quickshell/ii/modules/waffle/bar/StartButton.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/bar/StartButton.qml
@@ -7,6 +7,7 @@ import qs.services
import qs.modules.common
import qs.modules.waffle.looks
+// TODO: Replace the icon with QMLized svg (with /usr/lib/qt6/bin/svgtoqml) for proper micro-animation
AppButton {
id: root
diff --git a/dots/.config/quickshell/ii/modules/waffle/notificationCenter/NotificationCenterContent.qml b/dots/.config/quickshell/ii/modules/waffle/notificationCenter/NotificationCenterContent.qml
index 797cee28a..47ad2f92d 100644
--- a/dots/.config/quickshell/ii/modules/waffle/notificationCenter/NotificationCenterContent.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/notificationCenter/NotificationCenterContent.qml
@@ -20,6 +20,7 @@ WBarAttachedPanelContent {
property bool collapsed: false
contentItem: ColumnLayout {
+ id: contentLayout
anchors {
horizontalCenter: parent.horizontalCenter
top: parent.top
@@ -41,9 +42,24 @@ WBarAttachedPanelContent {
}
contentItem: NotificationPaneContent {
implicitWidth: calendarColumnLayout.implicitWidth
- implicitHeight: Notifications.list.length > 0 ? (notificationArea.height - notificationPane.borderWidth * 2) : 230
+ implicitHeight: {
+ if (Notifications.list.length > 0) {
+ return ((contentLayout.height - calendarPane.height - contentLayout.spacing) - notificationPane.borderWidth * 2)
+ }
+ return 230;
+ }
+ Timer {
+ id: enableTimer
+ interval: Config.options.hacks.arbitraryRaceConditionDelay
+ onTriggered: heightBehavior.enabled = true;
+ }
Behavior on implicitHeight {
+ id: heightBehavior
+ enabled: false
+ Component.onCompleted: {
+ enableTimer.restart();
+ }
animation: Looks.transition.enter.createObject(this)
}
}
@@ -51,6 +67,7 @@ WBarAttachedPanelContent {
}
WPane {
+ id: calendarPane
contentItem: ColumnLayout {
id: calendarColumnLayout
spacing: 0
diff --git a/dots/.config/quickshell/ii/modules/waffle/notificationCenter/WSingleNotification.qml b/dots/.config/quickshell/ii/modules/waffle/notificationCenter/WSingleNotification.qml
index 95780133c..856ddb160 100644
--- a/dots/.config/quickshell/ii/modules/waffle/notificationCenter/WSingleNotification.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/notificationCenter/WSingleNotification.qml
@@ -1,3 +1,4 @@
+pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Layouts
import Quickshell
@@ -41,52 +42,115 @@ MouseArea {
anchors.margins: contentItem.padding
spacing: 19
- RowLayout {
+ // Header
+ SingleNotificationHeader {
Layout.fillWidth: true
+ }
- ExpandButton {
- Layout.topMargin: -2
+ // Content
+ Item {
+ id: actualContent
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ property real spacing: 16
+ implicitHeight: Math.max(contentColumn.implicitHeight, imageLoader.height)
+ implicitWidth: contentColumn.implicitWidth
+
+ Loader {
+ id: imageLoader
+ active: root.notification.image != ""
+ sourceComponent: StyledImage {
+ width: 48
+ height: 48
+ sourceSize.width: width
+ sourceSize.height: height
+ source: root.notification.image
+ }
}
- Item {
- Layout.fillWidth: true
- }
+ ColumnLayout {
+ id: contentColumn
+ anchors {
+ top: parent.top
+ left: parent.left
+ right: parent.right
+ }
+ spacing: 3
- NotificationHeaderButton {
- Layout.rightMargin: 4
- opacity: root.containsMouse ? 1 : 0
- icon.name: "dismiss"
- implicitSize: 12
- onClicked: {
- Qt.callLater(() => {
- Notifications.discardNotification(root.notification?.notificationId);
- });
+ SummaryText {
+ id: summaryText
+ Layout.leftMargin: imageLoader.active ? imageLoader.width + actualContent.spacing : 0
+ }
+ BodyText {
+ Layout.leftMargin: imageLoader.active ? imageLoader.width + actualContent.spacing : 0
+ // onLineLaidOut: (line) => {
+ // if (!imageLoader.active) return;
+ // const dodgeDistance = imageLoader.width + actualContent.spacing;
+ // // print(line.y, dodgeDistance)
+ // if (summaryText.height + line.y > dodgeDistance) {
+ // line.x -= dodgeDistance;
+ // line.width += dodgeDistance;
+ // }
+ // }
}
}
}
- ColumnLayout {
+ // Actions
+ ActionsRow {
Layout.fillWidth: true
- spacing: 3
-
- SummaryText {}
- BodyText {}
}
- AcrylicButton {
- id: groupExpandButton
- visible: root.groupExpandControlMessage !== ""
+ // "+1 notifications" button
+ GroupExpandButton {
Layout.bottomMargin: 2
- horizontalPadding: 10
- implicitHeight: 24
- implicitWidth: expandButtonText.implicitWidth + horizontalPadding * 2
- onClicked: root.groupExpandToggle()
- contentItem: Item {
- WText {
- id: expandButtonText
- anchors.centerIn: parent
- text: root.groupExpandControlMessage
- }
+ }
+ }
+ }
+
+ component SingleNotificationHeader: RowLayout {
+ ExpandButton {
+ Layout.topMargin: -2
+ }
+
+ Item {
+ Layout.fillWidth: true
+ }
+
+ NotificationHeaderButton {
+ Layout.rightMargin: 4
+ opacity: root.containsMouse ? 1 : 0
+ icon.name: "dismiss"
+ implicitSize: 12
+ onClicked: {
+ Qt.callLater(() => {
+ Notifications.discardNotification(root.notification?.notificationId);
+ });
+ }
+ }
+ }
+
+ component ActionsRow: RowLayout {
+ visible: root.expanded && root.notification.actions.length > 0
+ uniformCellSizes: true
+ Repeater {
+ id: actionRepeater
+ model: root.notification.actions
+ delegate: WBorderedButton {
+ id: actionButton
+ Layout.fillHeight: true
+ required property var modelData
+ Layout.fillWidth: true
+ verticalPadding: 16
+ horizontalPadding: 12
+ text: modelData.text
+ implicitHeight: actionButtonText.implicitHeight + verticalPadding * 2
+ contentItem: WText {
+ id: actionButtonText
+ text: actionButton.text
+ font.pixelSize: Looks.font.pixelSize.large
+ horizontalAlignment: Text.AlignHCenter
+ wrapMode: Text.Wrap
}
}
}
@@ -106,8 +170,17 @@ MouseArea {
verticalAlignment: Text.AlignTop
wrapMode: Text.Wrap
maximumLineCount: root.expanded ? 100 : 1
- text: root.notification?.body
+ text: {
+ if (root.expanded)
+ return `` + `${NotificationUtils.processNotificationBody(root.notification.body, root.notification.appName || root.notification.summary).replace(/\n/g, "
")}`;
+ return NotificationUtils.processNotificationBody(root.notification.body, root.notification.appName || root.notification.summary).replace(/\n/g, "
");
+ }
color: Looks.colors.subfg
+ textFormat: root.expanded ? Text.RichText : Text.StyledText
+ onLinkActivated: link => {
+ Qt.openUrlExternally(link);
+ GlobalStates.sidebarRightOpen = false;
+ }
}
component ExpandButton: NotificationHeaderButton {
@@ -140,4 +213,20 @@ MouseArea {
}
}
}
+
+ component GroupExpandButton: AcrylicButton {
+ id: groupExpandButton
+ visible: root.groupExpandControlMessage !== ""
+ horizontalPadding: 10
+ implicitHeight: 24
+ implicitWidth: expandButtonText.implicitWidth + horizontalPadding * 2
+ onClicked: root.groupExpandToggle()
+ contentItem: Item {
+ WText {
+ id: expandButtonText
+ anchors.centerIn: parent
+ text: root.groupExpandControlMessage
+ }
+ }
+ }
}