mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-04-12 16:52:10 -04:00
Add Notification Rules
- Additional right-click ops - Allow for 3rd boy line on init notification popup
This commit is contained in:
@@ -2147,7 +2147,7 @@ Singleton {
|
|||||||
field: "appName",
|
field: "appName",
|
||||||
pattern: "",
|
pattern: "",
|
||||||
matchType: "contains",
|
matchType: "contains",
|
||||||
action: "mute",
|
action: "default",
|
||||||
urgency: "default"
|
urgency: "default"
|
||||||
});
|
});
|
||||||
notificationRules = rules;
|
notificationRules = rules;
|
||||||
@@ -2172,6 +2172,51 @@ Singleton {
|
|||||||
saveSettings();
|
saveSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isAppMuted(appName, desktopEntry) {
|
||||||
|
const rules = notificationRules || [];
|
||||||
|
const pat = (desktopEntry && desktopEntry !== "" ? desktopEntry : appName || "").toString().toLowerCase();
|
||||||
|
if (!pat)
|
||||||
|
return false;
|
||||||
|
for (let i = 0; i < rules.length; i++) {
|
||||||
|
const r = rules[i];
|
||||||
|
if ((r.action || "").toString().toLowerCase() !== "mute" || r.enabled === false)
|
||||||
|
continue;
|
||||||
|
const field = (r.field || "appName").toString().toLowerCase();
|
||||||
|
const rulePat = (r.pattern || "").toString().toLowerCase();
|
||||||
|
if (!rulePat)
|
||||||
|
continue;
|
||||||
|
const useDesktop = field === "desktopentry";
|
||||||
|
const matches = (useDesktop && desktopEntry) ? (desktopEntry.toString().toLowerCase() === rulePat) : (appName && appName.toString().toLowerCase() === rulePat);
|
||||||
|
if (matches)
|
||||||
|
return true;
|
||||||
|
if (rulePat === pat)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeMuteRuleForApp(appName, desktopEntry) {
|
||||||
|
var rules = JSON.parse(JSON.stringify(notificationRules || []));
|
||||||
|
const app = (appName || "").toString().toLowerCase();
|
||||||
|
const desktop = (desktopEntry || "").toString().toLowerCase();
|
||||||
|
if (!app && !desktop)
|
||||||
|
return;
|
||||||
|
for (let i = rules.length - 1; i >= 0; i--) {
|
||||||
|
const r = rules[i];
|
||||||
|
if ((r.action || "").toString().toLowerCase() !== "mute")
|
||||||
|
continue;
|
||||||
|
const rulePat = (r.pattern || "").toString().toLowerCase();
|
||||||
|
if (!rulePat)
|
||||||
|
continue;
|
||||||
|
if (rulePat === app || rulePat === desktop) {
|
||||||
|
rules.splice(i, 1);
|
||||||
|
notificationRules = rules;
|
||||||
|
saveSettings();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function updateNotificationRule(index, ruleData) {
|
function updateNotificationRule(index, ruleData) {
|
||||||
var rules = JSON.parse(JSON.stringify(notificationRules || []));
|
var rules = JSON.parse(JSON.stringify(notificationRules || []));
|
||||||
if (index < 0 || index >= rules.length)
|
if (index < 0 || index >= rules.length)
|
||||||
|
|||||||
@@ -749,7 +749,7 @@ Rectangle {
|
|||||||
|
|
||||||
Menu {
|
Menu {
|
||||||
id: notificationCardContextMenu
|
id: notificationCardContextMenu
|
||||||
width: 220
|
width: 300
|
||||||
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
|
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
|
||||||
|
|
||||||
background: Rectangle {
|
background: Rectangle {
|
||||||
@@ -760,7 +760,9 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
MenuItem {
|
MenuItem {
|
||||||
text: I18n.tr("Mute popups for %1").arg(notificationGroup?.appName || I18n.tr("this app"))
|
id: muteUnmuteItem
|
||||||
|
readonly property bool isMuted: SettingsData.isAppMuted(notificationGroup?.appName || "", notificationGroup?.latestNotification?.desktopEntry || "")
|
||||||
|
text: isMuted ? I18n.tr("Unmute popups for %1").arg(notificationGroup?.appName || I18n.tr("this app")) : I18n.tr("Mute popups for %1").arg(notificationGroup?.appName || I18n.tr("this app"))
|
||||||
|
|
||||||
contentItem: StyledText {
|
contentItem: StyledText {
|
||||||
text: parent.text
|
text: parent.text
|
||||||
@@ -778,8 +780,12 @@ Rectangle {
|
|||||||
onTriggered: {
|
onTriggered: {
|
||||||
const appName = notificationGroup?.appName || "";
|
const appName = notificationGroup?.appName || "";
|
||||||
const desktopEntry = notificationGroup?.latestNotification?.desktopEntry || "";
|
const desktopEntry = notificationGroup?.latestNotification?.desktopEntry || "";
|
||||||
SettingsData.addMuteRuleForApp(appName, desktopEntry);
|
if (isMuted) {
|
||||||
NotificationService.dismissGroup(notificationGroup?.key || "");
|
SettingsData.removeMuteRuleForApp(appName, desktopEntry);
|
||||||
|
} else {
|
||||||
|
SettingsData.addMuteRuleForApp(appName, desktopEntry);
|
||||||
|
NotificationService.dismissGroup(notificationGroup?.key || "");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ PanelWindow {
|
|||||||
readonly property real popupIconSize: compactMode ? 48 : 63
|
readonly property real popupIconSize: compactMode ? 48 : 63
|
||||||
readonly property real contentSpacing: compactMode ? Theme.spacingXS : Theme.spacingS
|
readonly property real contentSpacing: compactMode ? Theme.spacingXS : Theme.spacingS
|
||||||
readonly property real actionButtonHeight: compactMode ? 20 : 24
|
readonly property real actionButtonHeight: compactMode ? 20 : 24
|
||||||
readonly property real collapsedContentHeight: popupIconSize
|
readonly property real collapsedContentHeight: popupIconSize + (compactMode ? 0 : Theme.fontSizeSmall * 1.2)
|
||||||
readonly property real basePopupHeight: cardPadding * 2 + collapsedContentHeight + actionButtonHeight + Theme.spacingS
|
readonly property real basePopupHeight: cardPadding * 2 + collapsedContentHeight + actionButtonHeight + Theme.spacingS
|
||||||
|
|
||||||
signal entered
|
signal entered
|
||||||
@@ -104,9 +104,9 @@ PanelWindow {
|
|||||||
if (!descriptionExpanded)
|
if (!descriptionExpanded)
|
||||||
return basePopupHeight;
|
return basePopupHeight;
|
||||||
const bodyTextHeight = bodyText.contentHeight || 0;
|
const bodyTextHeight = bodyText.contentHeight || 0;
|
||||||
const twoLineHeight = Theme.fontSizeSmall * 1.2 * 2;
|
const collapsedBodyHeight = Theme.fontSizeSmall * 1.2 * (compactMode ? 1 : 3);
|
||||||
if (bodyTextHeight > twoLineHeight + 2)
|
if (bodyTextHeight > collapsedBodyHeight + 2)
|
||||||
return basePopupHeight + bodyTextHeight - twoLineHeight;
|
return basePopupHeight + bodyTextHeight - collapsedBodyHeight;
|
||||||
return basePopupHeight;
|
return basePopupHeight;
|
||||||
}
|
}
|
||||||
onHasValidDataChanged: {
|
onHasValidDataChanged: {
|
||||||
@@ -317,8 +317,8 @@ PanelWindow {
|
|||||||
id: notificationContent
|
id: notificationContent
|
||||||
|
|
||||||
readonly property real expandedTextHeight: bodyText.contentHeight || 0
|
readonly property real expandedTextHeight: bodyText.contentHeight || 0
|
||||||
readonly property real twoLineHeight: Theme.fontSizeSmall * 1.2 * 2
|
readonly property real collapsedBodyHeight: Theme.fontSizeSmall * 1.2 * (compactMode ? 1 : 3)
|
||||||
readonly property real extraHeight: (descriptionExpanded && expandedTextHeight > twoLineHeight + 2) ? (expandedTextHeight - twoLineHeight) : 0
|
readonly property real extraHeight: (descriptionExpanded && expandedTextHeight > collapsedBodyHeight + 2) ? (expandedTextHeight - collapsedBodyHeight) : 0
|
||||||
|
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
@@ -437,7 +437,7 @@ PanelWindow {
|
|||||||
width: parent.width
|
width: parent.width
|
||||||
elide: descriptionExpanded ? Text.ElideNone : Text.ElideRight
|
elide: descriptionExpanded ? Text.ElideNone : Text.ElideRight
|
||||||
horizontalAlignment: Text.AlignLeft
|
horizontalAlignment: Text.AlignLeft
|
||||||
maximumLineCount: descriptionExpanded ? -1 : (compactMode ? 1 : 2)
|
maximumLineCount: descriptionExpanded ? -1 : (compactMode ? 1 : 3)
|
||||||
wrapMode: Text.WordWrap
|
wrapMode: Text.WordWrap
|
||||||
visible: text.length > 0
|
visible: text.length > 0
|
||||||
linkColor: Theme.primary
|
linkColor: Theme.primary
|
||||||
@@ -816,7 +816,7 @@ PanelWindow {
|
|||||||
|
|
||||||
Menu {
|
Menu {
|
||||||
id: popupContextMenu
|
id: popupContextMenu
|
||||||
width: 220
|
width: 300
|
||||||
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
|
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
|
||||||
|
|
||||||
background: Rectangle {
|
background: Rectangle {
|
||||||
@@ -827,7 +827,9 @@ PanelWindow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
MenuItem {
|
MenuItem {
|
||||||
text: I18n.tr("Mute popups for %1").arg(notificationData?.appName || I18n.tr("this app"))
|
id: muteUnmuteItem
|
||||||
|
readonly property bool isMuted: SettingsData.isAppMuted(notificationData?.appName || "", notificationData?.desktopEntry || "")
|
||||||
|
text: isMuted ? I18n.tr("Unmute popups for %1").arg(notificationData?.appName || I18n.tr("this app")) : I18n.tr("Mute popups for %1").arg(notificationData?.appName || I18n.tr("this app"))
|
||||||
|
|
||||||
contentItem: StyledText {
|
contentItem: StyledText {
|
||||||
text: parent.text
|
text: parent.text
|
||||||
@@ -845,9 +847,13 @@ PanelWindow {
|
|||||||
onTriggered: {
|
onTriggered: {
|
||||||
const appName = notificationData?.appName || "";
|
const appName = notificationData?.appName || "";
|
||||||
const desktopEntry = notificationData?.desktopEntry || "";
|
const desktopEntry = notificationData?.desktopEntry || "";
|
||||||
SettingsData.addMuteRuleForApp(appName, desktopEntry);
|
if (isMuted) {
|
||||||
if (notificationData && !exiting)
|
SettingsData.removeMuteRuleForApp(appName, desktopEntry);
|
||||||
NotificationService.dismissNotification(notificationData);
|
} else {
|
||||||
|
SettingsData.addMuteRuleForApp(appName, desktopEntry);
|
||||||
|
if (notificationData && !exiting)
|
||||||
|
NotificationService.dismissNotification(notificationData);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ QtObject {
|
|||||||
readonly property real cardPadding: compactMode ? Theme.spacingS : Theme.spacingM
|
readonly property real cardPadding: compactMode ? Theme.spacingS : Theme.spacingM
|
||||||
readonly property real popupIconSize: compactMode ? 48 : 63
|
readonly property real popupIconSize: compactMode ? 48 : 63
|
||||||
readonly property real actionButtonHeight: compactMode ? 20 : 24
|
readonly property real actionButtonHeight: compactMode ? 20 : 24
|
||||||
readonly property real popupSpacing: 4
|
readonly property real popupSpacing: 8
|
||||||
readonly property int baseNotificationHeight: cardPadding * 2 + popupIconSize + actionButtonHeight + Theme.spacingS + popupSpacing
|
readonly property int baseNotificationHeight: cardPadding * 2 + popupIconSize + actionButtonHeight + Theme.spacingS + popupSpacing
|
||||||
property int maxTargetNotifications: 4
|
property int maxTargetNotifications: 4
|
||||||
property var popupWindows: [] // strong refs to windows (live until exitFinished)
|
property var popupWindows: [] // strong refs to windows (live until exitFinished)
|
||||||
|
|||||||
@@ -6,6 +6,16 @@ import qs.Modules.Settings.Widgets
|
|||||||
Item {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
|
readonly property var mutedRules: {
|
||||||
|
var rules = SettingsData.notificationRules || [];
|
||||||
|
var out = [];
|
||||||
|
for (var i = 0; i < rules.length; i++) {
|
||||||
|
if ((rules[i].action || "").toString().toLowerCase() === "mute")
|
||||||
|
out.push({ rule: rules[i], index: i });
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
readonly property var timeoutOptions: [
|
readonly property var timeoutOptions: [
|
||||||
{
|
{
|
||||||
text: I18n.tr("Never"),
|
text: I18n.tr("Never"),
|
||||||
@@ -478,6 +488,7 @@ Item {
|
|||||||
width: parent.width
|
width: parent.width
|
||||||
compactMode: true
|
compactMode: true
|
||||||
dropdownWidth: parent.width
|
dropdownWidth: parent.width
|
||||||
|
popupWidth: 165
|
||||||
currentValue: root.getRuleOptionLabel(root.notificationRuleFieldOptions, modelData.field, root.notificationRuleFieldOptions[0].label)
|
currentValue: root.getRuleOptionLabel(root.notificationRuleFieldOptions, modelData.field, root.notificationRuleFieldOptions[0].label)
|
||||||
options: root.notificationRuleFieldOptions.map(o => o.label)
|
options: root.notificationRuleFieldOptions.map(o => o.label)
|
||||||
onValueChanged: value => SettingsData.updateNotificationRuleField(index, "field", root.getRuleOptionValue(root.notificationRuleFieldOptions, value, "appName"))
|
onValueChanged: value => SettingsData.updateNotificationRuleField(index, "field", root.getRuleOptionValue(root.notificationRuleFieldOptions, value, "appName"))
|
||||||
@@ -518,6 +529,7 @@ Item {
|
|||||||
width: parent.width
|
width: parent.width
|
||||||
compactMode: true
|
compactMode: true
|
||||||
dropdownWidth: parent.width
|
dropdownWidth: parent.width
|
||||||
|
popupWidth: 170
|
||||||
currentValue: root.getRuleOptionLabel(root.notificationRuleActionOptions, modelData.action, root.notificationRuleActionOptions[0].label)
|
currentValue: root.getRuleOptionLabel(root.notificationRuleActionOptions, modelData.action, root.notificationRuleActionOptions[0].label)
|
||||||
options: root.notificationRuleActionOptions.map(o => o.label)
|
options: root.notificationRuleActionOptions.map(o => o.label)
|
||||||
onValueChanged: value => SettingsData.updateNotificationRuleField(index, "action", root.getRuleOptionValue(root.notificationRuleActionOptions, value, "default"))
|
onValueChanged: value => SettingsData.updateNotificationRuleField(index, "action", root.getRuleOptionValue(root.notificationRuleActionOptions, value, "default"))
|
||||||
@@ -538,6 +550,7 @@ Item {
|
|||||||
width: parent.width
|
width: parent.width
|
||||||
compactMode: true
|
compactMode: true
|
||||||
dropdownWidth: parent.width
|
dropdownWidth: parent.width
|
||||||
|
popupWidth: 165
|
||||||
currentValue: root.getRuleOptionLabel(root.notificationRuleUrgencyOptions, modelData.urgency, root.notificationRuleUrgencyOptions[0].label)
|
currentValue: root.getRuleOptionLabel(root.notificationRuleUrgencyOptions, modelData.urgency, root.notificationRuleUrgencyOptions[0].label)
|
||||||
options: root.notificationRuleUrgencyOptions.map(o => o.label)
|
options: root.notificationRuleUrgencyOptions.map(o => o.label)
|
||||||
onValueChanged: value => SettingsData.updateNotificationRuleField(index, "urgency", root.getRuleOptionValue(root.notificationRuleUrgencyOptions, value, "default"))
|
onValueChanged: value => SettingsData.updateNotificationRuleField(index, "urgency", root.getRuleOptionValue(root.notificationRuleUrgencyOptions, value, "default"))
|
||||||
@@ -550,6 +563,95 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SettingsCard {
|
||||||
|
width: parent.width
|
||||||
|
iconName: "volume_off"
|
||||||
|
title: I18n.tr("Muted Apps")
|
||||||
|
settingKey: "mutedApps"
|
||||||
|
tags: ["notification", "mute", "unmute", "popup"]
|
||||||
|
|
||||||
|
Column {
|
||||||
|
width: parent.width
|
||||||
|
spacing: Theme.spacingS
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
text: mutedRules.length > 0 ? I18n.tr("Apps with notification popups muted. Unmute or delete to remove.") : I18n.tr("No apps muted. Right-click a notification and choose \"Mute popups\" to add one here.")
|
||||||
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
color: Theme.surfaceVariantText
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
width: parent.width
|
||||||
|
bottomPadding: Theme.spacingS
|
||||||
|
}
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
model: mutedRules
|
||||||
|
|
||||||
|
delegate: Rectangle {
|
||||||
|
width: parent.width
|
||||||
|
height: mutedRow.implicitHeight + Theme.spacingS * 2
|
||||||
|
radius: Theme.cornerRadius
|
||||||
|
color: Theme.withAlpha(Theme.surfaceContainer, 0.5)
|
||||||
|
|
||||||
|
Row {
|
||||||
|
id: mutedRow
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.margins: Theme.spacingS
|
||||||
|
spacing: Theme.spacingM
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
id: mutedAppLabel
|
||||||
|
text: (modelData.rule && modelData.rule.pattern) ? modelData.rule.pattern : I18n.tr("Unknown")
|
||||||
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
color: Theme.surfaceText
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
width: Math.max(0, parent.width - parent.spacing - mutedAppLabel.width - unmuteBtn.width - deleteBtn.width - Theme.spacingS * 5)
|
||||||
|
height: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
DankButton {
|
||||||
|
id: unmuteBtn
|
||||||
|
text: I18n.tr("Unmute")
|
||||||
|
backgroundColor: Theme.surfaceContainer
|
||||||
|
textColor: Theme.primary
|
||||||
|
onClicked: SettingsData.removeNotificationRule(modelData.index)
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: deleteBtn
|
||||||
|
width: 28
|
||||||
|
height: 28
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
anchors.fill: parent
|
||||||
|
radius: Theme.cornerRadius
|
||||||
|
color: deleteArea.containsMouse ? Theme.withAlpha(Theme.error, 0.2) : "transparent"
|
||||||
|
}
|
||||||
|
|
||||||
|
DankIcon {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
name: "delete"
|
||||||
|
size: 18
|
||||||
|
color: deleteArea.containsMouse ? Theme.error : Theme.surfaceVariantText
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: deleteArea
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
onClicked: SettingsData.removeNotificationRule(modelData.index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SettingsCard {
|
SettingsCard {
|
||||||
width: parent.width
|
width: parent.width
|
||||||
iconName: "lock"
|
iconName: "lock"
|
||||||
|
|||||||
@@ -55,6 +55,10 @@ Item {
|
|||||||
|
|
||||||
signal valueChanged(string value)
|
signal valueChanged(string value)
|
||||||
|
|
||||||
|
function closeDropdownMenu() {
|
||||||
|
dropdownMenu.close();
|
||||||
|
}
|
||||||
|
|
||||||
width: compactMode ? dropdownWidth : parent.width
|
width: compactMode ? dropdownWidth : parent.width
|
||||||
implicitHeight: compactMode ? 40 : Math.max(60, labelColumn.implicitHeight + Theme.spacingM)
|
implicitHeight: compactMode ? 40 : Math.max(60, labelColumn.implicitHeight + Theme.spacingM)
|
||||||
|
|
||||||
@@ -409,7 +413,7 @@ Item {
|
|||||||
onClicked: {
|
onClicked: {
|
||||||
root.currentValue = delegateRoot.modelData;
|
root.currentValue = delegateRoot.modelData;
|
||||||
root.valueChanged(delegateRoot.modelData);
|
root.valueChanged(delegateRoot.modelData);
|
||||||
dropdownMenu.close();
|
root.closeDropdownMenu();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user