mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-10-16 00:04:01 -04:00
489 lines
20 KiB
QML
489 lines
20 KiB
QML
import QtQuick
|
|
import qs.Common
|
|
import qs.Services
|
|
import qs.Widgets
|
|
import qs.Modules.Settings.Widgets
|
|
|
|
Column {
|
|
id: root
|
|
|
|
property var parentModal: null
|
|
|
|
width: parent?.width ?? 0
|
|
spacing: Theme.spacingL
|
|
|
|
function indexedRules(predicate) {
|
|
return (SettingsData.notificationRules || []).map((rule, index) => ({
|
|
rule: rule,
|
|
index: index
|
|
})).filter(entry => predicate(entry.rule));
|
|
}
|
|
|
|
readonly property var dndBypassRules: indexedRules(rule => rule.bypassDnd === true)
|
|
|
|
readonly property var timeoutOptions: [
|
|
{
|
|
text: I18n.tr("Never"),
|
|
value: 0
|
|
},
|
|
{
|
|
text: I18n.duration(1),
|
|
value: 1000
|
|
},
|
|
{
|
|
text: I18n.duration(3),
|
|
value: 3000
|
|
},
|
|
{
|
|
text: I18n.duration(5),
|
|
value: 5000
|
|
},
|
|
{
|
|
text: I18n.duration(8),
|
|
value: 8000
|
|
},
|
|
{
|
|
text: I18n.duration(10),
|
|
value: 10000
|
|
},
|
|
{
|
|
text: I18n.duration(15),
|
|
value: 15000
|
|
},
|
|
{
|
|
text: I18n.duration(30),
|
|
value: 30000
|
|
},
|
|
{
|
|
text: I18n.duration(60),
|
|
value: 60000
|
|
},
|
|
{
|
|
text: I18n.duration(120),
|
|
value: 120000
|
|
},
|
|
{
|
|
text: I18n.duration(300),
|
|
value: 300000
|
|
},
|
|
{
|
|
text: I18n.duration(600),
|
|
value: 600000
|
|
}
|
|
]
|
|
|
|
function getTimeoutText(value) {
|
|
if (value === undefined || value === null || isNaN(value))
|
|
return I18n.duration(5);
|
|
for (let i = 0; i < timeoutOptions.length; i++) {
|
|
if (timeoutOptions[i].value === value)
|
|
return timeoutOptions[i].text;
|
|
}
|
|
if (value === 0)
|
|
return I18n.tr("Never");
|
|
return I18n.duration(value / 1000);
|
|
}
|
|
|
|
function applyTimeout(key, text) {
|
|
const option = timeoutOptions.find(opt => opt.text === text);
|
|
if (option)
|
|
SettingsData.set(key, option.value);
|
|
}
|
|
|
|
SettingsCard {
|
|
iconName: "notifications"
|
|
title: I18n.tr("Popups", "notification settings card title, popup notifications")
|
|
settingKey: "notificationPopups"
|
|
|
|
headerActions: DankButton {
|
|
text: I18n.tr("Preview")
|
|
buttonHeight: Theme.buttonHeightXS
|
|
onClicked: NotificationService.sendTestNotifications()
|
|
}
|
|
|
|
SettingsDropdownRow {
|
|
settingKey: "notificationPopupPosition"
|
|
tags: ["notification", "popup", "position", "screen", "location"]
|
|
text: I18n.tr("Position")
|
|
currentValue: {
|
|
if (SettingsData.notificationPopupPosition === -1)
|
|
return I18n.tr("Top Center", "screen position option");
|
|
switch (SettingsData.notificationPopupPosition) {
|
|
case SettingsData.Position.Top:
|
|
return I18n.tr("Top Right", "screen position option");
|
|
case SettingsData.Position.Bottom:
|
|
return I18n.tr("Bottom Left", "screen position option");
|
|
case SettingsData.Position.Left:
|
|
return I18n.tr("Top Left", "screen position option");
|
|
case SettingsData.Position.Right:
|
|
return I18n.tr("Bottom Right", "screen position option");
|
|
case SettingsData.Position.BottomCenter:
|
|
return I18n.tr("Bottom Center", "screen position option");
|
|
default:
|
|
return I18n.tr("Top Right", "screen position option");
|
|
}
|
|
}
|
|
options: [I18n.tr("Top Right", "screen position option"), I18n.tr("Top Left", "screen position option"), I18n.tr("Top Center", "screen position option"), I18n.tr("Bottom Center", "screen position option"), I18n.tr("Bottom Right", "screen position option"), I18n.tr("Bottom Left", "screen position option")]
|
|
onValueChanged: value => {
|
|
switch (value) {
|
|
case I18n.tr("Top Right", "screen position option"):
|
|
SettingsData.set("notificationPopupPosition", SettingsData.Position.Top);
|
|
break;
|
|
case I18n.tr("Top Left", "screen position option"):
|
|
SettingsData.set("notificationPopupPosition", SettingsData.Position.Left);
|
|
break;
|
|
case I18n.tr("Top Center", "screen position option"):
|
|
SettingsData.set("notificationPopupPosition", -1);
|
|
break;
|
|
case I18n.tr("Bottom Center", "screen position option"):
|
|
SettingsData.set("notificationPopupPosition", SettingsData.Position.BottomCenter);
|
|
break;
|
|
case I18n.tr("Bottom Right", "screen position option"):
|
|
SettingsData.set("notificationPopupPosition", SettingsData.Position.Right);
|
|
break;
|
|
case I18n.tr("Bottom Left", "screen position option"):
|
|
SettingsData.set("notificationPopupPosition", SettingsData.Position.Bottom);
|
|
break;
|
|
}
|
|
NotificationService.sendTestNotifications();
|
|
}
|
|
}
|
|
|
|
SettingsToggleRow {
|
|
settingKey: "notificationFocusedMonitor"
|
|
tags: ["notification", "popup", "focused", "monitor", "display", "screen", "active"]
|
|
text: I18n.tr("Focused display only")
|
|
checked: SettingsData.notificationFocusedMonitor
|
|
onToggled: checked => SettingsData.set("notificationFocusedMonitor", checked)
|
|
}
|
|
|
|
SettingsToggleRow {
|
|
settingKey: "notificationOverlayEnabled"
|
|
tags: ["notification", "overlay", "fullscreen", "priority"]
|
|
text: I18n.tr("Over fullscreen")
|
|
checked: SettingsData.notificationOverlayEnabled
|
|
onToggled: checked => SettingsData.set("notificationOverlayEnabled", checked)
|
|
}
|
|
|
|
SettingsToggleRow {
|
|
settingKey: "notificationCompactMode"
|
|
tags: ["notification", "compact", "size", "display", "mode"]
|
|
text: I18n.tr("Compact")
|
|
checked: SettingsData.notificationCompactMode
|
|
onToggled: checked => SettingsData.set("notificationCompactMode", checked)
|
|
}
|
|
|
|
SettingsToggleRow {
|
|
settingKey: "notificationDedupeEnabled"
|
|
tags: ["notification", "duplicate", "dedupe", "stack", "coalesce", "repeat"]
|
|
text: I18n.tr("Suppress duplicates")
|
|
checked: SettingsData.notificationDedupeEnabled
|
|
onToggled: checked => SettingsData.set("notificationDedupeEnabled", checked)
|
|
}
|
|
|
|
SettingsToggleRow {
|
|
settingKey: "notificationPopupBodyInvokesAction"
|
|
tags: ["notification", "popup", "click", "body", "action", "invoke", "expand", "open"]
|
|
text: I18n.tr("Body click runs default action")
|
|
checked: SettingsData.notificationPopupBodyInvokesAction
|
|
onToggled: checked => SettingsData.set("notificationPopupBodyInvokesAction", checked)
|
|
}
|
|
}
|
|
|
|
SettingsCard {
|
|
title: I18n.tr("Timeouts", "notification settings card title, popup dismiss times per urgency")
|
|
settingKey: "notificationTimeouts"
|
|
tags: ["notification", "timeout", "duration", "expire", "priority"]
|
|
|
|
SettingsDropdownRow {
|
|
settingKey: "notificationTimeoutLow"
|
|
tags: ["notification", "timeout", "low", "priority", "duration"]
|
|
text: I18n.tr("Low")
|
|
currentValue: root.getTimeoutText(SettingsData.notificationTimeoutLow)
|
|
options: root.timeoutOptions.map(opt => opt.text)
|
|
onValueChanged: value => root.applyTimeout("notificationTimeoutLow", value)
|
|
}
|
|
|
|
SettingsDropdownRow {
|
|
settingKey: "notificationTimeoutNormal"
|
|
tags: ["notification", "timeout", "normal", "priority", "duration"]
|
|
text: I18n.tr("Normal")
|
|
currentValue: root.getTimeoutText(SettingsData.notificationTimeoutNormal)
|
|
options: root.timeoutOptions.map(opt => opt.text)
|
|
onValueChanged: value => root.applyTimeout("notificationTimeoutNormal", value)
|
|
}
|
|
|
|
SettingsDropdownRow {
|
|
settingKey: "notificationTimeoutCritical"
|
|
tags: ["notification", "timeout", "critical", "priority", "duration"]
|
|
text: I18n.tr("Critical", "adjective, critical notification urgency row label")
|
|
currentValue: root.getTimeoutText(SettingsData.notificationTimeoutCritical)
|
|
options: root.timeoutOptions.map(opt => opt.text)
|
|
onValueChanged: value => root.applyTimeout("notificationTimeoutCritical", value)
|
|
}
|
|
|
|
SettingsToggleRow {
|
|
settingKey: "notificationIgnoreAppTimeout"
|
|
tags: ["notification", "timeout", "expire", "app", "override", "duration"]
|
|
text: I18n.tr("Ignore app-requested timeout")
|
|
checked: SettingsData.notificationIgnoreAppTimeout
|
|
onToggled: checked => SettingsData.set("notificationIgnoreAppTimeout", checked)
|
|
}
|
|
|
|
SettingsToggleRow {
|
|
settingKey: "notificationShowTimeoutBar"
|
|
tags: ["notification", "timeout", "progress", "bar", "timer", "countdown"]
|
|
text: I18n.tr("Timeout progress bar")
|
|
checked: SettingsData.notificationShowTimeoutBar
|
|
onToggled: checked => SettingsData.set("notificationShowTimeoutBar", checked)
|
|
}
|
|
}
|
|
|
|
SettingsCard {
|
|
iconName: "notifications_off"
|
|
title: I18n.tr("Do not disturb")
|
|
settingKey: "doNotDisturb"
|
|
|
|
SettingsToggleRow {
|
|
settingKey: "doNotDisturb"
|
|
tags: ["notification", "dnd", "mute", "silent", "suppress"]
|
|
text: I18n.tr("Do not disturb")
|
|
checked: SessionData.doNotDisturb
|
|
onToggled: checked => SessionData.setDoNotDisturb(checked)
|
|
}
|
|
|
|
SettingsToggleRow {
|
|
settingKey: "notificationDndWhileScreenSharing"
|
|
tags: ["notification", "dnd", "screenshare", "sharing", "privacy"]
|
|
text: I18n.tr("Automatically enable while screen sharing", "do not disturb auto enable while screen sharing toggle")
|
|
checked: SettingsData.notificationDndWhileScreenSharing
|
|
onToggled: checked => SettingsData.set("notificationDndWhileScreenSharing", checked)
|
|
}
|
|
|
|
SettingsToggleRow {
|
|
settingKey: "notificationDndAllowCritical"
|
|
tags: ["notification", "dnd", "critical", "priority", "urgent", "bypass"]
|
|
text: I18n.tr("Allow critical")
|
|
description: I18n.tr("Critical notifications still pop up", "do not disturb allow critical toggle description")
|
|
checked: SettingsData.notificationDndAllowCritical
|
|
onToggled: checked => SettingsData.set("notificationDndAllowCritical", checked)
|
|
}
|
|
|
|
SettingsRow {
|
|
body: Column {
|
|
width: parent.width
|
|
spacing: Theme.spacingS
|
|
|
|
StyledText {
|
|
text: I18n.tr("Right-click a notification and choose \"Allow in Do Not Disturb\" to add an app")
|
|
font.pixelSize: Theme.fontSizeSmall
|
|
color: Theme.surfaceVariantText
|
|
wrapMode: Text.WordWrap
|
|
width: parent.width
|
|
bottomPadding: Theme.spacingS
|
|
}
|
|
|
|
Repeater {
|
|
model: root.dndBypassRules
|
|
|
|
delegate: Rectangle {
|
|
width: parent.width
|
|
height: dndBypassRow.implicitHeight + Theme.spacingS * 2
|
|
radius: Theme.cornerRadius
|
|
color: Theme.floatingWindowFieldColor
|
|
|
|
Row {
|
|
id: dndBypassRow
|
|
anchors.fill: parent
|
|
anchors.margins: Theme.spacingS
|
|
spacing: Theme.spacingM
|
|
|
|
StyledText {
|
|
id: dndBypassLabel
|
|
text: 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 * 2 - dndBypassLabel.width - dndBypassRemoveBtn.width)
|
|
height: 1
|
|
}
|
|
|
|
DankActionButton {
|
|
id: dndBypassRemoveBtn
|
|
buttonSize: 28
|
|
iconName: "delete"
|
|
Accessible.name: I18n.tr("Remove")
|
|
iconSize: 18
|
|
iconColor: Theme.surfaceVariantText
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
onClicked: SettingsData.removeNotificationRule(modelData.index)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
SettingsCard {
|
|
settingKey: "notificationLinks"
|
|
|
|
SettingsNavRow {
|
|
iconName: "rule_settings"
|
|
title: I18n.tr("Rules")
|
|
hint: SettingsTabs.page("notification_rules")?.hint ?? ""
|
|
onClicked: root.parentModal?.navigateTo("notification_rules")
|
|
}
|
|
}
|
|
|
|
SettingsCard {
|
|
iconName: "visibility_off"
|
|
title: I18n.tr("Privacy", "notification settings card title")
|
|
settingKey: "notificationPrivacy"
|
|
tags: ["notification", "privacy", "hide", "content", "lock"]
|
|
|
|
SettingsToggleRow {
|
|
settingKey: "notificationPopupPrivacyMode"
|
|
tags: ["notification", "popup", "privacy", "body", "content", "hide"]
|
|
text: I18n.tr("Privacy mode")
|
|
description: I18n.tr("Popups hide the message until expanded", "notification privacy mode toggle description")
|
|
checked: SettingsData.notificationPopupPrivacyMode
|
|
onToggled: checked => SettingsData.set("notificationPopupPrivacyMode", checked)
|
|
}
|
|
|
|
SettingsDropdownRow {
|
|
settingKey: "lockScreenNotificationMode"
|
|
tags: ["lock", "screen", "notification", "notifications", "privacy"]
|
|
text: I18n.tr("Lock screen content")
|
|
options: [I18n.tr("Disabled", "lock screen notification mode option"), I18n.tr("Count only", "lock screen notification mode option"), I18n.tr("App names", "lock screen notification mode option"), I18n.tr("Full content", "lock screen notification mode option")]
|
|
currentValue: options[SettingsData.lockScreenNotificationMode] || options[0]
|
|
onValueChanged: value => {
|
|
const idx = options.indexOf(value);
|
|
if (idx < 0)
|
|
return;
|
|
SettingsData.set("lockScreenNotificationMode", idx);
|
|
}
|
|
}
|
|
}
|
|
|
|
SettingsCard {
|
|
iconName: "history"
|
|
title: I18n.tr("History")
|
|
settingKey: "notificationHistory"
|
|
|
|
SettingsToggleRow {
|
|
settingKey: "notificationHistoryEnabled"
|
|
tags: ["notification", "history", "enable", "disable", "save"]
|
|
text: I18n.tr("History")
|
|
checked: SettingsData.notificationHistoryEnabled
|
|
onToggled: checked => SettingsData.set("notificationHistoryEnabled", checked)
|
|
}
|
|
|
|
SettingsDropdownRow {
|
|
settingKey: "notificationHistoryMaxAgeDays"
|
|
tags: ["notification", "history", "max", "age", "days", "retention"]
|
|
text: I18n.tr("Retention", "notification history setting label, how long entries are kept")
|
|
readonly property var retentionDays: [0, 1, 3, 7, 14, 30]
|
|
options: retentionDays.map(days => days === 0 ? I18n.tr("Forever", "notification history retention option") : I18n.duration(days * 86400))
|
|
currentValue: {
|
|
const index = retentionDays.indexOf(SettingsData.notificationHistoryMaxAgeDays);
|
|
return index >= 0 ? options[index] : I18n.duration(SettingsData.notificationHistoryMaxAgeDays * 86400);
|
|
}
|
|
onValueChanged: value => {
|
|
const index = options.indexOf(value);
|
|
SettingsData.set("notificationHistoryMaxAgeDays", index >= 0 ? retentionDays[index] : 7);
|
|
}
|
|
}
|
|
|
|
SettingsSliderRow {
|
|
settingKey: "notificationHistoryMaxCount"
|
|
tags: ["notification", "history", "max", "count", "limit"]
|
|
text: I18n.tr("Maximum entries")
|
|
value: SettingsData.notificationHistoryMaxCount
|
|
minimum: 10
|
|
maximum: 200
|
|
step: 10
|
|
unit: ""
|
|
onSliderValueChanged: newValue => SettingsData.set("notificationHistoryMaxCount", newValue)
|
|
}
|
|
|
|
SettingsToggleRow {
|
|
settingKey: "notificationHistorySaveLow"
|
|
tags: ["notification", "history", "save", "low", "priority"]
|
|
text: I18n.tr("Low")
|
|
checked: SettingsData.notificationHistorySaveLow
|
|
onToggled: checked => SettingsData.set("notificationHistorySaveLow", checked)
|
|
}
|
|
|
|
SettingsToggleRow {
|
|
settingKey: "notificationHistorySaveNormal"
|
|
tags: ["notification", "history", "save", "normal", "priority"]
|
|
text: I18n.tr("Normal")
|
|
checked: SettingsData.notificationHistorySaveNormal
|
|
onToggled: checked => SettingsData.set("notificationHistorySaveNormal", checked)
|
|
}
|
|
|
|
SettingsToggleRow {
|
|
settingKey: "notificationHistorySaveCritical"
|
|
tags: ["notification", "history", "save", "critical", "priority"]
|
|
text: I18n.tr("Critical")
|
|
checked: SettingsData.notificationHistorySaveCritical
|
|
onToggled: checked => SettingsData.set("notificationHistorySaveCritical", checked)
|
|
}
|
|
}
|
|
|
|
SettingsCard {
|
|
iconName: "palette"
|
|
title: I18n.tr("Appearance")
|
|
settingKey: "notificationAppearance"
|
|
tags: ["notification", "font", "size", "layers", "animation", "speed"]
|
|
|
|
SettingsDropdownRow {
|
|
settingKey: "notificationSummaryFontSize"
|
|
tags: ["notification", "font", "summary", "size"]
|
|
text: I18n.tr("Summary font size")
|
|
options: [I18n.tr("Unset"), "10", "12", "14", "16", "18"]
|
|
currentValue: (SettingsData.notificationSummaryFontSize || I18n.tr("Unset")).toString()
|
|
onValueChanged: value => {
|
|
SettingsData.set("notificationSummaryFontSize", Number(value === I18n.tr("Unset") ? 0 : value));
|
|
NotificationService.sendTestNotifications();
|
|
}
|
|
}
|
|
|
|
SettingsDropdownRow {
|
|
settingKey: "notificationBodyFontSize"
|
|
tags: ["notification", "font", "body", "size"]
|
|
text: I18n.tr("Body font size")
|
|
options: [I18n.tr("Unset"), "10", "12", "14", "16", "18"]
|
|
currentValue: (SettingsData.notificationBodyFontSize || I18n.tr("Unset")).toString()
|
|
onValueChanged: value => {
|
|
SettingsData.set("notificationBodyFontSize", Number(value === I18n.tr("Unset") ? 0 : value));
|
|
NotificationService.sendTestNotifications();
|
|
}
|
|
}
|
|
|
|
SettingsToggleRow {
|
|
settingKey: "notificationForegroundLayers"
|
|
tags: ["notification", "foreground", "layers", "surface", "blur", "glass", "contrast", "cards"]
|
|
text: I18n.tr("Foreground layers")
|
|
checked: SettingsData.notificationForegroundLayers ?? true
|
|
onToggled: checked => SettingsData.set("notificationForegroundLayers", checked)
|
|
}
|
|
|
|
SettingsSliderRow {
|
|
settingKey: "notificationAnimationDuration"
|
|
tags: ["notification", "animation", "duration", "speed"]
|
|
text: I18n.tr("Animation duration")
|
|
minimumLabel: I18n.tr("Off")
|
|
minimum: 0
|
|
maximum: 800
|
|
value: SettingsData.notificationAnimationDuration
|
|
unit: "ms"
|
|
onSliderValueChanged: newValue => SettingsData.set("notificationAnimationDuration", newValue)
|
|
}
|
|
}
|
|
}
|