mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-10-15 07:44:01 -04:00
settings: stop repeating the page title as the first card label translations: index untitled cards by their page, not a nested row fixes #3604 fixes #3609
456 lines
21 KiB
QML
456 lines
21 KiB
QML
import QtQuick
|
|
import qs.Common
|
|
import qs.Services
|
|
import qs.Widgets
|
|
import qs.Modules.Settings.Widgets
|
|
|
|
Item {
|
|
id: root
|
|
|
|
function indexedRules(predicate) {
|
|
return (SettingsData.notificationRules || []).map((rule, index) => ({
|
|
rule: rule,
|
|
index: index
|
|
})).filter(entry => predicate(entry.rule));
|
|
}
|
|
|
|
readonly property var mutedRules: indexedRules(rule => (rule.action || "").toString().toLowerCase() === "mute")
|
|
|
|
readonly property var notificationRuleFieldOptions: [
|
|
{
|
|
value: "appName",
|
|
label: I18n.tr("App names", "notification rule match field option")
|
|
},
|
|
{
|
|
value: "desktopEntry",
|
|
label: I18n.tr("Desktop Entry", "notification rule match field option")
|
|
},
|
|
{
|
|
value: "summary",
|
|
label: I18n.tr("Summary", "notification rule match field option")
|
|
},
|
|
{
|
|
value: "body",
|
|
label: I18n.tr("Body", "notification rule match field option")
|
|
}
|
|
]
|
|
|
|
readonly property var notificationRuleMatchTypeOptions: [
|
|
{
|
|
value: "contains",
|
|
label: I18n.tr("Contains", "notification rule match type option")
|
|
},
|
|
{
|
|
value: "exact",
|
|
label: I18n.tr("Exact", "notification rule match type option")
|
|
},
|
|
{
|
|
value: "regex",
|
|
label: I18n.tr("Regex", "notification rule match type option")
|
|
}
|
|
]
|
|
|
|
readonly property var notificationRuleActionOptions: [
|
|
{
|
|
value: "default",
|
|
label: I18n.tr("Default", "notification rule action option")
|
|
},
|
|
{
|
|
value: "mute",
|
|
label: I18n.tr("Mute Popups", "notification rule action option")
|
|
},
|
|
{
|
|
value: "ignore",
|
|
label: I18n.tr("Ignore Completely", "notification rule action option")
|
|
},
|
|
{
|
|
value: "popup_only",
|
|
label: I18n.tr("Popup Only", "notification rule action option")
|
|
},
|
|
{
|
|
value: "no_history",
|
|
label: I18n.tr("No History", "notification rule action option")
|
|
}
|
|
]
|
|
|
|
readonly property var notificationRuleUrgencyOptions: [
|
|
{
|
|
value: "default",
|
|
label: I18n.tr("Default", "notification rule urgency option")
|
|
},
|
|
{
|
|
value: "low",
|
|
label: I18n.tr("Low Priority", "notification rule urgency option")
|
|
},
|
|
{
|
|
value: "normal",
|
|
label: I18n.tr("Normal Priority", "notification rule urgency option")
|
|
},
|
|
{
|
|
value: "critical",
|
|
label: I18n.tr("Critical Priority", "notification rule urgency option")
|
|
}
|
|
]
|
|
|
|
function getRuleOptionLabel(options, value, fallback) {
|
|
for (let i = 0; i < options.length; i++) {
|
|
if (options[i].value === value)
|
|
return options[i].label;
|
|
}
|
|
return fallback;
|
|
}
|
|
|
|
function getRuleOptionValue(options, label, fallback) {
|
|
for (let i = 0; i < options.length; i++) {
|
|
if (options[i].label === label)
|
|
return options[i].value;
|
|
}
|
|
return fallback;
|
|
}
|
|
|
|
SettingsPage {
|
|
id: mainColumn
|
|
|
|
SettingsCard {
|
|
id: notificationRulesCard
|
|
width: parent.width
|
|
iconName: "rule_settings"
|
|
title: I18n.tr("Notification rules")
|
|
settingKey: "notificationRules"
|
|
tags: ["notification", "rules", "mute", "ignore", "priority", "regex", "history"]
|
|
|
|
headerActions: DankActionButton {
|
|
buttonSize: 36
|
|
iconName: "restart_alt"
|
|
tooltipText: I18n.tr("Reset to default")
|
|
iconSize: 20
|
|
visible: JSON.stringify(SettingsData.notificationRules) !== JSON.stringify(SettingsData.getDefaultNotificationRules())
|
|
iconColor: Theme.surfaceVariantText
|
|
onClicked: SettingsData.resetNotificationRules()
|
|
}
|
|
|
|
SettingsRow {
|
|
body: Column {
|
|
width: parent.width
|
|
spacing: Theme.spacingS
|
|
|
|
StyledText {
|
|
text: I18n.tr("The Default action only overrides priority")
|
|
font.pixelSize: Theme.fontSizeSmall
|
|
color: Theme.surfaceVariantText
|
|
wrapMode: Text.WordWrap
|
|
width: parent.width
|
|
bottomPadding: Theme.spacingS
|
|
}
|
|
|
|
Repeater {
|
|
model: SettingsData.notificationRules
|
|
|
|
delegate: Rectangle {
|
|
id: ruleItem
|
|
width: parent.width
|
|
height: ruleColumn.implicitHeight + Theme.spacingM
|
|
radius: Theme.cornerRadius
|
|
color: Theme.floatingWindowFieldColor
|
|
|
|
Column {
|
|
id: ruleColumn
|
|
anchors.fill: parent
|
|
anchors.margins: Theme.spacingS
|
|
spacing: Theme.spacingS
|
|
|
|
Row {
|
|
width: parent.width
|
|
spacing: Theme.spacingS
|
|
|
|
StyledText {
|
|
id: ruleLabel
|
|
text: I18n.tr("Rule %1", "notification rule heading, %1 is the rule number").arg(index + 1)
|
|
font.pixelSize: Theme.fontSizeSmall
|
|
color: Theme.surfaceVariantText
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
}
|
|
|
|
Item {
|
|
width: Math.max(0, parent.width - ruleLabel.implicitWidth - enableToggle.width - deleteBtn.width - Theme.spacingS * 3)
|
|
height: 1
|
|
}
|
|
|
|
DankToggle {
|
|
id: enableToggle
|
|
width: 40
|
|
height: 24
|
|
hideText: true
|
|
checked: modelData.enabled !== false
|
|
onToggled: checked => SettingsData.updateNotificationRuleField(index, "enabled", checked)
|
|
}
|
|
|
|
Item {
|
|
id: deleteBtn
|
|
Accessible.role: Accessible.Button
|
|
Accessible.name: I18n.tr("Remove")
|
|
width: 28
|
|
height: 28
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
|
|
Rectangle {
|
|
anchors.fill: parent
|
|
radius: Theme.cornerRadius
|
|
color: deleteArea.containsMouse ? Theme.withAlpha(Theme.error, 0.2) : Theme.withAlpha(Theme.error, 0)
|
|
}
|
|
|
|
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(index)
|
|
}
|
|
}
|
|
}
|
|
|
|
Column {
|
|
width: parent.width
|
|
spacing: Theme.spacingXXS
|
|
|
|
DankTextField {
|
|
outlined: true
|
|
leftIconName: "filter_list"
|
|
labelText: I18n.tr("Pattern")
|
|
width: parent.width
|
|
text: modelData.pattern || ""
|
|
font.pixelSize: Theme.fontSizeSmall
|
|
onEditingFinished: SettingsData.updateNotificationRuleField(index, "pattern", text)
|
|
}
|
|
}
|
|
|
|
Row {
|
|
width: parent.width
|
|
spacing: Theme.spacingS
|
|
|
|
Column {
|
|
width: (parent.width - Theme.spacingS * 3) / 4
|
|
spacing: Theme.spacingXXS
|
|
|
|
StyledText {
|
|
text: I18n.tr("Field", "notification rule dropdown label, which notification field to match")
|
|
font.pixelSize: Theme.fontSizeSmall - 1
|
|
color: Theme.surfaceVariantText
|
|
}
|
|
|
|
DankDropdown {
|
|
width: parent.width
|
|
compactMode: true
|
|
dropdownWidth: parent.width
|
|
popupWidth: 165
|
|
currentValue: root.getRuleOptionLabel(root.notificationRuleFieldOptions, modelData.field, root.notificationRuleFieldOptions[0].label)
|
|
options: root.notificationRuleFieldOptions.map(o => o.label)
|
|
onValueChanged: value => SettingsData.updateNotificationRuleField(index, "field", root.getRuleOptionValue(root.notificationRuleFieldOptions, value, "appName"))
|
|
}
|
|
}
|
|
|
|
Column {
|
|
width: (parent.width - Theme.spacingS * 3) / 4
|
|
spacing: Theme.spacingXXS
|
|
|
|
StyledText {
|
|
text: I18n.tr("Type")
|
|
font.pixelSize: Theme.fontSizeSmall - 1
|
|
color: Theme.surfaceVariantText
|
|
}
|
|
|
|
DankDropdown {
|
|
width: parent.width
|
|
compactMode: true
|
|
dropdownWidth: parent.width
|
|
currentValue: root.getRuleOptionLabel(root.notificationRuleMatchTypeOptions, modelData.matchType, root.notificationRuleMatchTypeOptions[0].label)
|
|
options: root.notificationRuleMatchTypeOptions.map(o => o.label)
|
|
onValueChanged: value => SettingsData.updateNotificationRuleField(index, "matchType", root.getRuleOptionValue(root.notificationRuleMatchTypeOptions, value, "contains"))
|
|
}
|
|
}
|
|
|
|
Column {
|
|
width: (parent.width - Theme.spacingS * 3) / 4
|
|
spacing: Theme.spacingXXS
|
|
|
|
StyledText {
|
|
text: I18n.tr("Action", "noun, dropdown label for what a notification rule or keybind does")
|
|
font.pixelSize: Theme.fontSizeSmall - 1
|
|
color: Theme.surfaceVariantText
|
|
}
|
|
|
|
DankDropdown {
|
|
width: parent.width
|
|
compactMode: true
|
|
dropdownWidth: parent.width
|
|
popupWidth: 170
|
|
currentValue: root.getRuleOptionLabel(root.notificationRuleActionOptions, modelData.action, root.notificationRuleActionOptions[0].label)
|
|
options: root.notificationRuleActionOptions.map(o => o.label)
|
|
onValueChanged: value => SettingsData.updateNotificationRuleField(index, "action", root.getRuleOptionValue(root.notificationRuleActionOptions, value, "default"))
|
|
}
|
|
}
|
|
|
|
Column {
|
|
width: (parent.width - Theme.spacingS * 3) / 4
|
|
spacing: Theme.spacingXXS
|
|
|
|
StyledText {
|
|
text: I18n.tr("Priority", "notification rule dropdown label, urgency assigned to matches")
|
|
font.pixelSize: Theme.fontSizeSmall - 1
|
|
color: Theme.surfaceVariantText
|
|
}
|
|
|
|
DankDropdown {
|
|
width: parent.width
|
|
compactMode: true
|
|
dropdownWidth: parent.width
|
|
popupWidth: 165
|
|
currentValue: root.getRuleOptionLabel(root.notificationRuleUrgencyOptions, modelData.urgency, root.notificationRuleUrgencyOptions[0].label)
|
|
options: root.notificationRuleUrgencyOptions.map(o => o.label)
|
|
onValueChanged: value => SettingsData.updateNotificationRuleField(index, "urgency", root.getRuleOptionValue(root.notificationRuleUrgencyOptions, value, "default"))
|
|
}
|
|
}
|
|
}
|
|
|
|
Row {
|
|
width: parent.width
|
|
spacing: Theme.spacingS
|
|
|
|
StyledText {
|
|
id: bypassDndLabel
|
|
text: I18n.tr("Allow in Do Not Disturb")
|
|
font.pixelSize: Theme.fontSizeSmall - 1
|
|
color: Theme.surfaceVariantText
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
}
|
|
|
|
Item {
|
|
width: Math.max(0, parent.width - bypassDndLabel.implicitWidth - bypassDndToggle.width - Theme.spacingS * 2)
|
|
height: 1
|
|
}
|
|
|
|
DankToggle {
|
|
id: bypassDndToggle
|
|
width: 40
|
|
height: 24
|
|
hideText: true
|
|
checked: modelData.bypassDnd === true
|
|
onToggled: checked => SettingsData.updateNotificationRuleField(index, "bypassDnd", checked)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
SettingsCard {
|
|
iconName: "volume_off"
|
|
title: I18n.tr("Muted apps")
|
|
settingKey: "mutedApps"
|
|
tags: ["notification", "mute", "unmute", "popup"]
|
|
|
|
SettingsRow {
|
|
body: 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.floatingWindowFieldColor
|
|
|
|
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 - mutedDeleteBtn.width - Theme.spacingS * 5)
|
|
height: 1
|
|
}
|
|
|
|
DankButton {
|
|
id: unmuteBtn
|
|
text: I18n.tr("Unmute")
|
|
backgroundColor: Theme.chipSurface
|
|
textColor: Theme.primary
|
|
onClicked: SettingsData.removeNotificationRule(modelData.index)
|
|
}
|
|
|
|
Item {
|
|
id: mutedDeleteBtn
|
|
Accessible.role: Accessible.Button
|
|
Accessible.name: I18n.tr("Remove")
|
|
width: 28
|
|
height: 28
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
|
|
Rectangle {
|
|
anchors.fill: parent
|
|
radius: Theme.cornerRadius
|
|
color: mutedDeleteArea.containsMouse ? Theme.withAlpha(Theme.error, 0.2) : Theme.withAlpha(Theme.error, 0)
|
|
}
|
|
|
|
DankIcon {
|
|
anchors.centerIn: parent
|
|
name: "delete"
|
|
size: 18
|
|
color: mutedDeleteArea.containsMouse ? Theme.error : Theme.surfaceVariantText
|
|
}
|
|
|
|
MouseArea {
|
|
id: mutedDeleteArea
|
|
anchors.fill: parent
|
|
hoverEnabled: true
|
|
cursorShape: Qt.PointingHandCursor
|
|
onClicked: SettingsData.removeNotificationRule(modelData.index)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
SettingsFabBar {
|
|
DankFab {
|
|
text: I18n.tr("Add rule")
|
|
iconName: "add"
|
|
onClicked: SettingsData.addNotificationRule()
|
|
}
|
|
}
|
|
}
|
|
}
|