mirror of
https://github.com/noctalia-dev/noctalia-shell.git
synced 2026-05-11 17:08:27 +08:00
feat(notifications): add notification display rules
- block: skips the notification completely - mute: does not play sound (played by noctalia), shows popup, adds to history - hide: no sound, no popup, still adds to history
This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import qs.Commons
|
||||
import qs.Services.System
|
||||
import qs.Widgets
|
||||
|
||||
Popup {
|
||||
id: root
|
||||
modal: true
|
||||
closePolicy: Popup.NoAutoClose
|
||||
dim: true
|
||||
anchors.centerIn: parent
|
||||
|
||||
width: Math.min(500 * Style.uiScaleRatio, parent.width * 0.9)
|
||||
padding: Style.marginL
|
||||
|
||||
property int editIndex: -1
|
||||
property string patternValue: ""
|
||||
property string actionValue: "block"
|
||||
|
||||
signal saved(string pattern, string action)
|
||||
|
||||
property var _savedSlot: null
|
||||
property string _selectedAction: "block"
|
||||
|
||||
background: Rectangle {
|
||||
color: Color.mSurface
|
||||
radius: Style.radiusL
|
||||
border.color: Color.mOutline
|
||||
border.width: Style.borderS
|
||||
}
|
||||
|
||||
onOpened: {
|
||||
patternInput.text = patternValue;
|
||||
actionCombo.currentKey = actionValue;
|
||||
_selectedAction = actionValue;
|
||||
patternInput.forceActiveFocus();
|
||||
}
|
||||
|
||||
contentItem: ColumnLayout {
|
||||
id: contentLayout
|
||||
spacing: Style.marginL
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
NText {
|
||||
text: editIndex >= 0 ? I18n.tr("panels.notifications.rules-edit") : I18n.tr("panels.notifications.rules-add")
|
||||
font.weight: Style.fontWeightBold
|
||||
pointSize: Style.fontSizeL
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
NIconButton {
|
||||
icon: "close"
|
||||
onClicked: root.close()
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
spacing: Style.marginM
|
||||
|
||||
NTextInput {
|
||||
id: patternInput
|
||||
Layout.fillWidth: true
|
||||
label: I18n.tr("panels.notifications.rules-pattern-label")
|
||||
placeholderText: I18n.tr("panels.notifications.rules-pattern-placeholder")
|
||||
fontFamily: Settings.data.ui.fontFixed
|
||||
}
|
||||
|
||||
NComboBox {
|
||||
id: actionCombo
|
||||
Layout.fillWidth: true
|
||||
label: I18n.tr("panels.notifications.rules-action-label")
|
||||
model: [
|
||||
{ "key": "block", "name": I18n.tr("panels.notifications.rules-action-block") },
|
||||
{ "key": "mute", "name": I18n.tr("panels.notifications.rules-action-mute") },
|
||||
{ "key": "hide", "name": I18n.tr("panels.notifications.rules-action-hide") }
|
||||
]
|
||||
currentKey: actionValue
|
||||
onSelected: key => {
|
||||
actionValue = key;
|
||||
_selectedAction = key;
|
||||
}
|
||||
}
|
||||
|
||||
NLabel {
|
||||
Layout.fillWidth: true
|
||||
label: _selectedAction === "block" ? I18n.tr("panels.notifications.rules-action-block-desc") : (_selectedAction === "mute" ? I18n.tr("panels.notifications.rules-action-mute-desc") : I18n.tr("panels.notifications.rules-action-hide-desc"))
|
||||
labelColor: Color.mOnSurfaceVariant
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
spacing: Style.marginM
|
||||
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
NButton {
|
||||
text: I18n.tr("common.cancel")
|
||||
outlined: true
|
||||
onClicked: root.close()
|
||||
}
|
||||
|
||||
NButton {
|
||||
text: I18n.tr("common.save")
|
||||
icon: "check"
|
||||
backgroundColor: Color.mPrimary
|
||||
textColor: Color.mOnPrimary
|
||||
onClicked: {
|
||||
root.saved(patternInput.text.trim(), _selectedAction || "block");
|
||||
root.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -68,6 +68,11 @@ ColumnLayout {
|
||||
tabIndex: 4
|
||||
checked: subTabBar.currentIndex === 4
|
||||
}
|
||||
NTabButton {
|
||||
text: I18n.tr("panels.notifications.rules-tab")
|
||||
tabIndex: 5
|
||||
checked: subTabBar.currentIndex === 5
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
@@ -92,6 +97,7 @@ ColumnLayout {
|
||||
onOpenCriticalPicker: root.openCriticalSoundPicker()
|
||||
}
|
||||
ToastSubTab {}
|
||||
RulesSubTab {}
|
||||
}
|
||||
|
||||
// File Pickers for Sound Files
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import qs.Commons
|
||||
import qs.Services.System
|
||||
import qs.Widgets
|
||||
|
||||
ColumnLayout {
|
||||
id: root
|
||||
spacing: Style.marginL
|
||||
Layout.fillWidth: true
|
||||
enabled: Settings.data.notifications.enabled
|
||||
|
||||
function _saveToService() {
|
||||
NotificationRulesService.save();
|
||||
}
|
||||
|
||||
function _removeRule(index) {
|
||||
var arr = (NotificationRulesService.rules || []).slice();
|
||||
arr.splice(index, 1);
|
||||
NotificationRulesService.rules = arr;
|
||||
_saveToService();
|
||||
}
|
||||
|
||||
NotificationRuleEditPopup {
|
||||
id: editPopup
|
||||
parent: Overlay.overlay
|
||||
}
|
||||
|
||||
function openEdit(index, patternVal, actionVal) {
|
||||
editPopup.editIndex = index;
|
||||
editPopup.patternValue = patternVal || "";
|
||||
editPopup.actionValue = actionVal || "block";
|
||||
|
||||
try {
|
||||
editPopup.saved.disconnect(editPopup._savedSlot);
|
||||
} catch (e) {}
|
||||
|
||||
editPopup._savedSlot = function (pattern, action) {
|
||||
var arr = (NotificationRulesService.rules || []).slice();
|
||||
var rule = { "pattern": pattern, "action": action };
|
||||
if (index >= 0 && index < arr.length) {
|
||||
arr[index] = rule;
|
||||
} else {
|
||||
arr.push(rule);
|
||||
}
|
||||
NotificationRulesService.rules = arr;
|
||||
_saveToService();
|
||||
};
|
||||
|
||||
editPopup.saved.connect(editPopup._savedSlot);
|
||||
editPopup.open();
|
||||
}
|
||||
|
||||
NLabel {
|
||||
label: I18n.tr("panels.notifications.rules-label")
|
||||
description: I18n.tr("panels.notifications.rules-description")
|
||||
}
|
||||
|
||||
NDivider {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: Style.marginS
|
||||
Layout.bottomMargin: Style.marginS
|
||||
}
|
||||
|
||||
Repeater {
|
||||
model: NotificationRulesService.rules || []
|
||||
|
||||
delegate: RowLayout {
|
||||
id: entryDelegate
|
||||
required property int index
|
||||
required property var modelData
|
||||
|
||||
property string pattern: modelData.pattern || ""
|
||||
property string action: modelData.action || "block"
|
||||
property bool isRegex: pattern.length >= 3 && pattern.startsWith("/") && pattern.endsWith("/")
|
||||
|
||||
spacing: Style.marginM
|
||||
Layout.fillWidth: true
|
||||
|
||||
NLabel {
|
||||
Layout.fillWidth: true
|
||||
label: (entryDelegate.isRegex ? "regex: " : "") + (entryDelegate.pattern || I18n.tr("panels.notifications.rules-empty-pattern"))
|
||||
description: entryDelegate.action === "block" ? I18n.tr("panels.notifications.rules-action-block") : (entryDelegate.action === "mute" ? I18n.tr("panels.notifications.rules-action-mute") : I18n.tr("panels.notifications.rules-action-hide"))
|
||||
labelColor: entryDelegate.pattern ? Color.mPrimary : Color.mOnSurface
|
||||
}
|
||||
|
||||
NIconButton {
|
||||
icon: "settings"
|
||||
tooltipText: I18n.tr("common.edit")
|
||||
onClicked: root.openEdit(entryDelegate.index, entryDelegate.pattern, entryDelegate.action)
|
||||
}
|
||||
|
||||
NIconButton {
|
||||
icon: "trash"
|
||||
tooltipText: I18n.tr("panels.notifications.rules-delete")
|
||||
onClicked: root._removeRule(entryDelegate.index)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NButton {
|
||||
text: I18n.tr("panels.notifications.rules-add")
|
||||
icon: "add"
|
||||
enabled: Settings.data.notifications.enabled
|
||||
onClicked: root.openEdit(-1, "", "block")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user