1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-04-05 05:12:05 -04:00

notifications: Update Material 3 baselines

- New right-click to mute option
- New independent Notification Animation settings
This commit is contained in:
purian23
2026-02-12 22:16:16 -05:00
committed by bbedward
parent 8399d64c2d
commit 0ffeed3ff0
11 changed files with 350 additions and 48 deletions

View File

@@ -1,4 +1,5 @@
import QtQuick
import QtQuick.Controls
import Quickshell
import Quickshell.Services.Notifications
import qs.Common
@@ -215,26 +216,22 @@ Rectangle {
spacing: compactMode ? 1 : 2
StyledText {
width: parent.width
text: {
const timeStr = (notificationGroup && notificationGroup.latestNotification && notificationGroup.latestNotification.timeStr) || "";
const appName = (notificationGroup && notificationGroup.appName) || "";
return timeStr.length > 0 ? `${appName} ${timeStr}` : appName;
}
color: Theme.surfaceVariantText
font.pixelSize: Theme.fontSizeSmall
text: (notificationGroup && notificationGroup.latestNotification && notificationGroup.latestNotification.summary) || ""
color: Theme.surfaceText
font.pixelSize: Theme.fontSizeMedium
font.weight: Font.Medium
width: parent.width
elide: Text.ElideRight
maximumLineCount: 1
visible: text.length > 0
}
StyledText {
text: (notificationGroup && notificationGroup.latestNotification && notificationGroup.latestNotification.summary) || ""
color: Theme.surfaceText
font.pixelSize: Theme.fontSizeMedium
font.weight: Font.Medium
width: parent.width
text: (notificationGroup && notificationGroup.latestNotification && notificationGroup.latestNotification.timeStr) || ""
color: Theme.surfaceVariantText
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium
elide: Text.ElideRight
maximumLineCount: 1
visible: text.length > 0
@@ -541,7 +538,7 @@ Rectangle {
StyledText {
id: expandedActionText
text: {
const baseText = modelData.text || "View";
const baseText = modelData.text || "Open";
if (keyboardNavigationActive && (isGroupSelected || selectedNotificationIndex >= 0))
return `${baseText} (${index + 1})`;
return baseText;
@@ -624,7 +621,7 @@ Rectangle {
StyledText {
id: collapsedActionText
text: {
const baseText = modelData.text || "View";
const baseText = modelData.text || "Open";
if (keyboardNavigationActive && isGroupSelected) {
return `${baseText} (${index + 1})`;
}
@@ -733,9 +730,9 @@ Rectangle {
Behavior on height {
enabled: root.userInitiatedExpansion && root.animateExpansion
NumberAnimation {
duration: Theme.expressiveDurations.normal
duration: root.expanded ? Theme.notificationExpandDuration : Theme.notificationCollapseDuration
easing.type: Easing.BezierSpline
easing.bezierCurve: Theme.expressiveCurves.standard
easing.bezierCurve: root.expanded ? Theme.expressiveCurves.emphasizedDecel : Theme.expressiveCurves.emphasizedAccel
onRunningChanged: {
if (running) {
root.isAnimating = true;
@@ -746,4 +743,71 @@ Rectangle {
}
}
}
Menu {
id: notificationCardContextMenu
width: 220
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent
background: Rectangle {
color: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
radius: Theme.cornerRadius
border.width: 0
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
}
MenuItem {
text: I18n.tr("Mute popups for %1").arg(notificationGroup?.appName || I18n.tr("this app"))
contentItem: StyledText {
text: parent.text
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
leftPadding: Theme.spacingS
verticalAlignment: Text.AlignVCenter
}
background: Rectangle {
color: parent.hovered ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : "transparent"
radius: Theme.cornerRadius / 2
}
onTriggered: {
const appName = notificationGroup?.appName || "";
const desktopEntry = notificationGroup?.latestNotification?.desktopEntry || "";
SettingsData.addMuteRuleForApp(appName, desktopEntry);
NotificationService.dismissGroup(notificationGroup?.key || "");
}
}
MenuItem {
text: I18n.tr("Dismiss")
contentItem: StyledText {
text: parent.text
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
leftPadding: Theme.spacingS
verticalAlignment: Text.AlignVCenter
}
background: Rectangle {
color: parent.hovered ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : "transparent"
radius: Theme.cornerRadius / 2
}
onTriggered: NotificationService.dismissGroup(notificationGroup?.key || "")
}
}
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.RightButton
z: 10
onClicked: mouse => {
if (mouse.button === Qt.RightButton && notificationGroup) {
notificationCardContextMenu.popup();
}
}
}
}

View File

@@ -20,7 +20,7 @@ DankPopout {
}
}
popupWidth: 400
popupWidth: triggerScreen ? Math.min(500, Math.max(380, triggerScreen.width - 48)) : 400
popupHeight: contentLoader.item ? contentLoader.item.implicitHeight : 400
positioning: ""
animationScaleCollapsed: 1.0

View File

@@ -99,7 +99,7 @@ PanelWindow {
WlrLayershell.exclusiveZone: -1
WlrLayershell.keyboardFocus: WlrKeyboardFocus.None
color: "transparent"
implicitWidth: 400
implicitWidth: screen ? Math.min(420, Math.max(320, screen.width * 0.25)) : 400
implicitHeight: {
if (!descriptionExpanded)
return basePopupHeight;
@@ -404,17 +404,11 @@ PanelWindow {
spacing: compactMode ? 1 : 2
StyledText {
width: parent.width
text: {
if (!notificationData)
return "";
const appName = notificationData.appName || "";
const timeStr = notificationData.timeStr || "";
return timeStr.length > 0 ? appName + " • " + timeStr : appName;
}
color: Theme.surfaceVariantText
font.pixelSize: Theme.fontSizeSmall
text: notificationData ? (notificationData.summary || "") : ""
color: Theme.surfaceText
font.pixelSize: Theme.fontSizeMedium
font.weight: Font.Medium
width: parent.width
elide: Text.ElideRight
horizontalAlignment: Text.AlignLeft
maximumLineCount: 1
@@ -422,11 +416,11 @@ PanelWindow {
}
StyledText {
text: notificationData ? (notificationData.summary || "") : ""
color: Theme.surfaceText
font.pixelSize: Theme.fontSizeMedium
font.weight: Font.Medium
width: parent.width
text: notificationData ? (notificationData.timeStr || "") : ""
color: Theme.surfaceVariantText
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium
elide: Text.ElideRight
horizontalAlignment: Text.AlignLeft
maximumLineCount: 1
@@ -511,7 +505,7 @@ PanelWindow {
StyledText {
id: actionText
text: modelData.text || "View"
text: modelData.text || "Open"
color: parent.isHovered ? Theme.primary : Theme.surfaceVariantText
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium
@@ -598,7 +592,7 @@ PanelWindow {
if (!notificationData || win.exiting)
return;
if (mouse.button === Qt.RightButton) {
NotificationService.dismissNotification(notificationData);
popupContextMenu.popup();
} else if (mouse.button === Qt.LeftButton) {
if (notificationData.actions && notificationData.actions.length > 0) {
notificationData.actions[0].invoke();
@@ -704,7 +698,7 @@ PanelWindow {
return isLeft ? -Anims.slidePx : Anims.slidePx;
}
to: 0
duration: Theme.mediumDuration
duration: Theme.notificationEnterDuration
easing.type: Easing.BezierSpline
easing.bezierCurve: isTopCenter ? Theme.expressiveCurves.standardDecel : Theme.expressiveCurves.emphasizedDecel
onStopped: {
@@ -735,7 +729,7 @@ PanelWindow {
const isLeft = SettingsData.notificationPopupPosition === SettingsData.Position.Left || SettingsData.notificationPopupPosition === SettingsData.Position.Bottom;
return isLeft ? -Anims.slidePx : Anims.slidePx;
}
duration: Theme.shortDuration
duration: Theme.notificationExitDuration
easing.type: Easing.BezierSpline
easing.bezierCurve: Theme.expressiveCurves.emphasizedAccel
}
@@ -745,7 +739,7 @@ PanelWindow {
property: "opacity"
from: 1
to: 0
duration: Theme.shortDuration
duration: Theme.notificationExitDuration
easing.type: Easing.BezierSpline
easing.bezierCurve: Theme.expressiveCurves.standardAccel
}
@@ -755,7 +749,7 @@ PanelWindow {
property: "scale"
from: 1
to: 0.98
duration: Theme.shortDuration
duration: Theme.notificationExitDuration
easing.type: Easing.BezierSpline
easing.bezierCurve: Theme.expressiveCurves.emphasizedAccel
}
@@ -819,4 +813,64 @@ PanelWindow {
easing.bezierCurve: Theme.expressiveCurves.standardDecel
}
}
Menu {
id: popupContextMenu
width: 220
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent
background: Rectangle {
color: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
radius: Theme.cornerRadius
border.width: 0
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
}
MenuItem {
text: I18n.tr("Mute popups for %1").arg(notificationData?.appName || I18n.tr("this app"))
contentItem: StyledText {
text: parent.text
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
leftPadding: Theme.spacingS
verticalAlignment: Text.AlignVCenter
}
background: Rectangle {
color: parent.hovered ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : "transparent"
radius: Theme.cornerRadius / 2
}
onTriggered: {
const appName = notificationData?.appName || "";
const desktopEntry = notificationData?.desktopEntry || "";
SettingsData.addMuteRuleForApp(appName, desktopEntry);
if (notificationData && !exiting)
NotificationService.dismissNotification(notificationData);
}
}
MenuItem {
text: I18n.tr("Dismiss")
contentItem: StyledText {
text: parent.text
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
leftPadding: Theme.spacingS
verticalAlignment: Text.AlignVCenter
}
background: Rectangle {
color: parent.hovered ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : "transparent"
radius: Theme.cornerRadius / 2
}
onTriggered: {
if (notificationData && !exiting)
NotificationService.dismissNotification(notificationData);
}
}
}
}