1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-01-24 21:42:51 -05:00

motifications: add support for configurable persistent history

fixes #929
This commit is contained in:
bbedward
2026-01-03 13:08:48 -05:00
parent faddc46185
commit 2bf85bc4dd
11 changed files with 1233 additions and 140 deletions

View File

@@ -0,0 +1,189 @@
import QtQuick
import Quickshell
import qs.Common
import qs.Services
import qs.Widgets
Rectangle {
id: root
required property var historyItem
property bool isSelected: false
property bool keyboardNavigationActive: false
width: parent ? parent.width : 400
height: 116
radius: Theme.cornerRadius
clip: true
color: {
if (isSelected && keyboardNavigationActive)
return Theme.primaryPressed;
return Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency);
}
border.color: {
if (isSelected && keyboardNavigationActive)
return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.5);
if (historyItem.urgency === 2)
return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.3);
return Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.05);
}
border.width: {
if (isSelected && keyboardNavigationActive)
return 1.5;
if (historyItem.urgency === 2)
return 2;
return 1;
}
Behavior on border.color {
ColorAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
Rectangle {
anchors.fill: parent
radius: parent.radius
visible: historyItem.urgency === 2
gradient: Gradient {
orientation: Gradient.Horizontal
GradientStop {
position: 0.0
color: Theme.primary
}
GradientStop {
position: 0.02
color: Theme.primary
}
GradientStop {
position: 0.021
color: "transparent"
}
}
}
Item {
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.topMargin: 12
anchors.leftMargin: 16
anchors.rightMargin: 56
height: 92
DankCircularImage {
id: iconContainer
readonly property bool hasNotificationImage: historyItem.image && historyItem.image !== ""
width: 63
height: 63
anchors.left: parent.left
anchors.top: parent.top
anchors.topMargin: 14
imageSource: {
if (hasNotificationImage)
return historyItem.image;
if (historyItem.appIcon) {
const appIcon = historyItem.appIcon;
if (appIcon.startsWith("file://") || appIcon.startsWith("http://") || appIcon.startsWith("https://"))
return appIcon;
return Quickshell.iconPath(appIcon, true);
}
return "";
}
hasImage: hasNotificationImage
fallbackIcon: ""
fallbackText: {
const appName = historyItem.appName || "?";
return appName.charAt(0).toUpperCase();
}
Rectangle {
anchors.fill: parent
anchors.margins: -2
radius: width / 2
color: "transparent"
border.color: root.color
border.width: 5
visible: parent.hasImage
antialiasing: true
}
}
Rectangle {
anchors.left: iconContainer.right
anchors.leftMargin: 12
anchors.right: parent.right
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.bottomMargin: 8
color: "transparent"
Item {
width: parent.width
height: parent.height
anchors.top: parent.top
anchors.topMargin: -2
Column {
width: parent.width
spacing: 2
StyledText {
width: parent.width
text: {
const timeStr = NotificationService.formatHistoryTime(historyItem.timestamp);
const appName = historyItem.appName || "";
return timeStr.length > 0 ? `${appName} ${timeStr}` : appName;
}
color: Theme.surfaceVariantText
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium
elide: Text.ElideRight
maximumLineCount: 1
}
StyledText {
text: historyItem.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 {
id: descriptionText
text: historyItem.htmlBody || historyItem.body || ""
color: Theme.surfaceVariantText
font.pixelSize: Theme.fontSizeSmall
width: parent.width
elide: Text.ElideRight
maximumLineCount: 2
wrapMode: Text.WordWrap
visible: text.length > 0
linkColor: Theme.primary
onLinkActivated: link => Qt.openUrlExternally(link)
}
}
}
}
}
DankActionButton {
anchors.top: parent.top
anchors.right: parent.right
anchors.topMargin: 12
anchors.rightMargin: 16
iconName: "close"
iconSize: 18
buttonSize: 28
onClicked: NotificationService.removeFromHistory(historyItem.id)
}
}

View File

@@ -0,0 +1,276 @@
import QtQuick
import Quickshell
import qs.Common
import qs.Services
import qs.Widgets
Item {
id: root
property string selectedFilterKey: "all"
property var keyboardController: null
property bool keyboardActive: false
property int selectedIndex: -1
property bool showKeyboardHints: false
function getStartOfDay(date) {
const d = new Date(date);
d.setHours(0, 0, 0, 0);
return d;
}
function getFilterRange(key) {
const now = new Date();
const startOfToday = getStartOfDay(now);
const startOfYesterday = new Date(startOfToday.getTime() - 86400000);
switch (key) {
case "all":
return {
start: null,
end: null
};
case "1h":
return {
start: new Date(now.getTime() - 3600000),
end: null
};
case "today":
return {
start: startOfToday,
end: null
};
case "yesterday":
return {
start: startOfYesterday,
end: startOfToday
};
case "older":
return {
start: null,
end: getOlderCutoff()
};
case "7d":
return {
start: new Date(now.getTime() - 7 * 86400000),
end: null
};
case "30d":
return {
start: new Date(now.getTime() - 30 * 86400000),
end: null
};
default:
return {
start: null,
end: null
};
}
}
function countForFilter(key) {
const range = getFilterRange(key);
if (!range.start && !range.end)
return NotificationService.historyList.length;
return NotificationService.historyList.filter(n => {
const ts = n.timestamp;
if (range.start && ts < range.start.getTime())
return false;
if (range.end && ts >= range.end.getTime())
return false;
return true;
}).length;
}
readonly property var allFilters: [
{ label: I18n.tr("All", "notification history filter"), key: "all", maxDays: 0 },
{ label: I18n.tr("Last hour", "notification history filter"), key: "1h", maxDays: 1 },
{ label: I18n.tr("Today", "notification history filter"), key: "today", maxDays: 1 },
{ label: I18n.tr("Yesterday", "notification history filter"), key: "yesterday", maxDays: 2 },
{ label: I18n.tr("7 days", "notification history filter"), key: "7d", maxDays: 7 },
{ label: I18n.tr("30 days", "notification history filter"), key: "30d", maxDays: 30 },
{ label: I18n.tr("Older", "notification history filter for content older than other filters"), key: "older", maxDays: 0 }
]
function filterRelevantForRetention(filter) {
const retention = SettingsData.notificationHistoryMaxAgeDays;
if (filter.key === "older") {
if (retention === 0) return true;
return retention > 2 && retention < 7 || retention > 30;
}
if (retention === 0) return true;
if (filter.maxDays === 0) return true;
return filter.maxDays <= retention;
}
function getOlderCutoff() {
const retention = SettingsData.notificationHistoryMaxAgeDays;
const now = new Date();
if (retention === 0 || retention > 30)
return new Date(now.getTime() - 30 * 86400000);
if (retention >= 7)
return new Date(now.getTime() - 7 * 86400000);
const startOfToday = getStartOfDay(now);
return new Date(startOfToday.getTime() - 86400000);
}
readonly property var visibleFilters: {
const result = [];
const retention = SettingsData.notificationHistoryMaxAgeDays;
for (let i = 0; i < allFilters.length; i++) {
const f = allFilters[i];
if (!filterRelevantForRetention(f)) continue;
const count = countForFilter(f.key);
if (f.key === "all" || count > 0) {
result.push({ label: f.label, key: f.key, count: count });
}
}
return result;
}
onVisibleFiltersChanged: {
let found = false;
for (let i = 0; i < visibleFilters.length; i++) {
if (visibleFilters[i].key === selectedFilterKey) {
found = true;
break;
}
}
if (!found)
selectedFilterKey = "all";
}
function getFilteredHistory() {
const range = getFilterRange(selectedFilterKey);
if (!range.start && !range.end)
return NotificationService.historyList;
return NotificationService.historyList.filter(n => {
const ts = n.timestamp;
if (range.start && ts < range.start.getTime())
return false;
if (range.end && ts >= range.end.getTime())
return false;
return true;
});
}
function getChipIndex() {
for (let i = 0; i < visibleFilters.length; i++) {
if (visibleFilters[i].key === selectedFilterKey)
return i;
}
return 0;
}
function enableAutoScroll() {
}
Column {
anchors.fill: parent
spacing: Theme.spacingS
DankFilterChips {
id: filterChips
width: parent.width
currentIndex: root.getChipIndex()
showCounts: true
model: root.visibleFilters
onSelectionChanged: index => {
if (index >= 0 && index < root.visibleFilters.length) {
root.selectedFilterKey = root.visibleFilters[index].key;
}
}
}
DankListView {
id: historyListView
width: parent.width
height: parent.height - filterChips.height - Theme.spacingS
clip: true
spacing: Theme.spacingS
model: ScriptModel {
id: historyModel
values: root.getFilteredHistory()
objectProp: "id"
}
NotificationEmptyState {
visible: historyListView.count === 0
y: Theme.spacingL
anchors.horizontalCenter: parent.horizontalCenter
}
delegate: HistoryNotificationCard {
required property var modelData
required property int index
width: ListView.view.width
historyItem: modelData
isSelected: root.keyboardActive && root.selectedIndex === index
keyboardNavigationActive: root.keyboardActive
}
}
}
function selectNext() {
if (historyModel.values.length === 0)
return;
keyboardActive = true;
selectedIndex = Math.min(selectedIndex + 1, historyModel.values.length - 1);
historyListView.positionViewAtIndex(selectedIndex, ListView.Contain);
}
function selectPrevious() {
if (historyModel.values.length === 0)
return;
if (selectedIndex <= 0) {
keyboardActive = false;
selectedIndex = -1;
return;
}
selectedIndex = Math.max(selectedIndex - 1, 0);
historyListView.positionViewAtIndex(selectedIndex, ListView.Contain);
}
function clearSelected() {
if (selectedIndex < 0 || selectedIndex >= historyModel.values.length)
return;
const item = historyModel.values[selectedIndex];
NotificationService.removeFromHistory(item.id);
if (historyModel.values.length === 0) {
keyboardActive = false;
selectedIndex = -1;
} else {
selectedIndex = Math.min(selectedIndex, historyModel.values.length - 1);
}
}
function handleKey(event) {
if (event.key === Qt.Key_Down || event.key === 16777237) {
if (!keyboardActive) {
keyboardActive = true;
selectedIndex = 0;
} else {
selectNext();
}
event.accepted = true;
} else if (event.key === Qt.Key_Up || event.key === 16777235) {
if (keyboardActive) {
selectPrevious();
}
event.accepted = true;
} else if (keyboardActive && (event.key === Qt.Key_Delete || event.key === Qt.Key_Backspace)) {
clearSelected();
event.accepted = true;
} else if ((event.key === Qt.Key_Delete || event.key === Qt.Key_Backspace) && (event.modifiers & Qt.ShiftModifier)) {
NotificationService.clearHistory();
keyboardActive = false;
selectedIndex = -1;
event.accepted = true;
} else if (event.key === Qt.Key_F10) {
showKeyboardHints = !showKeyboardHints;
event.accepted = true;
}
}
}

View File

@@ -2,7 +2,6 @@ import QtQuick
import qs.Common
import qs.Services
import qs.Widgets
import qs.Modules.Notifications.Center
DankPopout {
id: root
@@ -112,8 +111,11 @@ DankPopout {
baseHeight += Theme.spacingM * 2;
const settingsHeight = notificationSettings.expanded ? notificationSettings.contentHeight : 0;
let listHeight = notificationList.listContentHeight;
if (NotificationService.groupedNotifications.length === 0) {
let listHeight = notificationHeader.currentTab === 0 ? notificationList.listContentHeight : Math.max(200, NotificationService.historyList.length * 80);
if (notificationHeader.currentTab === 0 && NotificationService.groupedNotifications.length === 0) {
listHeight = 200;
}
if (notificationHeader.currentTab === 1 && NotificationService.historyList.length === 0) {
listHeight = 200;
}
@@ -143,7 +145,13 @@ DankPopout {
if (event.key === Qt.Key_Escape) {
notificationHistoryVisible = false;
event.accepted = true;
} else if (externalKeyboardController) {
return;
}
if (notificationHeader.currentTab === 1) {
historyList.handleKey(event);
return;
}
if (externalKeyboardController) {
externalKeyboardController.handleKey(event);
}
}
@@ -187,7 +195,14 @@ DankPopout {
KeyboardNavigatedNotificationList {
id: notificationList
objectName: "notificationList"
visible: notificationHeader.currentTab === 0
width: parent.width
height: parent.height - notificationContent.cachedHeaderHeight - notificationSettings.height - contentColumnInner.spacing * 2
}
HistoryNotificationList {
id: historyList
visible: notificationHeader.currentTab === 1
width: parent.width
height: parent.height - notificationContent.cachedHeaderHeight - notificationSettings.height - contentColumnInner.spacing * 2
}
@@ -200,7 +215,7 @@ DankPopout {
anchors.left: parent.left
anchors.right: parent.right
anchors.margins: Theme.spacingL
showHints: (externalKeyboardController && externalKeyboardController.showKeyboardHints) || false
showHints: notificationHeader.currentTab === 0 ? (externalKeyboardController && externalKeyboardController.showKeyboardHints) || false : historyList.showKeyboardHints
z: 200
}
}

View File

@@ -8,108 +8,150 @@ Item {
property var keyboardController: null
property bool showSettings: false
property int currentTab: 0
onCurrentTabChanged: {
if (currentTab === 1 && !SettingsData.notificationHistoryEnabled)
currentTab = 0;
}
Connections {
target: SettingsData
function onNotificationHistoryEnabledChanged() {
if (!SettingsData.notificationHistoryEnabled)
root.currentTab = 0;
}
}
width: parent.width
height: 32
height: headerColumn.implicitHeight
DankTooltipV2 {
id: sharedTooltip
}
Row {
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
spacing: Theme.spacingXS
Column {
id: headerColumn
width: parent.width
spacing: Theme.spacingS
StyledText {
text: I18n.tr("Notifications")
font.pixelSize: Theme.fontSizeLarge
color: Theme.surfaceText
font.weight: Font.Medium
anchors.verticalCenter: parent.verticalCenter
}
DankActionButton {
id: doNotDisturbButton
iconName: SessionData.doNotDisturb ? "notifications_off" : "notifications"
iconColor: SessionData.doNotDisturb ? Theme.error : Theme.surfaceText
buttonSize: 28
anchors.verticalCenter: parent.verticalCenter
onClicked: SessionData.setDoNotDisturb(!SessionData.doNotDisturb)
onEntered: {
sharedTooltip.show(I18n.tr("Do Not Disturb"), doNotDisturbButton, 0, 0, "bottom");
}
onExited: {
sharedTooltip.hide();
}
}
}
Row {
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
spacing: Theme.spacingXS
DankActionButton {
id: helpButton
iconName: "info"
iconColor: (keyboardController && keyboardController.showKeyboardHints) ? Theme.primary : Theme.surfaceText
buttonSize: 28
visible: keyboardController !== null
anchors.verticalCenter: parent.verticalCenter
onClicked: {
if (keyboardController) {
keyboardController.showKeyboardHints = !keyboardController.showKeyboardHints;
}
}
}
DankActionButton {
id: settingsButton
iconName: "settings"
iconColor: root.showSettings ? Theme.primary : Theme.surfaceText
buttonSize: 28
anchors.verticalCenter: parent.verticalCenter
onClicked: root.showSettings = !root.showSettings
}
Rectangle {
id: clearAllButton
width: 120
height: 28
radius: Theme.cornerRadius
visible: NotificationService.notifications.length > 0
color: clearArea.containsMouse ? Theme.primaryHoverLight : Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
Item {
width: parent.width
height: Math.max(titleRow.implicitHeight, actionsRow.implicitHeight)
Row {
anchors.centerIn: parent
id: titleRow
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
spacing: Theme.spacingXS
DankIcon {
name: "delete_sweep"
size: Theme.iconSizeSmall
color: clearArea.containsMouse ? Theme.primary : Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: I18n.tr("Clear")
font.pixelSize: Theme.fontSizeSmall
color: clearArea.containsMouse ? Theme.primary : Theme.surfaceText
text: I18n.tr("Notifications")
font.pixelSize: Theme.fontSizeLarge
color: Theme.surfaceText
font.weight: Font.Medium
anchors.verticalCenter: parent.verticalCenter
}
DankActionButton {
id: doNotDisturbButton
iconName: SessionData.doNotDisturb ? "notifications_off" : "notifications"
iconColor: SessionData.doNotDisturb ? Theme.error : Theme.surfaceText
buttonSize: Theme.iconSize + Theme.spacingS
anchors.verticalCenter: parent.verticalCenter
onClicked: SessionData.setDoNotDisturb(!SessionData.doNotDisturb)
onEntered: sharedTooltip.show(I18n.tr("Do Not Disturb"), doNotDisturbButton, 0, 0, "bottom")
onExited: sharedTooltip.hide()
}
}
MouseArea {
id: clearArea
Row {
id: actionsRow
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
spacing: Theme.spacingXS
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: NotificationService.clearAllNotifications()
DankActionButton {
id: helpButton
iconName: "info"
iconColor: (keyboardController && keyboardController.showKeyboardHints) ? Theme.primary : Theme.surfaceText
buttonSize: Theme.iconSize + Theme.spacingS
visible: keyboardController !== null
anchors.verticalCenter: parent.verticalCenter
onClicked: {
if (keyboardController)
keyboardController.showKeyboardHints = !keyboardController.showKeyboardHints;
}
}
DankActionButton {
id: settingsButton
iconName: "settings"
iconColor: root.showSettings ? Theme.primary : Theme.surfaceText
buttonSize: Theme.iconSize + Theme.spacingS
anchors.verticalCenter: parent.verticalCenter
onClicked: root.showSettings = !root.showSettings
}
Rectangle {
id: clearAllButton
width: clearButtonContent.implicitWidth + Theme.spacingM * 2
height: Theme.iconSize + Theme.spacingS
radius: Theme.cornerRadius
visible: root.currentTab === 0 ? NotificationService.notifications.length > 0 : NotificationService.historyList.length > 0
color: clearArea.containsMouse ? Theme.primaryHoverLight : Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
Row {
id: clearButtonContent
anchors.centerIn: parent
spacing: Theme.spacingXS
DankIcon {
name: "delete_sweep"
size: Theme.iconSizeSmall
color: clearArea.containsMouse ? Theme.primary : Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: I18n.tr("Clear")
font.pixelSize: Theme.fontSizeSmall
color: clearArea.containsMouse ? Theme.primary : Theme.surfaceText
font.weight: Font.Medium
anchors.verticalCenter: parent.verticalCenter
}
}
MouseArea {
id: clearArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
if (root.currentTab === 0) {
NotificationService.clearAllNotifications();
} else {
NotificationService.clearHistory();
}
}
}
}
}
}
DankButtonGroup {
id: tabGroup
width: parent.width
currentIndex: root.currentTab
buttonHeight: 32
buttonPadding: Theme.spacingM
checkEnabled: false
textSize: Theme.fontSizeSmall
visible: SettingsData.notificationHistoryEnabled
model: [I18n.tr("Current", "notification center tab") + " (" + NotificationService.notifications.length + ")", I18n.tr("History", "notification center tab") + " (" + NotificationService.historyList.length + ")"]
onSelectionChanged: (index, selected) => {
if (selected)
root.currentTab = index;
}
}
}

View File

@@ -1,7 +1,5 @@
import QtQuick
import QtQuick.Controls
import qs.Common
import qs.Services
import qs.Widgets
Rectangle {
@@ -36,64 +34,77 @@ Rectangle {
}
}
readonly property var timeoutOptions: [{
readonly property var timeoutOptions: [
{
"text": "Never",
"value": 0
}, {
},
{
"text": "1 second",
"value": 1000
}, {
},
{
"text": "3 seconds",
"value": 3000
}, {
},
{
"text": "5 seconds",
"value": 5000
}, {
},
{
"text": "8 seconds",
"value": 8000
}, {
},
{
"text": "10 seconds",
"value": 10000
}, {
},
{
"text": "15 seconds",
"value": 15000
}, {
},
{
"text": "30 seconds",
"value": 30000
}, {
},
{
"text": "1 minute",
"value": 60000
}, {
},
{
"text": "2 minutes",
"value": 120000
}, {
},
{
"text": "5 minutes",
"value": 300000
}, {
},
{
"text": "10 minutes",
"value": 600000
}]
}
]
function getTimeoutText(value) {
if (value === undefined || value === null || isNaN(value)) {
return "5 seconds"
return "5 seconds";
}
for (let i = 0; i < timeoutOptions.length; i++) {
if (timeoutOptions[i].value === value) {
return timeoutOptions[i].text
return timeoutOptions[i].text;
}
}
if (value === 0) {
return "Never"
return "Never";
}
if (value < 1000) {
return value + "ms"
return value + "ms";
}
if (value < 60000) {
return Math.round(value / 1000) + " seconds"
return Math.round(value / 1000) + " seconds";
}
return Math.round(value / 60000) + " minutes"
return Math.round(value / 60000) + " minutes";
}
Column {
@@ -113,9 +124,10 @@ Rectangle {
Item {
width: parent.width
height: 36
height: Math.max(dndRow.implicitHeight, dndToggle.implicitHeight) + Theme.spacingS
Row {
id: dndRow
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
spacing: Theme.spacingM
@@ -136,6 +148,7 @@ Rectangle {
}
DankToggle {
id: dndToggle
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
checked: SessionData.doNotDisturb
@@ -162,13 +175,13 @@ Rectangle {
currentValue: getTimeoutText(SettingsData.notificationTimeoutLow)
options: timeoutOptions.map(opt => opt.text)
onValueChanged: value => {
for (let i = 0; i < timeoutOptions.length; i++) {
if (timeoutOptions[i].text === value) {
SettingsData.set("notificationTimeoutLow", timeoutOptions[i].value)
break
}
}
}
for (let i = 0; i < timeoutOptions.length; i++) {
if (timeoutOptions[i].text === value) {
SettingsData.set("notificationTimeoutLow", timeoutOptions[i].value);
break;
}
}
}
}
DankDropdown {
@@ -177,13 +190,13 @@ Rectangle {
currentValue: getTimeoutText(SettingsData.notificationTimeoutNormal)
options: timeoutOptions.map(opt => opt.text)
onValueChanged: value => {
for (let i = 0; i < timeoutOptions.length; i++) {
if (timeoutOptions[i].text === value) {
SettingsData.set("notificationTimeoutNormal", timeoutOptions[i].value)
break
}
}
}
for (let i = 0; i < timeoutOptions.length; i++) {
if (timeoutOptions[i].text === value) {
SettingsData.set("notificationTimeoutNormal", timeoutOptions[i].value);
break;
}
}
}
}
DankDropdown {
@@ -192,13 +205,13 @@ Rectangle {
currentValue: getTimeoutText(SettingsData.notificationTimeoutCritical)
options: timeoutOptions.map(opt => opt.text)
onValueChanged: value => {
for (let i = 0; i < timeoutOptions.length; i++) {
if (timeoutOptions[i].text === value) {
SettingsData.set("notificationTimeoutCritical", timeoutOptions[i].value)
break
}
}
}
for (let i = 0; i < timeoutOptions.length; i++) {
if (timeoutOptions[i].text === value) {
SettingsData.set("notificationTimeoutCritical", timeoutOptions[i].value);
break;
}
}
}
}
Rectangle {
@@ -209,9 +222,10 @@ Rectangle {
Item {
width: parent.width
height: 36
height: Math.max(overlayRow.implicitHeight, overlayToggle.implicitHeight) + Theme.spacingS
Row {
id: overlayRow
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
spacing: Theme.spacingM
@@ -242,11 +256,127 @@ Rectangle {
}
DankToggle {
id: overlayToggle
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
checked: SettingsData.notificationOverlayEnabled
onToggled: toggled => SettingsData.set("notificationOverlayEnabled", toggled)
}
}
Rectangle {
width: parent.width
height: 1
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.1)
}
StyledText {
text: I18n.tr("History Settings")
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium
color: Theme.surfaceVariantText
}
Item {
width: parent.width
height: Math.max(lowRow.implicitHeight, lowToggle.implicitHeight) + Theme.spacingS
Row {
id: lowRow
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
spacing: Theme.spacingM
DankIcon {
name: "low_priority"
size: Theme.iconSizeSmall
color: SettingsData.notificationHistorySaveLow ? Theme.primary : Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: I18n.tr("Low Priority")
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
DankToggle {
id: lowToggle
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
checked: SettingsData.notificationHistorySaveLow
onToggled: toggled => SettingsData.set("notificationHistorySaveLow", toggled)
}
}
Item {
width: parent.width
height: Math.max(normalRow.implicitHeight, normalToggle.implicitHeight) + Theme.spacingS
Row {
id: normalRow
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
spacing: Theme.spacingM
DankIcon {
name: "notifications"
size: Theme.iconSizeSmall
color: SettingsData.notificationHistorySaveNormal ? Theme.primary : Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: I18n.tr("Normal Priority")
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
DankToggle {
id: normalToggle
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
checked: SettingsData.notificationHistorySaveNormal
onToggled: toggled => SettingsData.set("notificationHistorySaveNormal", toggled)
}
}
Item {
width: parent.width
height: Math.max(criticalRow.implicitHeight, criticalToggle.implicitHeight) + Theme.spacingS
Row {
id: criticalRow
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
spacing: Theme.spacingM
DankIcon {
name: "priority_high"
size: Theme.iconSizeSmall
color: SettingsData.notificationHistorySaveCritical ? Theme.primary : Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: I18n.tr("Critical Priority")
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
DankToggle {
id: criticalToggle
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
checked: SettingsData.notificationHistorySaveCritical
onToggled: toggled => SettingsData.set("notificationHistorySaveCritical", toggled)
}
}
}
}