Push Rule Model Rework
This is a significant rework of the handling of push rules. Rather than using a lot of boilerplate code for the default models `KeywordNotificationModel` has been converted to `PushRuleModel` and now handles all push rules. The new model has the following features: - Handles all push rules - Has special handling for the names of default keywords (i.e. it still gives the same text as previously for showing in the settings menus) - Push rules for blocking individuals or room overrides are still there but hidden so will be available for developer tools (to follow) - Room specific keywords are now supported. The notification settings pages have also been refactored to take advantage of the new models. Each section is now just a repeater with a filter for the rules that it should contain. The push rule delegate has now been cleaned up and uses required properties. Implements network/neochat#574
This commit is contained in:
@@ -24,7 +24,7 @@ add_library(neochat STATIC
|
||||
models/userfiltermodel.cpp
|
||||
models/publicroomlistmodel.cpp
|
||||
models/userdirectorylistmodel.cpp
|
||||
models/keywordnotificationrulemodel.cpp
|
||||
models/pushrulemodel.cpp
|
||||
models/emoticonfiltermodel.cpp
|
||||
notificationsmanager.cpp
|
||||
models/sortfilterroomlistmodel.cpp
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
#include "controller.h"
|
||||
#include "models/pushrulemodel.h"
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
||||
#include <qt5keychain/keychain.h>
|
||||
@@ -126,6 +127,10 @@ Controller::Controller(QObject *parent)
|
||||
oldAccountCount = Accounts.size();
|
||||
});
|
||||
#endif
|
||||
|
||||
QTimer::singleShot(0, this, [this] {
|
||||
m_pushRuleModel = new PushRuleModel;
|
||||
});
|
||||
}
|
||||
|
||||
Controller &Controller::instance()
|
||||
@@ -507,6 +512,11 @@ void Controller::setActiveConnection(Connection *connection)
|
||||
Q_EMIT activeAccountLabelChanged();
|
||||
}
|
||||
|
||||
PushRuleModel *Controller::pushRuleModel() const
|
||||
{
|
||||
return m_pushRuleModel;
|
||||
}
|
||||
|
||||
void Controller::saveWindowGeometry()
|
||||
{
|
||||
WindowController::instance().saveGeometry();
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "models/pushrulemodel.h"
|
||||
#include <QObject>
|
||||
#include <QQuickItem>
|
||||
|
||||
@@ -50,6 +51,11 @@ class Controller : public QObject
|
||||
*/
|
||||
Q_PROPERTY(Quotient::Connection *activeConnection READ activeConnection WRITE setActiveConnection NOTIFY activeConnectionChanged)
|
||||
|
||||
/**
|
||||
* @brief The PushRuleModel that has the active connection's push rules.
|
||||
*/
|
||||
Q_PROPERTY(PushRuleModel *pushRuleModel READ pushRuleModel CONSTANT)
|
||||
|
||||
/**
|
||||
* @brief The row number in the accounts directory of the active connection.
|
||||
*/
|
||||
@@ -119,6 +125,8 @@ public:
|
||||
void setActiveConnection(Quotient::Connection *connection);
|
||||
[[nodiscard]] Quotient::Connection *activeConnection() const;
|
||||
|
||||
[[nodiscard]] PushRuleModel *pushRuleModel() const;
|
||||
|
||||
/**
|
||||
* @brief Add a new connection to the account registry.
|
||||
*/
|
||||
@@ -236,6 +244,8 @@ private:
|
||||
|
||||
bool hasWindowSystem() const;
|
||||
|
||||
QPointer<PushRuleModel> m_pushRuleModel;
|
||||
|
||||
private Q_SLOTS:
|
||||
void invokeLogin();
|
||||
void showWindow();
|
||||
|
||||
@@ -57,13 +57,13 @@
|
||||
#include "models/emojimodel.h"
|
||||
#include "models/emoticonfiltermodel.h"
|
||||
#include "models/imagepacksmodel.h"
|
||||
#include "models/keywordnotificationrulemodel.h"
|
||||
#include "models/livelocationsmodel.h"
|
||||
#include "models/locationsmodel.h"
|
||||
#include "models/mediamessagefiltermodel.h"
|
||||
#include "models/messageeventmodel.h"
|
||||
#include "models/messagefiltermodel.h"
|
||||
#include "models/publicroomlistmodel.h"
|
||||
#include "models/pushrulemodel.h"
|
||||
#include "models/reactionmodel.h"
|
||||
#include "models/roomlistmodel.h"
|
||||
#include "models/searchmodel.h"
|
||||
@@ -257,13 +257,15 @@ int main(int argc, char *argv[])
|
||||
#ifdef QUOTIENT_07
|
||||
qmlRegisterType<PollHandler>("org.kde.neochat", 1, 0, "PollHandler");
|
||||
#endif
|
||||
qmlRegisterType<KeywordNotificationRuleModel>("org.kde.neochat", 1, 0, "KeywordNotificationRuleModel");
|
||||
qmlRegisterType<PushRuleModel>("org.kde.neochat", 1, 0, "PushRuleModel");
|
||||
qmlRegisterType<StickerModel>("org.kde.neochat", 1, 0, "StickerModel");
|
||||
qmlRegisterType<ImagePacksModel>("org.kde.neochat", 1, 0, "ImagePacksModel");
|
||||
qmlRegisterType<AccountEmoticonModel>("org.kde.neochat", 1, 0, "AccountEmoticonModel");
|
||||
qmlRegisterType<EmoticonFilterModel>("org.kde.neochat", 1, 0, "EmoticonFilterModel");
|
||||
qmlRegisterType<DelegateSizeHelper>("org.kde.neochat", 1, 0, "DelegateSizeHelper");
|
||||
qmlRegisterUncreatableType<RoomMessageEvent>("org.kde.neochat", 1, 0, "RoomMessageEvent", "ENUM");
|
||||
qmlRegisterUncreatableType<PushNotificationKind>("org.kde.neochat", 1, 0, "PushNotificationKind", "ENUM");
|
||||
qmlRegisterUncreatableType<PushNotificationSection>("org.kde.neochat", 1, 0, "PushNotificationSection", "ENUM");
|
||||
qmlRegisterUncreatableType<PushNotificationState>("org.kde.neochat", 1, 0, "PushNotificationState", "ENUM");
|
||||
qmlRegisterUncreatableType<PushNotificationAction>("org.kde.neochat", 1, 0, "PushNotificationAction", "ENUM");
|
||||
qmlRegisterUncreatableType<NeoChatRoomType>("org.kde.neochat", 1, 0, "NeoChatRoomType", "ENUM");
|
||||
|
||||
@@ -1,110 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2022 James Graham <james.h.graham@protonmail.com>
|
||||
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
|
||||
#include "keywordnotificationrulemodel.h"
|
||||
#include "controller.h"
|
||||
#include "notificationsmanager.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <connection.h>
|
||||
#include <converters.h>
|
||||
#include <csapi/definitions/push_ruleset.h>
|
||||
#include <csapi/pushrules.h>
|
||||
#include <jobs/basejob.h>
|
||||
|
||||
KeywordNotificationRuleModel::KeywordNotificationRuleModel(QObject *parent)
|
||||
: QAbstractListModel(parent)
|
||||
{
|
||||
if (Controller::instance().activeConnection()) {
|
||||
controllerConnectionChanged();
|
||||
}
|
||||
connect(&Controller::instance(), &Controller::activeConnectionChanged, this, &KeywordNotificationRuleModel::controllerConnectionChanged);
|
||||
}
|
||||
|
||||
void KeywordNotificationRuleModel::controllerConnectionChanged()
|
||||
{
|
||||
connect(Controller::instance().activeConnection(), &Quotient::Connection::accountDataChanged, this, &KeywordNotificationRuleModel::updateNotificationRules);
|
||||
updateNotificationRules("m.push_rules");
|
||||
}
|
||||
|
||||
void KeywordNotificationRuleModel::updateNotificationRules(const QString &type)
|
||||
{
|
||||
if (type != "m.push_rules") {
|
||||
return;
|
||||
}
|
||||
|
||||
const QJsonObject ruleDataJson = Controller::instance().activeConnection()->accountDataJson("m.push_rules");
|
||||
const Quotient::PushRuleset ruleData = Quotient::fromJson<Quotient::PushRuleset>(ruleDataJson["global"].toObject());
|
||||
const QVector<Quotient::PushRule> contentRules = ruleData.content;
|
||||
|
||||
beginResetModel();
|
||||
m_notificationRules.clear();
|
||||
for (const auto &i : contentRules) {
|
||||
if (!m_notificationRules.contains(i.ruleId) && i.ruleId[0] != '.') {
|
||||
m_notificationRules.append(i.ruleId);
|
||||
}
|
||||
}
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
QVariant KeywordNotificationRuleModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
if (index.row() >= m_notificationRules.count()) {
|
||||
qDebug() << "KeywordNotificationRuleModel, something's wrong: index.row() >= m_notificationRules.count()";
|
||||
return {};
|
||||
}
|
||||
|
||||
if (role == NameRole) {
|
||||
return m_notificationRules.at(index.row());
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
int KeywordNotificationRuleModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(parent)
|
||||
|
||||
return m_notificationRules.count();
|
||||
}
|
||||
|
||||
void KeywordNotificationRuleModel::addKeyword(const QString &keyword)
|
||||
{
|
||||
if (m_notificationRules.count() == 0) {
|
||||
NotificationsManager::instance().initializeKeywordNotificationAction();
|
||||
}
|
||||
|
||||
const QVector<QVariant> actions = NotificationsManager::instance().getKeywordNotificationActions();
|
||||
|
||||
auto job = Controller::instance()
|
||||
.activeConnection()
|
||||
->callApi<Quotient::SetPushRuleJob>("global", "content", keyword, actions, "", "", QVector<Quotient::PushCondition>(), keyword);
|
||||
connect(job, &Quotient::BaseJob::success, this, [this, keyword]() {
|
||||
beginInsertRows(QModelIndex(), m_notificationRules.count(), m_notificationRules.count());
|
||||
m_notificationRules.append(keyword);
|
||||
endInsertRows();
|
||||
});
|
||||
}
|
||||
|
||||
void KeywordNotificationRuleModel::removeKeywordAtIndex(int index)
|
||||
{
|
||||
auto job = Controller::instance().activeConnection()->callApi<Quotient::DeletePushRuleJob>("global", "content", m_notificationRules[index]);
|
||||
connect(job, &Quotient::BaseJob::success, this, [this, index]() {
|
||||
beginRemoveRows(QModelIndex(), index, index);
|
||||
m_notificationRules.removeAt(index);
|
||||
endRemoveRows();
|
||||
|
||||
if (m_notificationRules.count() == 0) {
|
||||
NotificationsManager::instance().deactivateKeywordNotificationAction();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> KeywordNotificationRuleModel::roleNames() const
|
||||
{
|
||||
return {{NameRole, QByteArrayLiteral("name")}};
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2022 James Graham <james.h.graham@protonmail.com>
|
||||
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <csapi/definitions/push_rule.h>
|
||||
|
||||
#include <QAbstractListModel>
|
||||
|
||||
/**
|
||||
* @class KeywordNotificationRuleModel
|
||||
*
|
||||
* This class defines the model for managing notification push rule keywords.
|
||||
*/
|
||||
class KeywordNotificationRuleModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Defines the model roles.
|
||||
*/
|
||||
enum EventRoles {
|
||||
NameRole = Qt::DisplayRole, /**< The push rule keyword. */
|
||||
};
|
||||
|
||||
KeywordNotificationRuleModel(QObject *parent = nullptr);
|
||||
|
||||
/**
|
||||
* @brief Get the given role value at the given index.
|
||||
*
|
||||
* @sa QAbstractItemModel::data
|
||||
*/
|
||||
[[nodiscard]] QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
|
||||
/**
|
||||
* @brief Number of rows in the model.
|
||||
*
|
||||
* @sa QAbstractItemModel::rowCount
|
||||
*/
|
||||
[[nodiscard]] int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
|
||||
/**
|
||||
* @brief Returns a mapping from Role enum values to role names.
|
||||
*
|
||||
* @sa EventRoles, QAbstractItemModel::roleNames()
|
||||
*/
|
||||
[[nodiscard]] QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
/**
|
||||
* @brief Add a new keyword to the model.
|
||||
*/
|
||||
Q_INVOKABLE void addKeyword(const QString &keyword);
|
||||
|
||||
/**
|
||||
* @brief Remove a keyword from the model.
|
||||
*/
|
||||
Q_INVOKABLE void removeKeywordAtIndex(int index);
|
||||
|
||||
private Q_SLOTS:
|
||||
void controllerConnectionChanged();
|
||||
void updateNotificationRules(const QString &type);
|
||||
|
||||
private:
|
||||
QList<QString> m_notificationRules;
|
||||
};
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
#include "livelocationsmodel.h"
|
||||
|
||||
#include <Quotient/events/roommessageevent.h>
|
||||
#include <events/roommessageevent.h>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
|
||||
445
src/models/pushrulemodel.cpp
Normal file
445
src/models/pushrulemodel.cpp
Normal file
@@ -0,0 +1,445 @@
|
||||
// SPDX-FileCopyrightText: 2022 James Graham <james.h.graham@protonmail.com>
|
||||
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
|
||||
#include "pushrulemodel.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include <connection.h>
|
||||
#include <converters.h>
|
||||
#include <csapi/definitions/push_ruleset.h>
|
||||
#include <csapi/pushrules.h>
|
||||
#include <jobs/basejob.h>
|
||||
#include <qobjectdefs.h>
|
||||
|
||||
#include "controller.h"
|
||||
#include "neochatconfig.h"
|
||||
#include "notificationsmanager.h"
|
||||
|
||||
// Alternate name text for default rules.
|
||||
static const QHash<QString, QString> defaultRuleNames = {
|
||||
{QStringLiteral(".m.rule.master"), QStringLiteral("Enable notifications for this account")},
|
||||
{QStringLiteral(".m.rule.room_one_to_one"), QStringLiteral("Messages in one-to-one chats")},
|
||||
{QStringLiteral(".m.rule.encrypted_room_one_to_one"), QStringLiteral("Encrypted messages in one-to-one chats")},
|
||||
{QStringLiteral(".m.rule.message"), QStringLiteral("Messages in group chats")},
|
||||
{QStringLiteral(".m.rule.encrypted"), QStringLiteral("Messages in encrypted group chats")},
|
||||
{QStringLiteral(".m.rule.tombstone"), QStringLiteral("Room upgrade messages")},
|
||||
{QStringLiteral(".m.rule.contains_display_name"), QStringLiteral("Messages containing my display name")},
|
||||
{QStringLiteral(".m.rule.roomnotif"), QStringLiteral("Whole room (@room) notifications")},
|
||||
{QStringLiteral(".m.rule.invite_for_me"), QStringLiteral("Invites to a room")},
|
||||
{QStringLiteral(".m.rule.call"), QStringLiteral("Call invitation")},
|
||||
};
|
||||
|
||||
// Sections for default rules.
|
||||
static const QHash<QString, PushNotificationSection::Section> defaultSections = {
|
||||
{QStringLiteral(".m.rule.master"), PushNotificationSection::Master},
|
||||
{QStringLiteral(".m.rule.room_one_to_one"), PushNotificationSection::Room},
|
||||
{QStringLiteral(".m.rule.encrypted_room_one_to_one"), PushNotificationSection::Room},
|
||||
{QStringLiteral(".m.rule.message"), PushNotificationSection::Room},
|
||||
{QStringLiteral(".m.rule.encrypted"), PushNotificationSection::Room},
|
||||
{QStringLiteral(".m.rule.tombstone"), PushNotificationSection::Room},
|
||||
{QStringLiteral(".m.rule.contains_display_name"), PushNotificationSection::Mentions},
|
||||
{QStringLiteral(".m.rule.roomnotif"), PushNotificationSection::Mentions},
|
||||
{QStringLiteral(".m.rule.invite_for_me"), PushNotificationSection::Invites},
|
||||
{QStringLiteral(".m.rule.call"), PushNotificationSection::Undefined}, // TODO: make invites when VOIP added.
|
||||
{QStringLiteral(".m.rule.suppress_notices"), PushNotificationSection::Undefined},
|
||||
{QStringLiteral(".m.rule.member_event"), PushNotificationSection::Undefined},
|
||||
{QStringLiteral(".m.rule.reaction"), PushNotificationSection::Undefined},
|
||||
{QStringLiteral(".m.rule.room.server_acl"), PushNotificationSection::Undefined},
|
||||
{QStringLiteral(".im.vector.jitsi"), PushNotificationSection::Undefined},
|
||||
};
|
||||
|
||||
// Default rules that don't have a highlight option as it would lead to all messages
|
||||
// in a room being highlighted.
|
||||
static const QStringList noHighlight = {
|
||||
QStringLiteral(".m.rule.room_one_to_one"),
|
||||
QStringLiteral(".m.rule.encrypted_room_one_to_one"),
|
||||
QStringLiteral(".m.rule.message"),
|
||||
QStringLiteral(".m.rule.encrypted"),
|
||||
};
|
||||
|
||||
PushRuleModel::PushRuleModel(QObject *parent)
|
||||
: QAbstractListModel(parent)
|
||||
{
|
||||
m_defaultKeywordAction = static_cast<PushNotificationAction::Action>(NeoChatConfig::self()->keywordPushRuleDefault());
|
||||
|
||||
if (Controller::instance().activeConnection()) {
|
||||
controllerConnectionChanged();
|
||||
}
|
||||
connect(&Controller::instance(), &Controller::activeConnectionChanged, this, &PushRuleModel::controllerConnectionChanged);
|
||||
}
|
||||
|
||||
void PushRuleModel::controllerConnectionChanged()
|
||||
{
|
||||
connect(Controller::instance().activeConnection(), &Quotient::Connection::accountDataChanged, this, &PushRuleModel::updateNotificationRules);
|
||||
updateNotificationRules("m.push_rules");
|
||||
}
|
||||
|
||||
void PushRuleModel::updateNotificationRules(const QString &type)
|
||||
{
|
||||
if (type != "m.push_rules") {
|
||||
return;
|
||||
}
|
||||
|
||||
const QJsonObject ruleDataJson = Controller::instance().activeConnection()->accountDataJson("m.push_rules");
|
||||
const Quotient::PushRuleset ruleData = Quotient::fromJson<Quotient::PushRuleset>(ruleDataJson["global"].toObject());
|
||||
|
||||
beginResetModel();
|
||||
m_rules.clear();
|
||||
|
||||
// Doing this 5 times because PushRuleset is a struct.
|
||||
setRules(ruleData.override, PushNotificationKind::Override);
|
||||
setRules(ruleData.content, PushNotificationKind::Content);
|
||||
setRules(ruleData.room, PushNotificationKind::Room);
|
||||
setRules(ruleData.sender, PushNotificationKind::Sender);
|
||||
setRules(ruleData.underride, PushNotificationKind::Underride);
|
||||
|
||||
Q_EMIT globalNotificationsEnabledChanged();
|
||||
Q_EMIT globalNotificationsSetChanged();
|
||||
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
void PushRuleModel::setRules(QVector<Quotient::PushRule> rules, PushNotificationKind::Kind kind)
|
||||
{
|
||||
for (const auto &rule : rules) {
|
||||
QString roomId;
|
||||
if (rule.conditions.size() > 0) {
|
||||
for (const auto &condition : rule.conditions) {
|
||||
if (condition.key == QStringLiteral("room_id")) {
|
||||
roomId = condition.pattern;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_rules.append(Rule{
|
||||
rule.ruleId,
|
||||
kind,
|
||||
variantToAction(rule.actions, rule.enabled),
|
||||
getSection(rule),
|
||||
rule.enabled,
|
||||
roomId,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
int PushRuleModel::getRuleIndex(const QString &ruleId) const
|
||||
{
|
||||
for (auto i = 0; i < m_rules.count(); i++) {
|
||||
if (m_rules[i].id == ruleId) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
PushNotificationSection::Section PushRuleModel::getSection(Quotient::PushRule rule)
|
||||
{
|
||||
auto ruleId = rule.ruleId;
|
||||
|
||||
if (defaultSections.contains(ruleId)) {
|
||||
return defaultSections.value(ruleId);
|
||||
} else {
|
||||
/**
|
||||
* If the rule name resolves to a matrix id for a room that the user is part
|
||||
* of it shouldn't appear in the global list as it's overriding the global
|
||||
* state for that room.
|
||||
*
|
||||
* Rooms that the user hasn't joined shouldn't have a rule.
|
||||
*/
|
||||
auto connection = Controller::instance().activeConnection();
|
||||
if (connection->room(ruleId) != nullptr) {
|
||||
return PushNotificationSection::Undefined;
|
||||
}
|
||||
/**
|
||||
* If the rule name resolves to a matrix id for a user it shouldn't appear
|
||||
* in the global list as it's a rule to block notifications from a user and
|
||||
* is handled elsewhere.
|
||||
*/
|
||||
auto testUserId = ruleId;
|
||||
// Rules for user matrix IDs often don't have the @ on the beginning so add
|
||||
// if not there to avoid malformed ID.
|
||||
if (!testUserId.startsWith(u'@')) {
|
||||
testUserId.prepend(u'@');
|
||||
}
|
||||
if (connection->user(testUserId) != nullptr) {
|
||||
return PushNotificationSection::Undefined;
|
||||
}
|
||||
// If the rule has push conditions and one is a room ID it is a room only keyword.
|
||||
if (!rule.conditions.isEmpty()) {
|
||||
for (auto condition : rule.conditions) {
|
||||
if (condition.key == QStringLiteral("room_id")) {
|
||||
return PushNotificationSection::RoomKeywords;
|
||||
}
|
||||
}
|
||||
}
|
||||
return PushNotificationSection::Keywords;
|
||||
}
|
||||
}
|
||||
|
||||
PushNotificationAction::Action PushRuleModel::defaultState() const
|
||||
{
|
||||
return m_defaultKeywordAction;
|
||||
}
|
||||
|
||||
void PushRuleModel::setDefaultState(PushNotificationAction::Action defaultState)
|
||||
{
|
||||
if (defaultState == m_defaultKeywordAction) {
|
||||
return;
|
||||
}
|
||||
m_defaultKeywordAction = defaultState;
|
||||
NeoChatConfig::setKeywordPushRuleDefault(m_defaultKeywordAction);
|
||||
Q_EMIT defaultStateChanged();
|
||||
}
|
||||
|
||||
bool PushRuleModel::globalNotificationsEnabled() const
|
||||
{
|
||||
auto masterIndex = getRuleIndex(QStringLiteral(".m.rule.master"));
|
||||
if (masterIndex > -1) {
|
||||
return !m_rules[masterIndex].enabled;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void PushRuleModel::setGlobalNotificationsEnabled(bool enabled)
|
||||
{
|
||||
setNotificationRuleEnabled("override", ".m.rule.master", !enabled);
|
||||
}
|
||||
|
||||
bool PushRuleModel::globalNotificationsSet() const
|
||||
{
|
||||
return getRuleIndex(QStringLiteral(".m.rule.master")) > -1;
|
||||
}
|
||||
|
||||
QVariant PushRuleModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
if (index.row() >= rowCount()) {
|
||||
qDebug() << "PushRuleModel, something's wrong: index.row() >= m_rules.count()";
|
||||
return {};
|
||||
}
|
||||
|
||||
if (role == NameRole) {
|
||||
auto ruleId = m_rules.at(index.row()).id;
|
||||
if (defaultRuleNames.contains(ruleId)) {
|
||||
return defaultRuleNames.value(ruleId);
|
||||
} else {
|
||||
return ruleId;
|
||||
}
|
||||
}
|
||||
if (role == IdRole) {
|
||||
return m_rules.at(index.row()).id;
|
||||
}
|
||||
if (role == KindRole) {
|
||||
return m_rules.at(index.row()).kind;
|
||||
}
|
||||
if (role == ActionRole) {
|
||||
return m_rules.at(index.row()).action;
|
||||
}
|
||||
if (role == HighlightableRole) {
|
||||
return !noHighlight.contains(m_rules.at(index.row()).id);
|
||||
}
|
||||
if (role == DeletableRole) {
|
||||
return !m_rules.at(index.row()).id.startsWith(QStringLiteral("."));
|
||||
}
|
||||
if (role == SectionRole) {
|
||||
return m_rules.at(index.row()).section;
|
||||
}
|
||||
if (role == RoomIdRole) {
|
||||
return m_rules.at(index.row()).roomId;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
int PushRuleModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(parent)
|
||||
|
||||
return m_rules.count();
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> PushRuleModel::roleNames() const
|
||||
{
|
||||
QHash<int, QByteArray> roles = QAbstractItemModel::roleNames();
|
||||
roles[NameRole] = "name";
|
||||
roles[IdRole] = "id";
|
||||
roles[KindRole] = "kind";
|
||||
roles[ActionRole] = "ruleAction";
|
||||
roles[HighlightableRole] = "highlightable";
|
||||
roles[DeletableRole] = "deletable";
|
||||
roles[SectionRole] = "section";
|
||||
roles[RoomIdRole] = "roomId";
|
||||
return roles;
|
||||
}
|
||||
|
||||
void PushRuleModel::setPushRuleAction(const QString &id, PushNotificationAction::Action action)
|
||||
{
|
||||
int index = getRuleIndex(id);
|
||||
if (index == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto rule = m_rules[index];
|
||||
|
||||
// Override rules need to be disabled when off so that other rules can match the message if they apply.
|
||||
if (action == PushNotificationAction::Off && rule.kind == PushNotificationKind::Override) {
|
||||
setNotificationRuleEnabled(PushNotificationKind::kindString(rule.kind), rule.id, false);
|
||||
} else if (rule.kind == PushNotificationKind::Override) {
|
||||
setNotificationRuleEnabled(PushNotificationKind::kindString(rule.kind), rule.id, true);
|
||||
}
|
||||
|
||||
setNotificationRuleActions(PushNotificationKind::kindString(rule.kind), rule.id, action);
|
||||
}
|
||||
|
||||
void PushRuleModel::addKeyword(const QString &keyword, const QString &roomId)
|
||||
{
|
||||
PushNotificationKind::Kind kind = PushNotificationKind::Content;
|
||||
const QVector<QVariant> actions = actionToVariant(m_defaultKeywordAction);
|
||||
QVector<Quotient::PushCondition> pushConditions;
|
||||
if (!roomId.isEmpty()) {
|
||||
kind = PushNotificationKind::Override;
|
||||
|
||||
Quotient::PushCondition roomCondition;
|
||||
roomCondition.kind = "event_match";
|
||||
roomCondition.key = "room_id";
|
||||
roomCondition.pattern = roomId;
|
||||
pushConditions.append(roomCondition);
|
||||
|
||||
Quotient::PushCondition keywordCondition;
|
||||
keywordCondition.kind = "event_match";
|
||||
keywordCondition.key = "content.body";
|
||||
keywordCondition.pattern = keyword;
|
||||
pushConditions.append(keywordCondition);
|
||||
}
|
||||
|
||||
auto job = Controller::instance().activeConnection()->callApi<Quotient::SetPushRuleJob>("global",
|
||||
PushNotificationKind::kindString(kind),
|
||||
keyword,
|
||||
actions,
|
||||
QLatin1String(""),
|
||||
QLatin1String(""),
|
||||
pushConditions,
|
||||
roomId.isEmpty() ? keyword : QLatin1String(""));
|
||||
connect(job, &Quotient::BaseJob::failure, this, [job, keyword]() {
|
||||
qWarning() << QLatin1String("Unable to set push rule for keyword %1: ").arg(keyword) << job->errorString();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* The rule never being removed from the list by this function is intentional. When
|
||||
* the server is updated the new push rule account data will be synced and it will
|
||||
* be removed when the model is updated then.
|
||||
*/
|
||||
void PushRuleModel::removeKeyword(const QString &keyword)
|
||||
{
|
||||
int index = getRuleIndex(keyword);
|
||||
if (index == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto kind = PushNotificationKind::kindString(m_rules[index].kind);
|
||||
auto job = Controller::instance().activeConnection()->callApi<Quotient::DeletePushRuleJob>("global", kind, m_rules[index].id);
|
||||
connect(job, &Quotient::BaseJob::failure, this, [this, job, index]() {
|
||||
qWarning() << QLatin1String("Unable to remove push rule for keyword %1: ").arg(m_rules[index].id) << job->errorString();
|
||||
});
|
||||
}
|
||||
|
||||
void PushRuleModel::setNotificationRuleEnabled(const QString &kind, const QString &ruleId, bool enabled)
|
||||
{
|
||||
auto job = Controller::instance().activeConnection()->callApi<Quotient::IsPushRuleEnabledJob>("global", kind, ruleId);
|
||||
connect(job, &Quotient::BaseJob::success, this, [job, kind, ruleId, enabled]() {
|
||||
if (job->enabled() != enabled) {
|
||||
Controller::instance().activeConnection()->callApi<Quotient::SetPushRuleEnabledJob>("global", kind, ruleId, enabled);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void PushRuleModel::setNotificationRuleActions(const QString &kind, const QString &ruleId, PushNotificationAction::Action action)
|
||||
{
|
||||
QVector<QVariant> actions;
|
||||
if (ruleId == ".m.rule.call") {
|
||||
actions = actionToVariant(action, "ring");
|
||||
} else {
|
||||
actions = actionToVariant(action);
|
||||
}
|
||||
|
||||
Controller::instance().activeConnection()->callApi<Quotient::SetPushRuleActionsJob>("global", kind, ruleId, actions);
|
||||
}
|
||||
|
||||
PushNotificationAction::Action PushRuleModel::variantToAction(const QVector<QVariant> &actions, bool enabled)
|
||||
{
|
||||
bool notify = false;
|
||||
bool isNoisy = false;
|
||||
bool highlightEnabled = false;
|
||||
for (const auto &i : actions) {
|
||||
auto actionString = i.toString();
|
||||
if (!actionString.isEmpty()) {
|
||||
if (actionString == QLatin1String("notify")) {
|
||||
notify = true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
QJsonObject action = i.toJsonObject();
|
||||
if (action["set_tweak"].toString() == "sound") {
|
||||
isNoisy = true;
|
||||
} else if (action["set_tweak"].toString() == "highlight") {
|
||||
if (action["value"].toString() != "false") {
|
||||
highlightEnabled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!enabled) {
|
||||
return PushNotificationAction::Off;
|
||||
}
|
||||
|
||||
if (notify) {
|
||||
if (isNoisy && highlightEnabled) {
|
||||
return PushNotificationAction::NoisyHighlight;
|
||||
} else if (isNoisy) {
|
||||
return PushNotificationAction::Noisy;
|
||||
} else if (highlightEnabled) {
|
||||
return PushNotificationAction::Highlight;
|
||||
} else {
|
||||
return PushNotificationAction::On;
|
||||
}
|
||||
} else {
|
||||
return PushNotificationAction::Off;
|
||||
}
|
||||
}
|
||||
|
||||
QVector<QVariant> PushRuleModel::actionToVariant(PushNotificationAction::Action action, const QString &sound)
|
||||
{
|
||||
// The caller should never try to set the state to unknown.
|
||||
// It exists only as a default state to diable the settings options until the actual state is retrieved from the server.
|
||||
if (action == PushNotificationAction::Unknown) {
|
||||
Q_ASSERT(false);
|
||||
return QVector<QVariant>();
|
||||
}
|
||||
|
||||
QVector<QVariant> actions;
|
||||
|
||||
if (action != PushNotificationAction::Off) {
|
||||
actions.append("notify");
|
||||
} else {
|
||||
actions.append("dont_notify");
|
||||
}
|
||||
if (action == PushNotificationAction::Noisy || action == PushNotificationAction::NoisyHighlight) {
|
||||
QJsonObject soundTweak;
|
||||
soundTweak.insert("set_tweak", "sound");
|
||||
soundTweak.insert("value", sound);
|
||||
actions.append(soundTweak);
|
||||
}
|
||||
if (action == PushNotificationAction::Highlight || action == PushNotificationAction::NoisyHighlight) {
|
||||
QJsonObject highlightTweak;
|
||||
highlightTweak.insert("set_tweak", "highlight");
|
||||
actions.append(highlightTweak);
|
||||
}
|
||||
|
||||
return actions;
|
||||
}
|
||||
241
src/models/pushrulemodel.h
Normal file
241
src/models/pushrulemodel.h
Normal file
@@ -0,0 +1,241 @@
|
||||
// SPDX-FileCopyrightText: 2022 James Graham <james.h.graham@protonmail.com>
|
||||
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QAbstractListModel>
|
||||
|
||||
#include <csapi/definitions/push_rule.h>
|
||||
|
||||
#include "notificationsmanager.h"
|
||||
|
||||
/**
|
||||
* @class PushNotificationKind
|
||||
*
|
||||
* A class with the Kind enum for push notifications and helper functions.
|
||||
*
|
||||
* The kind relates to the kinds of push rule definied in the matrix spec, see
|
||||
* https://spec.matrix.org/v1.7/client-server-api/#push-rules for full details.
|
||||
*/
|
||||
class PushNotificationKind : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Defines the different kinds of push rule.
|
||||
*/
|
||||
enum Kind {
|
||||
Override = 0, /**< The highest priority rules. */
|
||||
Content, /**< These configure behaviour for messages that match certain patterns. */
|
||||
Room, /**< These rules change the behaviour of all messages for a given room. */
|
||||
Sender, /**< These rules configure notification behaviour for messages from a specific Matrix user ID. */
|
||||
Underride, /**< These are identical to override rules, but have a lower priority than content, room and sender rules. */
|
||||
};
|
||||
Q_ENUM(Kind);
|
||||
|
||||
/**
|
||||
* @brief Translate the Kind enum value to a human readable string.
|
||||
*
|
||||
* @sa Kind
|
||||
*/
|
||||
static QString kindString(Kind kind)
|
||||
{
|
||||
switch (kind) {
|
||||
case Kind::Override:
|
||||
return QLatin1String("override");
|
||||
case Kind::Content:
|
||||
return QLatin1String("content");
|
||||
case Kind::Room:
|
||||
return QLatin1String("room");
|
||||
case Kind::Sender:
|
||||
return QLatin1String("sender");
|
||||
case Kind::Underride:
|
||||
return QLatin1String("underride");
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* @class PushNotificationSection
|
||||
*
|
||||
* A class with the Section enum for push notifications and helper functions.
|
||||
*
|
||||
* @note This is different from the PushNotificationKind and instead is used for sorting
|
||||
* in the settings page which is not necessarily by Kind.
|
||||
*
|
||||
* @sa PushNotificationKind
|
||||
*/
|
||||
class PushNotificationSection : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Defines the sections to sort push rules into.
|
||||
*/
|
||||
enum Section {
|
||||
Master = 0, /**< The master push rule */
|
||||
Room, /**< Push rules relating to all rooms. */
|
||||
Mentions, /**< Push rules relating to user mentions. */
|
||||
Keywords, /**< Global Keyword push rules. */
|
||||
RoomKeywords, /**< Keyword push rules that only apply to a specific room. */
|
||||
Invites, /**< Push rules relating to invites. */
|
||||
/**
|
||||
* @brief Push rules that should never be shown.
|
||||
*
|
||||
* There are numerous rules that get set that shouldn't be shown in the general
|
||||
* list e.g. The array of rules used to override global settings in individual
|
||||
* rooms.
|
||||
*/
|
||||
Undefined,
|
||||
};
|
||||
Q_ENUM(Section);
|
||||
|
||||
/**
|
||||
* @brief Translate the Section enum value to a human readable string.
|
||||
*
|
||||
* @sa Section
|
||||
*/
|
||||
static QString sectionString(Section section)
|
||||
{
|
||||
switch (section) {
|
||||
case Section::Master:
|
||||
return QLatin1String("Master");
|
||||
case Section::Room:
|
||||
return QLatin1String("Room Notifications");
|
||||
case Section::Mentions:
|
||||
return QLatin1String("@Mentions");
|
||||
case Section::Keywords:
|
||||
return QLatin1String("Keywords");
|
||||
case Section::Invites:
|
||||
return QLatin1String("Invites");
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* @class PushRuleModel
|
||||
*
|
||||
* This class defines the model for managing notification push rule keywords.
|
||||
*/
|
||||
class PushRuleModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
/**
|
||||
* @brief The default state for any newly created keyword rule.
|
||||
*/
|
||||
Q_PROPERTY(PushNotificationAction::Action defaultState READ defaultState WRITE setDefaultState NOTIFY defaultStateChanged)
|
||||
|
||||
/**
|
||||
* @brief The global notification state.
|
||||
*
|
||||
* If this rule is set to off all push notifications are disabled regardless
|
||||
* of other settings.
|
||||
*/
|
||||
Q_PROPERTY(bool globalNotificationsEnabled READ globalNotificationsEnabled WRITE setGlobalNotificationsEnabled NOTIFY globalNotificationsEnabledChanged)
|
||||
|
||||
/**
|
||||
* @brief Whether the global notification state has been retrieved from the server.
|
||||
*
|
||||
* @sa globalNotificationsEnabled, PushNotificationAction::Action
|
||||
*/
|
||||
Q_PROPERTY(bool globalNotificationsSet READ globalNotificationsSet NOTIFY globalNotificationsSetChanged)
|
||||
|
||||
public:
|
||||
struct Rule {
|
||||
QString id;
|
||||
PushNotificationKind::Kind kind;
|
||||
PushNotificationAction::Action action;
|
||||
PushNotificationSection::Section section;
|
||||
bool enabled;
|
||||
QString roomId;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Defines the model roles.
|
||||
*/
|
||||
enum EventRoles {
|
||||
NameRole = Qt::DisplayRole, /**< The push rule name. */
|
||||
IdRole, /**< The push rule ID. */
|
||||
KindRole, /**< The kind of notification rule; override, content, etc. */
|
||||
ActionRole, /**< The PushNotificationAction for the rule. */
|
||||
HighlightableRole, /**< Whether the rule can have a highlight action. */
|
||||
DeletableRole, /**< Whether the rule can be deleted the rule. */
|
||||
SectionRole, /**< The section to sort into in the settings page. */
|
||||
RoomIdRole, /**< The room the rule applies to (blank if global). */
|
||||
};
|
||||
Q_ENUM(EventRoles)
|
||||
|
||||
PushRuleModel(QObject *parent = nullptr);
|
||||
|
||||
[[nodiscard]] PushNotificationAction::Action defaultState() const;
|
||||
void setDefaultState(PushNotificationAction::Action defaultState);
|
||||
|
||||
[[nodiscard]] bool globalNotificationsEnabled() const;
|
||||
void setGlobalNotificationsEnabled(bool enabled);
|
||||
|
||||
[[nodiscard]] bool globalNotificationsSet() const;
|
||||
|
||||
/**
|
||||
* @brief Get the given role value at the given index.
|
||||
*
|
||||
* @sa QAbstractItemModel::data
|
||||
*/
|
||||
[[nodiscard]] QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
|
||||
/**
|
||||
* @brief Number of rows in the model.
|
||||
*
|
||||
* @sa QAbstractItemModel::rowCount
|
||||
*/
|
||||
[[nodiscard]] int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
|
||||
/**
|
||||
* @brief Returns a mapping from Role enum values to role names.
|
||||
*
|
||||
* @sa EventRoles, QAbstractItemModel::roleNames()
|
||||
*/
|
||||
[[nodiscard]] QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
Q_INVOKABLE void setPushRuleAction(const QString &id, PushNotificationAction::Action action);
|
||||
|
||||
/**
|
||||
* @brief Add a new keyword to the model.
|
||||
*/
|
||||
Q_INVOKABLE void addKeyword(const QString &keyword, const QString &roomId = {});
|
||||
|
||||
/**
|
||||
* @brief Remove a keyword from the model.
|
||||
*/
|
||||
Q_INVOKABLE void removeKeyword(const QString &keyword);
|
||||
|
||||
Q_SIGNALS:
|
||||
void defaultStateChanged();
|
||||
void globalNotificationsEnabledChanged();
|
||||
void globalNotificationsSetChanged();
|
||||
|
||||
private Q_SLOTS:
|
||||
void controllerConnectionChanged();
|
||||
void updateNotificationRules(const QString &type);
|
||||
|
||||
private:
|
||||
PushNotificationAction::Action m_defaultKeywordAction;
|
||||
QList<Rule> m_rules;
|
||||
|
||||
void setRules(QVector<Quotient::PushRule> rules, PushNotificationKind::Kind kind);
|
||||
|
||||
int getRuleIndex(const QString &ruleId) const;
|
||||
PushNotificationSection::Section getSection(Quotient::PushRule rule);
|
||||
|
||||
void setNotificationRuleEnabled(const QString &kind, const QString &ruleId, bool enabled);
|
||||
void setNotificationRuleActions(const QString &kind, const QString &ruleId, PushNotificationAction::Action action);
|
||||
PushNotificationAction::Action variantToAction(const QVector<QVariant> &actions, bool enabled);
|
||||
QVector<QVariant> actionToVariant(PushNotificationAction::Action action, const QString &sound = "default");
|
||||
};
|
||||
Q_DECLARE_METATYPE(PushRuleModel *)
|
||||
@@ -54,6 +54,10 @@
|
||||
<entry name="LastSaveDirectory" type="String">
|
||||
<label>Directory last used for saving a file</label>
|
||||
</entry>
|
||||
<entry name="KeywordPushRuleDefault" type="int">
|
||||
<label>The default setting for a new keyword push rule.</label>
|
||||
<default>4</default>
|
||||
</entry>
|
||||
</group>
|
||||
<group name="Timeline">
|
||||
<entry name="ShowAvatarInTimeline" type="bool">
|
||||
|
||||
@@ -41,12 +41,6 @@ NotificationsManager &NotificationsManager::instance()
|
||||
NotificationsManager::NotificationsManager(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
// Can't connect the signal up until the active connection has been established by the controller
|
||||
connect(&Controller::instance(), &Controller::activeConnectionChanged, this, [this]() {
|
||||
connect(Controller::instance().activeConnection(), &Connection::accountDataChanged, this, &NotificationsManager::updateNotificationRules);
|
||||
// Ensure that the push rule states are retrieved after the connection is changed
|
||||
updateNotificationRules("m.push_rules");
|
||||
});
|
||||
}
|
||||
|
||||
#ifdef QUOTIENT_07
|
||||
@@ -300,309 +294,3 @@ void NotificationsManager::clearInvitationNotification(const QString &roomId)
|
||||
m_invitations[roomId]->close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The master push rule sets all notifications to off when enabled
|
||||
* see https://spec.matrix.org/v1.3/client-server-api/#default-override-rules
|
||||
* therefore to enable push rules the master rule needs to be disabled and vice versa
|
||||
*/
|
||||
void NotificationsManager::setGlobalNotificationsEnabled(bool enabled)
|
||||
{
|
||||
setNotificationRuleEnabled("override", ".m.rule.master", !enabled);
|
||||
}
|
||||
|
||||
void NotificationsManager::setOneToOneNotificationAction(PushNotificationAction::Action action)
|
||||
{
|
||||
setNotificationRuleActions("underride", ".m.rule.room_one_to_one", action);
|
||||
}
|
||||
|
||||
void NotificationsManager::setEncryptedOneToOneNotificationAction(PushNotificationAction::Action action)
|
||||
{
|
||||
setNotificationRuleActions("underride", ".m.rule.encrypted_room_one_to_one", action);
|
||||
}
|
||||
|
||||
void NotificationsManager::setGroupChatNotificationAction(PushNotificationAction::Action action)
|
||||
{
|
||||
setNotificationRuleActions("underride", ".m.rule.message", action);
|
||||
}
|
||||
|
||||
void NotificationsManager::setEncryptedGroupChatNotificationAction(PushNotificationAction::Action action)
|
||||
{
|
||||
setNotificationRuleActions("underride", ".m.rule.encrypted", action);
|
||||
}
|
||||
|
||||
/*
|
||||
* .m.rule.contains_display_name is an override rule so it needs to be disabled when off
|
||||
* so that other rules can match the message if they apply.
|
||||
*/
|
||||
void NotificationsManager::setDisplayNameNotificationAction(PushNotificationAction::Action action)
|
||||
{
|
||||
if (action == PushNotificationAction::Off) {
|
||||
setNotificationRuleEnabled("override", ".m.rule.contains_display_name", false);
|
||||
} else {
|
||||
setNotificationRuleActions("override", ".m.rule.contains_display_name", action);
|
||||
setNotificationRuleEnabled("override", ".m.rule.contains_display_name", true);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* .m.rule.roomnotif is an override rule so it needs to be disabled when off
|
||||
* so that other rules can match the message if they apply.
|
||||
*/
|
||||
void NotificationsManager::setRoomNotificationAction(PushNotificationAction::Action action)
|
||||
{
|
||||
if (action == PushNotificationAction::Off) {
|
||||
setNotificationRuleEnabled("override", ".m.rule.roomnotif", false);
|
||||
} else {
|
||||
setNotificationRuleActions("override", ".m.rule.roomnotif", action);
|
||||
setNotificationRuleEnabled("override", ".m.rule.roomnotif", true);
|
||||
}
|
||||
}
|
||||
|
||||
void NotificationsManager::initializeKeywordNotificationAction()
|
||||
{
|
||||
m_keywordNotificationAction = PushNotificationAction::Highlight;
|
||||
Q_EMIT keywordNotificationActionChanged(m_keywordNotificationAction);
|
||||
}
|
||||
|
||||
void NotificationsManager::deactivateKeywordNotificationAction()
|
||||
{
|
||||
m_keywordNotificationAction = PushNotificationAction::Off;
|
||||
Q_EMIT keywordNotificationActionChanged(m_keywordNotificationAction);
|
||||
}
|
||||
|
||||
QVector<QVariant> NotificationsManager::getKeywordNotificationActions()
|
||||
{
|
||||
return toActions(m_keywordNotificationAction);
|
||||
}
|
||||
|
||||
void NotificationsManager::setKeywordNotificationAction(PushNotificationAction::Action action)
|
||||
{
|
||||
// Unlike the other rules this needs to be set here for the case where there are no keyords.
|
||||
m_keywordNotificationAction = action;
|
||||
Q_EMIT keywordNotificationActionChanged(m_keywordNotificationAction);
|
||||
|
||||
const QJsonObject accountData = Controller::instance().activeConnection()->accountDataJson("m.push_rules");
|
||||
const QJsonArray contentRuleArray = accountData["global"].toObject()["content"].toArray();
|
||||
for (const auto &i : contentRuleArray) {
|
||||
const QJsonObject contentRule = i.toObject();
|
||||
if (contentRule["rule_id"].toString()[0] != '.') {
|
||||
setNotificationRuleActions("content", contentRule["rule_id"].toString(), action);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* .m.rule.invite_for_me is an override rule so it needs to be disabled when off
|
||||
* so that other rules can match the message if they apply.
|
||||
*/
|
||||
void NotificationsManager::setInviteNotificationAction(PushNotificationAction::Action action)
|
||||
{
|
||||
if (action == PushNotificationAction::Off) {
|
||||
setNotificationRuleEnabled("override", ".m.rule.invite_for_me", false);
|
||||
} else {
|
||||
setNotificationRuleActions("override", ".m.rule.invite_for_me", action);
|
||||
setNotificationRuleEnabled("override", ".m.rule.invite_for_me", true);
|
||||
}
|
||||
}
|
||||
|
||||
void NotificationsManager::setCallInviteNotificationAction(PushNotificationAction::Action action)
|
||||
{
|
||||
setNotificationRuleActions("underride", ".m.rule.call", action);
|
||||
}
|
||||
|
||||
/*
|
||||
* .m.rule.tombstone is an override rule so it needs to be disabled when off
|
||||
* so that other rules can match the message if they apply.
|
||||
*/
|
||||
void NotificationsManager::setTombstoneNotificationAction(PushNotificationAction::Action action)
|
||||
{
|
||||
if (action == PushNotificationAction::Off) {
|
||||
setNotificationRuleEnabled("override", ".m.rule.tombstone", false);
|
||||
} else {
|
||||
setNotificationRuleActions("override", ".m.rule.tombstone", action);
|
||||
setNotificationRuleEnabled("override", ".m.rule.tombstone", true);
|
||||
}
|
||||
}
|
||||
|
||||
void NotificationsManager::updateNotificationRules(const QString &type)
|
||||
{
|
||||
if (type != "m.push_rules") {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Controller::instance().activeConnection()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const QJsonObject accountData = Controller::instance().activeConnection()->accountDataJson("m.push_rules");
|
||||
|
||||
// Update override rules
|
||||
const QJsonArray overrideRuleArray = accountData["global"].toObject()["override"].toArray();
|
||||
for (const auto &i : overrideRuleArray) {
|
||||
const QJsonObject overrideRule = i.toObject();
|
||||
if (overrideRule["rule_id"] == ".m.rule.master") {
|
||||
bool ruleEnabled = overrideRule["enabled"].toBool();
|
||||
m_globalNotificationsEnabled = !ruleEnabled;
|
||||
if (!m_globalNotificationsSet) {
|
||||
m_globalNotificationsSet = true;
|
||||
}
|
||||
Q_EMIT globalNotificationsEnabledChanged(m_globalNotificationsEnabled);
|
||||
}
|
||||
|
||||
const PushNotificationAction::Action action = toAction(overrideRule);
|
||||
|
||||
if (overrideRule["rule_id"] == ".m.rule.contains_display_name") {
|
||||
m_displayNameNotificationAction = action;
|
||||
Q_EMIT displayNameNotificationActionChanged(m_displayNameNotificationAction);
|
||||
} else if (overrideRule["rule_id"] == ".m.rule.roomnotif") {
|
||||
m_roomNotificationAction = action;
|
||||
Q_EMIT roomNotificationActionChanged(m_roomNotificationAction);
|
||||
} else if (overrideRule["rule_id"] == ".m.rule.invite_for_me") {
|
||||
m_inviteNotificationAction = action;
|
||||
Q_EMIT inviteNotificationActionChanged(m_inviteNotificationAction);
|
||||
} else if (overrideRule["rule_id"] == ".m.rule.tombstone") {
|
||||
m_tombstoneNotificationAction = action;
|
||||
Q_EMIT tombstoneNotificationActionChanged(m_tombstoneNotificationAction);
|
||||
}
|
||||
}
|
||||
|
||||
// Update content rules
|
||||
const QJsonArray contentRuleArray = accountData["global"].toObject()["content"].toArray();
|
||||
PushNotificationAction::Action keywordAction = PushNotificationAction::Unknown;
|
||||
for (const auto &i : contentRuleArray) {
|
||||
const QJsonObject contentRule = i.toObject();
|
||||
const PushNotificationAction::Action action = toAction(contentRule);
|
||||
bool actionMismatch = false;
|
||||
|
||||
if (contentRule["rule_id"].toString()[0] != '.' && !actionMismatch) {
|
||||
if (keywordAction == PushNotificationAction::Unknown) {
|
||||
keywordAction = action;
|
||||
m_keywordNotificationAction = action;
|
||||
Q_EMIT keywordNotificationActionChanged(m_keywordNotificationAction);
|
||||
} else if (action != keywordAction) {
|
||||
actionMismatch = true;
|
||||
m_keywordNotificationAction = PushNotificationAction::On;
|
||||
Q_EMIT keywordNotificationActionChanged(m_keywordNotificationAction);
|
||||
}
|
||||
}
|
||||
}
|
||||
// If there are no keywords set the state to off, this is the only time it'll be in the off state
|
||||
if (keywordAction == PushNotificationAction::Unknown) {
|
||||
m_keywordNotificationAction = PushNotificationAction::Off;
|
||||
Q_EMIT keywordNotificationActionChanged(m_keywordNotificationAction);
|
||||
}
|
||||
|
||||
// Update underride rules
|
||||
const QJsonArray underrideRuleArray = accountData["global"].toObject()["underride"].toArray();
|
||||
for (const auto &i : underrideRuleArray) {
|
||||
const QJsonObject underrideRule = i.toObject();
|
||||
const PushNotificationAction::Action action = toAction(underrideRule);
|
||||
|
||||
if (underrideRule["rule_id"] == ".m.rule.room_one_to_one") {
|
||||
m_oneToOneNotificationAction = action;
|
||||
Q_EMIT oneToOneNotificationActionChanged(m_oneToOneNotificationAction);
|
||||
} else if (underrideRule["rule_id"] == ".m.rule.encrypted_room_one_to_one") {
|
||||
m_encryptedOneToOneNotificationAction = action;
|
||||
Q_EMIT encryptedOneToOneNotificationActionChanged(m_encryptedOneToOneNotificationAction);
|
||||
} else if (underrideRule["rule_id"] == ".m.rule.message") {
|
||||
m_groupChatNotificationAction = action;
|
||||
Q_EMIT groupChatNotificationActionChanged(m_groupChatNotificationAction);
|
||||
} else if (underrideRule["rule_id"] == ".m.rule.encrypted") {
|
||||
m_encryptedGroupChatNotificationAction = action;
|
||||
Q_EMIT encryptedGroupChatNotificationActionChanged(m_encryptedGroupChatNotificationAction);
|
||||
} else if (underrideRule["rule_id"] == ".m.rule.call") {
|
||||
m_callInviteNotificationAction = action;
|
||||
Q_EMIT callInviteNotificationActionChanged(m_callInviteNotificationAction);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NotificationsManager::setNotificationRuleEnabled(const QString &kind, const QString &ruleId, bool enabled)
|
||||
{
|
||||
auto job = Controller::instance().activeConnection()->callApi<IsPushRuleEnabledJob>("global", kind, ruleId);
|
||||
connect(job, &BaseJob::success, this, [job, kind, ruleId, enabled]() {
|
||||
if (job->enabled() != enabled) {
|
||||
Controller::instance().activeConnection()->callApi<SetPushRuleEnabledJob>("global", kind, ruleId, enabled);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void NotificationsManager::setNotificationRuleActions(const QString &kind, const QString &ruleId, PushNotificationAction::Action action)
|
||||
{
|
||||
QVector<QVariant> actions;
|
||||
if (ruleId == ".m.rule.call") {
|
||||
actions = toActions(action, "ring");
|
||||
} else {
|
||||
actions = toActions(action);
|
||||
}
|
||||
|
||||
Controller::instance().activeConnection()->callApi<SetPushRuleActionsJob>("global", kind, ruleId, actions);
|
||||
}
|
||||
|
||||
PushNotificationAction::Action NotificationsManager::toAction(const QJsonObject &rule)
|
||||
{
|
||||
const QJsonArray actions = rule["actions"].toArray();
|
||||
bool isNoisy = false;
|
||||
bool highlightEnabled = false;
|
||||
const bool enabled = rule["enabled"].toBool();
|
||||
for (const auto &i : actions) {
|
||||
QJsonObject action = i.toObject();
|
||||
if (action["set_tweak"].toString() == "sound") {
|
||||
isNoisy = true;
|
||||
} else if (action["set_tweak"].toString() == "highlight") {
|
||||
if (action["value"].toString() != "false") {
|
||||
highlightEnabled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!enabled) {
|
||||
return PushNotificationAction::Off;
|
||||
}
|
||||
|
||||
if (actions[0] == "notify") {
|
||||
if (isNoisy && highlightEnabled) {
|
||||
return PushNotificationAction::NoisyHighlight;
|
||||
} else if (isNoisy) {
|
||||
return PushNotificationAction::Noisy;
|
||||
} else if (highlightEnabled) {
|
||||
return PushNotificationAction::Highlight;
|
||||
} else {
|
||||
return PushNotificationAction::On;
|
||||
}
|
||||
} else {
|
||||
return PushNotificationAction::Off;
|
||||
}
|
||||
}
|
||||
|
||||
QVector<QVariant> NotificationsManager::toActions(PushNotificationAction::Action action, const QString &sound)
|
||||
{
|
||||
// The caller should never try to set the state to unknown.
|
||||
// It exists only as a default state to diable the settings options until the actual state is retrieved from the server.
|
||||
if (action == PushNotificationAction::Unknown) {
|
||||
Q_ASSERT(false);
|
||||
return QVector<QVariant>();
|
||||
}
|
||||
|
||||
QVector<QVariant> actions;
|
||||
|
||||
if (action != PushNotificationAction::Off) {
|
||||
actions.append("notify");
|
||||
} else {
|
||||
actions.append("dont_notify");
|
||||
}
|
||||
if (action == PushNotificationAction::Noisy || action == PushNotificationAction::NoisyHighlight) {
|
||||
QJsonObject soundTweak;
|
||||
soundTweak.insert("set_tweak", "sound");
|
||||
soundTweak.insert("value", sound);
|
||||
actions.append(soundTweak);
|
||||
}
|
||||
if (action == PushNotificationAction::Highlight || action == PushNotificationAction::NoisyHighlight) {
|
||||
QJsonObject highlightTweak;
|
||||
highlightTweak.insert("set_tweak", "highlight");
|
||||
actions.append(highlightTweak);
|
||||
}
|
||||
|
||||
return actions;
|
||||
}
|
||||
|
||||
@@ -56,93 +56,6 @@ class NotificationsManager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
/**
|
||||
* @brief The global notification state.
|
||||
*
|
||||
* If this rule is set to off all push notifications are disabled regardless
|
||||
* of other settings.
|
||||
*/
|
||||
Q_PROPERTY(bool globalNotificationsEnabled MEMBER m_globalNotificationsEnabled WRITE setGlobalNotificationsEnabled NOTIFY globalNotificationsEnabledChanged)
|
||||
|
||||
/**
|
||||
* @brief Whether the global notification state has been retrieved from the server.
|
||||
*
|
||||
* This is different to the others below as globalNotificationsEnabled is only
|
||||
* a bool rather than a PushNotificationAction::Action so a separate property
|
||||
* is required to track if the state has been retrieved from the server.
|
||||
*
|
||||
* @sa globalNotificationsEnabled, PushNotificationAction::Action
|
||||
*/
|
||||
Q_PROPERTY(bool globalNotificationsSet MEMBER m_globalNotificationsSet NOTIFY globalNotificationsSetChanged)
|
||||
|
||||
/**
|
||||
* @brief The notification action for direct chats.
|
||||
*
|
||||
* @note Encrypted direct chats have a separate setting.
|
||||
*
|
||||
* @sa encryptedOneToOneNotificationAction
|
||||
*/
|
||||
Q_PROPERTY(PushNotificationAction::Action oneToOneNotificationAction MEMBER m_oneToOneNotificationAction WRITE setOneToOneNotificationAction NOTIFY
|
||||
oneToOneNotificationActionChanged)
|
||||
|
||||
/**
|
||||
* @brief The notification action for encrypted direct chats.
|
||||
*/
|
||||
Q_PROPERTY(PushNotificationAction::Action encryptedOneToOneNotificationAction MEMBER m_encryptedOneToOneNotificationAction WRITE
|
||||
setEncryptedOneToOneNotificationAction NOTIFY encryptedOneToOneNotificationActionChanged)
|
||||
|
||||
/**
|
||||
* @brief The notification action for group chats.
|
||||
*
|
||||
* @note Encrypted group chats have a separate setting.
|
||||
*
|
||||
* @sa encryptedGroupChatNotificationAction
|
||||
*/
|
||||
Q_PROPERTY(PushNotificationAction::Action groupChatNotificationAction MEMBER m_groupChatNotificationAction WRITE setGroupChatNotificationAction NOTIFY
|
||||
groupChatNotificationActionChanged)
|
||||
|
||||
/**
|
||||
* @brief The notification action for encrypted group chats.
|
||||
*/
|
||||
Q_PROPERTY(PushNotificationAction::Action encryptedGroupChatNotificationAction MEMBER m_encryptedGroupChatNotificationAction WRITE
|
||||
setEncryptedGroupChatNotificationAction NOTIFY encryptedGroupChatNotificationActionChanged)
|
||||
|
||||
/**
|
||||
* @brief The notification action for events containing the local user's display name.
|
||||
*/
|
||||
Q_PROPERTY(PushNotificationAction::Action displayNameNotificationAction MEMBER m_displayNameNotificationAction WRITE setDisplayNameNotificationAction NOTIFY
|
||||
displayNameNotificationActionChanged)
|
||||
|
||||
/**
|
||||
* @brief The notification action for room events.
|
||||
*/
|
||||
Q_PROPERTY(PushNotificationAction::Action roomNotificationAction MEMBER m_roomNotificationAction WRITE setRoomNotificationAction NOTIFY
|
||||
roomNotificationActionChanged)
|
||||
|
||||
/**
|
||||
* @brief The notification action for keyword push rules.
|
||||
*/
|
||||
Q_PROPERTY(PushNotificationAction::Action keywordNotificationAction MEMBER m_keywordNotificationAction WRITE setKeywordNotificationAction NOTIFY
|
||||
keywordNotificationActionChanged)
|
||||
|
||||
/**
|
||||
* @brief The notification action for invites to chats.
|
||||
*/
|
||||
Q_PROPERTY(PushNotificationAction::Action inviteNotificationAction MEMBER m_inviteNotificationAction WRITE setInviteNotificationAction NOTIFY
|
||||
inviteNotificationActionChanged)
|
||||
|
||||
/**
|
||||
* @brief The notification action for voice calls.
|
||||
*/
|
||||
Q_PROPERTY(PushNotificationAction::Action callInviteNotificationAction MEMBER m_callInviteNotificationAction WRITE setCallInviteNotificationAction NOTIFY
|
||||
callInviteNotificationActionChanged)
|
||||
|
||||
/**
|
||||
* @brief The notification action for room upgrade events.
|
||||
*/
|
||||
Q_PROPERTY(PushNotificationAction::Action tombstoneNotificationAction MEMBER m_tombstoneNotificationAction WRITE setTombstoneNotificationAction NOTIFY
|
||||
tombstoneNotificationActionChanged)
|
||||
|
||||
public:
|
||||
static NotificationsManager &instance();
|
||||
|
||||
@@ -164,30 +77,6 @@ public:
|
||||
*/
|
||||
void clearInvitationNotification(const QString &roomId);
|
||||
|
||||
/**
|
||||
* @brief Set the initial keyword notification action.
|
||||
*
|
||||
* This is only required if no keyword rules exist and one is created. The default
|
||||
* action is PushNotificationAction::Action::Highlight.
|
||||
*
|
||||
* @sa PushNotificationAction::Action
|
||||
*/
|
||||
void initializeKeywordNotificationAction();
|
||||
|
||||
/**
|
||||
* @brief Set the keyword notification action to PushNotificationAction::Action::Off.
|
||||
*
|
||||
* This is only required the last keyword rule is deleted.
|
||||
*
|
||||
* @sa PushNotificationAction::Action
|
||||
*/
|
||||
void deactivateKeywordNotificationAction();
|
||||
|
||||
/**
|
||||
* @brief Return the keyword notification action in a form required for the server push rule.
|
||||
*/
|
||||
QVector<QVariant> getKeywordNotificationActions();
|
||||
|
||||
#ifdef QUOTIENT_07
|
||||
/**
|
||||
* @brief Handle the notifications for the given connection.
|
||||
@@ -208,52 +97,6 @@ private:
|
||||
QHash<QString, KNotification *> m_notifications;
|
||||
QHash<QString, QPointer<KNotification>> m_invitations;
|
||||
|
||||
bool m_globalNotificationsEnabled = false;
|
||||
bool m_globalNotificationsSet = false;
|
||||
PushNotificationAction::Action m_oneToOneNotificationAction = PushNotificationAction::Unknown;
|
||||
PushNotificationAction::Action m_encryptedOneToOneNotificationAction = PushNotificationAction::Unknown;
|
||||
PushNotificationAction::Action m_groupChatNotificationAction = PushNotificationAction::Unknown;
|
||||
PushNotificationAction::Action m_encryptedGroupChatNotificationAction = PushNotificationAction::Unknown;
|
||||
PushNotificationAction::Action m_displayNameNotificationAction = PushNotificationAction::Unknown;
|
||||
PushNotificationAction::Action m_roomNotificationAction = PushNotificationAction::Unknown;
|
||||
PushNotificationAction::Action m_keywordNotificationAction = PushNotificationAction::Unknown;
|
||||
PushNotificationAction::Action m_inviteNotificationAction = PushNotificationAction::Unknown;
|
||||
PushNotificationAction::Action m_callInviteNotificationAction = PushNotificationAction::Unknown;
|
||||
PushNotificationAction::Action m_tombstoneNotificationAction = PushNotificationAction::Unknown;
|
||||
|
||||
void setGlobalNotificationsEnabled(bool enabled);
|
||||
void setOneToOneNotificationAction(PushNotificationAction::Action action);
|
||||
void setEncryptedOneToOneNotificationAction(PushNotificationAction::Action action);
|
||||
void setGroupChatNotificationAction(PushNotificationAction::Action action);
|
||||
void setEncryptedGroupChatNotificationAction(PushNotificationAction::Action action);
|
||||
void setDisplayNameNotificationAction(PushNotificationAction::Action action);
|
||||
void setRoomNotificationAction(PushNotificationAction::Action action);
|
||||
void setKeywordNotificationAction(PushNotificationAction::Action action);
|
||||
void setInviteNotificationAction(PushNotificationAction::Action action);
|
||||
void setCallInviteNotificationAction(PushNotificationAction::Action action);
|
||||
void setTombstoneNotificationAction(PushNotificationAction::Action action);
|
||||
|
||||
void setNotificationRuleEnabled(const QString &kind, const QString &ruleId, bool enabled);
|
||||
void setNotificationRuleActions(const QString &kind, const QString &ruleId, PushNotificationAction::Action action);
|
||||
PushNotificationAction::Action toAction(const QJsonObject &rule);
|
||||
QVector<QVariant> toActions(PushNotificationAction::Action action, const QString &sound = "default");
|
||||
|
||||
private Q_SLOTS:
|
||||
void processNotificationJob(QPointer<Quotient::Connection> connection, Quotient::GetNotificationsJob *job, bool initialization);
|
||||
|
||||
void updateNotificationRules(const QString &type);
|
||||
|
||||
Q_SIGNALS:
|
||||
void globalNotificationsEnabledChanged(bool newState);
|
||||
void globalNotificationsSetChanged(bool newState);
|
||||
void oneToOneNotificationActionChanged(PushNotificationAction::Action action);
|
||||
void encryptedOneToOneNotificationActionChanged(PushNotificationAction::Action action);
|
||||
void groupChatNotificationActionChanged(PushNotificationAction::Action action);
|
||||
void encryptedGroupChatNotificationActionChanged(PushNotificationAction::Action action);
|
||||
void displayNameNotificationActionChanged(PushNotificationAction::Action action);
|
||||
void roomNotificationActionChanged(PushNotificationAction::Action action);
|
||||
void keywordNotificationActionChanged(PushNotificationAction::Action action);
|
||||
void inviteNotificationActionChanged(PushNotificationAction::Action action);
|
||||
void callInviteNotificationActionChanged(PushNotificationAction::Action action);
|
||||
void tombstoneNotificationActionChanged(PushNotificationAction::Action action);
|
||||
};
|
||||
|
||||
@@ -7,10 +7,12 @@ import QtQuick.Layouts 1.15
|
||||
|
||||
import org.kde.kirigami 2.15 as Kirigami
|
||||
import org.kde.kirigamiaddons.labs.mobileform 0.1 as MobileForm
|
||||
import org.kde.kitemmodels 1.0
|
||||
|
||||
import org.kde.neochat 1.0
|
||||
|
||||
Kirigami.ScrollablePage {
|
||||
id: root
|
||||
|
||||
property NeoChatRoom room
|
||||
|
||||
@@ -62,5 +64,86 @@ Kirigami.ScrollablePage {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MobileForm.FormCard {
|
||||
Layout.fillWidth: true
|
||||
|
||||
contentItem: ColumnLayout {
|
||||
spacing: 0
|
||||
|
||||
MobileForm.FormCardHeader {
|
||||
title: i18n("Keywords")
|
||||
}
|
||||
Repeater {
|
||||
model: KSortFilterProxyModel {
|
||||
sourceModel: Controller.pushRuleModel
|
||||
|
||||
filterRowCallback: function(source_row, source_parent) {
|
||||
let sectionRole = sourceModel.data(sourceModel.index(source_row, 0, source_parent), PushRuleModel.SectionRole)
|
||||
let roomIdRole = sourceModel.data(sourceModel.index(source_row, 0, source_parent), PushRuleModel.RoomIdRole)
|
||||
return sectionRole == PushNotificationSection.RoomKeywords && roomIdRole == root.room.id;
|
||||
}
|
||||
}
|
||||
|
||||
delegate: ruleDelegate
|
||||
}
|
||||
MobileForm.AbstractFormDelegate {
|
||||
Layout.fillWidth: true
|
||||
|
||||
contentItem : RowLayout {
|
||||
Kirigami.ActionTextField {
|
||||
id: keywordAddField
|
||||
|
||||
Layout.fillWidth: true
|
||||
|
||||
placeholderText: i18n("Keyword…")
|
||||
enabled: NotificationsManager.keywordNotificationAction !== PushNotificationAction.Unknown
|
||||
|
||||
rightActions: Kirigami.Action {
|
||||
icon.name: "edit-clear"
|
||||
visible: keywordAddField.text.length > 0
|
||||
onTriggered: {
|
||||
keywordAddField.text = ""
|
||||
}
|
||||
}
|
||||
|
||||
onAccepted: {
|
||||
Controller.pushRuleModel.addKeyword(keywordAddField.text, root.room.id)
|
||||
keywordAddField.text = ""
|
||||
}
|
||||
}
|
||||
QQC2.Button {
|
||||
id: addButton
|
||||
|
||||
text: i18n("Add keyword")
|
||||
Accessible.name: text
|
||||
icon.name: "list-add"
|
||||
display: QQC2.AbstractButton.IconOnly
|
||||
enabled: NotificationsManager.keywordNotificationAction !== PushNotificationAction.Unknown
|
||||
|
||||
onClicked: {
|
||||
Controller.pushRuleModel.addKeyword(keywordAddField.text, root.room.id)
|
||||
keywordAddField.text = ""
|
||||
}
|
||||
|
||||
QQC2.ToolTip {
|
||||
text: addButton.text
|
||||
delay: Kirigami.Units.toolTipDelay
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: ruleDelegate
|
||||
NotificationRuleItem {
|
||||
onDeleteRule: {
|
||||
Controller.pushRuleModel.removeKeyword(id)
|
||||
}
|
||||
onActionChanged: (action) => Controller.pushRuleModel.setPushRuleAction(id, action)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,13 +7,17 @@ import QtQuick.Layouts 1.15
|
||||
|
||||
import org.kde.kirigami 2.15 as Kirigami
|
||||
import org.kde.kirigamiaddons.labs.mobileform 0.1 as MobileForm
|
||||
import org.kde.kitemmodels 1.0
|
||||
|
||||
import org.kde.neochat 1.0
|
||||
|
||||
Kirigami.ScrollablePage {
|
||||
id: root
|
||||
|
||||
title: i18nc("@title:window", "Notifications")
|
||||
leftPadding: 0
|
||||
rightPadding: 0
|
||||
|
||||
ColumnLayout {
|
||||
id: notificationLayout
|
||||
|
||||
@@ -22,10 +26,10 @@ Kirigami.ScrollablePage {
|
||||
contentItem: MobileForm.FormCheckDelegate {
|
||||
text: i18n("Enable notifications for this account")
|
||||
description: i18n("Whether push notifications are generated by your Matrix server")
|
||||
checked: NotificationsManager.globalNotificationsEnabled
|
||||
enabled: NotificationsManager.globalNotificationsSet
|
||||
checked: Controller.pushRuleModel.globalNotificationsEnabled
|
||||
enabled: Controller.pushRuleModel.globalNotificationsSet
|
||||
onToggled: {
|
||||
NotificationsManager.globalNotificationsEnabled = checked
|
||||
Controller.pushRuleModel.globalNotificationsEnabled = checked
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -39,81 +43,17 @@ Kirigami.ScrollablePage {
|
||||
MobileForm.FormCardHeader {
|
||||
title: i18n("Room Notifications")
|
||||
}
|
||||
NotificationRuleItem {
|
||||
text: i18n("Messages in one-to-one chats")
|
||||
Repeater {
|
||||
model: KSortFilterProxyModel {
|
||||
sourceModel: Controller.pushRuleModel
|
||||
|
||||
notificationsOn: notificationLayout.isNotificationRuleOn(NotificationsManager.oneToOneNotificationAction)
|
||||
noisyOn: notificationLayout.isNotificationRuleNoisy(NotificationsManager.oneToOneNotificationAction)
|
||||
enabled: NotificationsManager.oneToOneNotificationAction !== PushNotificationAction.Unknown
|
||||
|
||||
notificationAction: NotificationsManager.oneToOneNotificationAction
|
||||
onNotificationActionChanged: {
|
||||
if (notificationAction && NotificationsManager.oneToOneNotificationAction != notificationAction) {
|
||||
NotificationsManager.oneToOneNotificationAction = notificationAction
|
||||
filterRowCallback: function(source_row, source_parent) {
|
||||
let sectionRole = sourceModel.data(sourceModel.index(source_row, 0, source_parent), PushRuleModel.SectionRole)
|
||||
return sectionRole == PushNotificationSection.Room;
|
||||
}
|
||||
}
|
||||
}
|
||||
NotificationRuleItem {
|
||||
text: i18n("Encrypted messages in one-to-one chats")
|
||||
|
||||
visible: Controller.encryptionSupported
|
||||
|
||||
notificationsOn: notificationLayout.isNotificationRuleOn(NotificationsManager.encryptedOneToOneNotificationAction)
|
||||
noisyOn: notificationLayout.isNotificationRuleNoisy(NotificationsManager.encryptedOneToOneNotificationAction)
|
||||
enabled: NotificationsManager.encryptedOneToOneNotificationAction !== PushNotificationAction.Unknown
|
||||
|
||||
notificationAction: NotificationsManager.encryptedOneToOneNotificationAction
|
||||
onNotificationActionChanged: {
|
||||
if (notificationAction && NotificationsManager.encryptedOneToOneNotificationAction != notificationAction) {
|
||||
NotificationsManager.encryptedOneToOneNotificationAction = notificationAction
|
||||
}
|
||||
}
|
||||
}
|
||||
NotificationRuleItem {
|
||||
text: i18n("Messages in group chats")
|
||||
|
||||
notificationsOn: notificationLayout.isNotificationRuleOn(NotificationsManager.groupChatNotificationAction)
|
||||
noisyOn: notificationLayout.isNotificationRuleNoisy(NotificationsManager.groupChatNotificationAction)
|
||||
enabled: NotificationsManager.groupChatNotificationAction !== PushNotificationAction.Unknown
|
||||
|
||||
notificationAction: NotificationsManager.groupChatNotificationAction
|
||||
onNotificationActionChanged: {
|
||||
if (notificationAction && NotificationsManager.groupChatNotificationAction != notificationAction) {
|
||||
NotificationsManager.groupChatNotificationAction = notificationAction
|
||||
}
|
||||
}
|
||||
}
|
||||
NotificationRuleItem {
|
||||
text: i18n("Messages in encrypted group chats")
|
||||
|
||||
visible: Controller.encryptionSupported
|
||||
|
||||
notificationsOn: notificationLayout.isNotificationRuleOn(NotificationsManager.encryptedGroupChatNotificationAction)
|
||||
noisyOn: notificationLayout.isNotificationRuleNoisy(NotificationsManager.encryptedGroupChatNotificationAction)
|
||||
enabled: NotificationsManager.encryptedGroupChatNotificationAction !== PushNotificationAction.Unknown
|
||||
|
||||
notificationAction: NotificationsManager.encryptedGroupChatNotificationAction
|
||||
onNotificationActionChanged: {
|
||||
if (notificationAction && NotificationsManager.encryptedGroupChatNotificationAction != notificationAction) {
|
||||
NotificationsManager.encryptedGroupChatNotificationAction = notificationAction
|
||||
}
|
||||
}
|
||||
}
|
||||
NotificationRuleItem {
|
||||
text: i18n("Room upgrade messages")
|
||||
|
||||
notificationsOn: notificationLayout.isNotificationRuleOn(NotificationsManager.tombstoneNotificationAction)
|
||||
noisyOn: notificationLayout.isNotificationRuleNoisy(NotificationsManager.tombstoneNotificationAction)
|
||||
highlightable: true
|
||||
highlightOn: notificationLayout.isNotificationRuleHighlight(NotificationsManager.tombstoneNotificationAction)
|
||||
enabled: NotificationsManager.tombstoneNotificationAction !== PushNotificationAction.Unknown
|
||||
|
||||
notificationAction: NotificationsManager.tombstoneNotificationAction
|
||||
onNotificationActionChanged: {
|
||||
if (notificationAction && NotificationsManager.tombstoneNotificationAction != notificationAction) {
|
||||
NotificationsManager.tombstoneNotificationAction = notificationAction
|
||||
}
|
||||
}
|
||||
delegate: ruleDelegate
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -127,37 +67,17 @@ Kirigami.ScrollablePage {
|
||||
MobileForm.FormCardHeader {
|
||||
title: i18n("@Mentions")
|
||||
}
|
||||
NotificationRuleItem {
|
||||
text: i18n("Messages containing my display name")
|
||||
Repeater {
|
||||
model: KSortFilterProxyModel {
|
||||
sourceModel: Controller.pushRuleModel
|
||||
|
||||
notificationsOn: notificationLayout.isNotificationRuleOn(NotificationsManager.displayNameNotificationAction)
|
||||
noisyOn: notificationLayout.isNotificationRuleNoisy(NotificationsManager.displayNameNotificationAction)
|
||||
highlightable: true
|
||||
highlightOn: notificationLayout.isNotificationRuleHighlight(NotificationsManager.displayNameNotificationAction)
|
||||
enabled: NotificationsManager.displayNameNotificationAction !== PushNotificationAction.Unknown
|
||||
|
||||
notificationAction: NotificationsManager.displayNameNotificationAction
|
||||
onNotificationActionChanged: {
|
||||
if (notificationAction && NotificationsManager.displayNameNotificationAction != notificationAction) {
|
||||
NotificationsManager.displayNameNotificationAction = notificationAction
|
||||
filterRowCallback: function(source_row, source_parent) {
|
||||
let sectionRole = sourceModel.data(sourceModel.index(source_row, 0, source_parent), PushRuleModel.SectionRole)
|
||||
return sectionRole == PushNotificationSection.Mentions;
|
||||
}
|
||||
}
|
||||
}
|
||||
NotificationRuleItem {
|
||||
text: i18n("Whole room (@room) notifications")
|
||||
|
||||
notificationsOn: notificationLayout.isNotificationRuleOn(NotificationsManager.roomNotificationAction)
|
||||
noisyOn: notificationLayout.isNotificationRuleNoisy(NotificationsManager.roomNotificationAction)
|
||||
highlightable: true
|
||||
highlightOn: notificationLayout.isNotificationRuleHighlight(NotificationsManager.roomNotificationAction)
|
||||
enabled: NotificationsManager.roomNotificationAction !== PushNotificationAction.Unknown
|
||||
|
||||
notificationAction: NotificationsManager.roomNotificationAction
|
||||
onNotificationActionChanged: {
|
||||
if (notificationAction && NotificationsManager.roomNotificationAction != notificationAction) {
|
||||
NotificationsManager.roomNotificationAction = notificationAction
|
||||
}
|
||||
}
|
||||
delegate: ruleDelegate
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -171,47 +91,17 @@ Kirigami.ScrollablePage {
|
||||
MobileForm.FormCardHeader {
|
||||
title: i18n("Keywords")
|
||||
}
|
||||
NotificationRuleItem {
|
||||
id: keywordNotificationAction
|
||||
text: i18n("Messages containing my keywords")
|
||||
|
||||
notificationsOn: true
|
||||
notificationsOnModifiable: false
|
||||
noisyOn: notificationLayout.isNotificationRuleNoisy(NotificationsManager.keywordNotificationAction)
|
||||
highlightable: true
|
||||
highlightOn: notificationLayout.isNotificationRuleHighlight(NotificationsManager.keywordNotificationAction)
|
||||
enabled: NotificationsManager.keywordNotificationAction !== PushNotificationAction.Unknown &&
|
||||
NotificationsManager.keywordNotificationAction !== PushNotificationAction.Off
|
||||
|
||||
notificationAction: NotificationsManager.keywordNotificationAction
|
||||
onNotificationActionChanged: {
|
||||
if (notificationAction && NotificationsManager.keywordNotificationAction != notificationAction) {
|
||||
NotificationsManager.keywordNotificationAction = notificationAction
|
||||
}
|
||||
}
|
||||
}
|
||||
MobileForm.FormDelegateSeparator {}
|
||||
Repeater {
|
||||
model: KeywordNotificationRuleModel {
|
||||
id: keywordNotificationRuleModel
|
||||
}
|
||||
model: KSortFilterProxyModel {
|
||||
sourceModel: Controller.pushRuleModel
|
||||
|
||||
delegate: NotificationRuleItem {
|
||||
text: name
|
||||
notificationAction: keywordNotificationAction.notificationAction
|
||||
notificationsOn: keywordNotificationAction.notificationsOn
|
||||
notificationsOnModifiable: false
|
||||
noisyOn: keywordNotificationAction.noisyOn
|
||||
noisyModifiable: false
|
||||
highlightOn: keywordNotificationAction.highlightOn
|
||||
deletable: true
|
||||
|
||||
onDeleteItemChanged: {
|
||||
if (deleteItem && deletable) {
|
||||
keywordNotificationRuleModel.removeKeywordAtIndex(index)
|
||||
}
|
||||
filterRowCallback: function(source_row, source_parent) {
|
||||
let sectionRole = sourceModel.data(sourceModel.index(source_row, 0, source_parent), PushRuleModel.SectionRole)
|
||||
return sectionRole == PushNotificationSection.Keywords;
|
||||
}
|
||||
}
|
||||
|
||||
delegate: ruleDelegate
|
||||
}
|
||||
MobileForm.AbstractFormDelegate {
|
||||
Layout.fillWidth: true
|
||||
@@ -234,7 +124,7 @@ Kirigami.ScrollablePage {
|
||||
}
|
||||
|
||||
onAccepted: {
|
||||
keywordNotificationRuleModel.addKeyword(keywordAddField.text, PushNotificationAction.On)
|
||||
Controller.pushRuleModel.addKeyword(keywordAddField.text)
|
||||
keywordAddField.text = ""
|
||||
}
|
||||
}
|
||||
@@ -248,7 +138,7 @@ Kirigami.ScrollablePage {
|
||||
enabled: NotificationsManager.keywordNotificationAction !== PushNotificationAction.Unknown
|
||||
|
||||
onClicked: {
|
||||
keywordNotificationRuleModel.addKeyword(keywordAddField.text, PushNotificationAction.On)
|
||||
Controller.pushRuleModel.addKeyword(keywordAddField.text)
|
||||
keywordAddField.text = ""
|
||||
}
|
||||
|
||||
@@ -271,59 +161,29 @@ Kirigami.ScrollablePage {
|
||||
MobileForm.FormCardHeader {
|
||||
title: i18n("Invites")
|
||||
}
|
||||
NotificationRuleItem {
|
||||
text: i18n("Invites to a room")
|
||||
Repeater {
|
||||
model: KSortFilterProxyModel {
|
||||
sourceModel: Controller.pushRuleModel
|
||||
|
||||
notificationsOn: notificationLayout.isNotificationRuleOn(NotificationsManager.inviteNotificationAction)
|
||||
noisyOn: notificationLayout.isNotificationRuleNoisy(NotificationsManager.inviteNotificationAction)
|
||||
highlightable: true
|
||||
highlightOn: notificationLayout.isNotificationRuleHighlight(NotificationsManager.inviteNotificationAction)
|
||||
enabled: NotificationsManager.inviteNotificationAction !== PushNotificationAction.Unknown
|
||||
|
||||
notificationAction: NotificationsManager.inviteNotificationAction
|
||||
onNotificationActionChanged: {
|
||||
if (notificationAction && NotificationsManager.inviteNotificationAction != notificationAction) {
|
||||
NotificationsManager.inviteNotificationAction = notificationAction
|
||||
filterRowCallback: function(source_row, source_parent) {
|
||||
let sectionRole = sourceModel.data(sourceModel.index(source_row, 0, source_parent), PushRuleModel.SectionRole)
|
||||
return sectionRole == PushNotificationSection.Invites;
|
||||
}
|
||||
}
|
||||
}
|
||||
NotificationRuleItem {
|
||||
text: i18n("Call invitation")
|
||||
|
||||
// TODO enable this option when calls are supported
|
||||
visible: false
|
||||
|
||||
notificationsOn: notificationLayout.isNotificationRuleOn(NotificationsManager.callInviteNotificationAction)
|
||||
noisyOn: notificationLayout.isNotificationRuleNoisy(NotificationsManager.callInviteNotificationAction)
|
||||
highlightable: true
|
||||
highlightOn: notificationLayout.isNotificationRuleHighlight(NotificationsManager.callInviteNotificationAction)
|
||||
enabled: NotificationsManager.callInviteNotificationAction !== PushNotificationAction.Unknown
|
||||
|
||||
notificationAction: NotificationsManager.callInviteNotificationAction
|
||||
onNotificationActionChanged: {
|
||||
if (notificationAction && NotificationsManager.callInviteNotificationAction != notificationAction) {
|
||||
NotificationsManager.callInviteNotificationAction = notificationAction
|
||||
}
|
||||
}
|
||||
delegate: ruleDelegate
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function isNotificationRuleOn(action) {
|
||||
return action == PushNotificationAction.On ||
|
||||
action == PushNotificationAction.Noisy ||
|
||||
action == PushNotificationAction.Highlight ||
|
||||
action == PushNotificationAction.NoisyHighlight
|
||||
}
|
||||
|
||||
function isNotificationRuleNoisy(action) {
|
||||
return action == PushNotificationAction.Noisy ||
|
||||
action == PushNotificationAction.NoisyHighlight
|
||||
}
|
||||
|
||||
function isNotificationRuleHighlight(action) {
|
||||
return action == PushNotificationAction.Highlight ||
|
||||
action == PushNotificationAction.NoisyHighlight
|
||||
Component {
|
||||
id: ruleDelegate
|
||||
NotificationRuleItem {
|
||||
onDeleteRule: {
|
||||
Controller.pushRuleModel.removeKeyword(id)
|
||||
}
|
||||
onActionChanged: (action) => Controller.pushRuleModel.setPushRuleAction(id, action)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,19 +11,25 @@ import org.kde.kirigamiaddons.labs.mobileform 0.1 as MobileForm
|
||||
import org.kde.neochat 1.0
|
||||
|
||||
MobileForm.AbstractFormDelegate {
|
||||
id: notificationRuleItem
|
||||
id: root
|
||||
|
||||
property var notificationAction: PushNotificationAction.Unkown
|
||||
property bool notificationsOn: false
|
||||
property bool notificationsOnModifiable: true
|
||||
property bool noisyOn: false
|
||||
property bool noisyModifiable: true
|
||||
property bool highlightOn: false
|
||||
property bool highlightable: false
|
||||
property bool deleteItem: false
|
||||
property bool deletable: false
|
||||
required property string id
|
||||
required property string name
|
||||
required property int ruleAction
|
||||
required property bool highlightable
|
||||
required property bool deletable
|
||||
|
||||
readonly property bool notificationsOn: isNotificationRuleOn(ruleAction)
|
||||
readonly property bool notificationsOnModifiable: !deletable
|
||||
readonly property bool highlightOn: isNotificationRuleHighlight(ruleAction)
|
||||
|
||||
signal actionChanged(int action)
|
||||
signal deleteRule()
|
||||
|
||||
Layout.fillWidth: true
|
||||
enabled: ruleAction !== PushNotificationAction.Unknown
|
||||
|
||||
text: name
|
||||
|
||||
onClicked: {
|
||||
notificationAction = nextNotificationRuleAction(notificationAction)
|
||||
@@ -42,8 +48,8 @@ MobileForm.AbstractFormDelegate {
|
||||
background: Rectangle {
|
||||
visible: notificationsOn
|
||||
Kirigami.Theme.colorSet: Kirigami.Theme.Button
|
||||
color: highlightOn ? Kirigami.Theme.positiveTextColor : Kirigami.Theme.disabledTextColor
|
||||
opacity: highlightOn ? 1 : 0.3
|
||||
color: highlightOn && highlightable ? Kirigami.Theme.positiveTextColor : Kirigami.Theme.disabledTextColor
|
||||
opacity: highlightOn && highlightable ? 1 : 0.3
|
||||
radius: height / 2
|
||||
}
|
||||
}
|
||||
@@ -51,7 +57,7 @@ MobileForm.AbstractFormDelegate {
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
|
||||
text: notificationRuleItem.text
|
||||
text: root.text
|
||||
elide: Text.ElideRight
|
||||
wrapMode: Text.Wrap
|
||||
maximumLineCount: 2
|
||||
@@ -67,13 +73,13 @@ MobileForm.AbstractFormDelegate {
|
||||
icon.name: checked ? "notifications" : "notifications-disabled"
|
||||
display: QQC2.AbstractButton.IconOnly
|
||||
|
||||
visible: notificationRuleItem.notificationsOnModifiable
|
||||
visible: root.notificationsOnModifiable
|
||||
checkable: true
|
||||
checked: notificationRuleItem.notificationsOn
|
||||
enabled: notificationRuleItem.enabled
|
||||
checked: root.notificationsOn
|
||||
enabled: root.enabled
|
||||
down: checked
|
||||
onToggled: {
|
||||
notificationRuleItem.notificationAction = notificationRuleItem.notifcationRuleAction()
|
||||
root.actionChanged(root.notifcationRuleAction())
|
||||
}
|
||||
|
||||
QQC2.ToolTip {
|
||||
@@ -89,13 +95,12 @@ MobileForm.AbstractFormDelegate {
|
||||
icon.name: checked ? "audio-volume-high" : "audio-volume-muted"
|
||||
display: QQC2.AbstractButton.IconOnly
|
||||
|
||||
visible: notificationRuleItem.noisyModifiable
|
||||
checkable: true
|
||||
checked: notificationRuleItem.noisyOn
|
||||
enabled: (onButton.checked || !notificationRuleItem.notificationsOnModifiable) && notificationRuleItem.enabled
|
||||
checked: isNotificationRuleNoisy(root.ruleAction)
|
||||
enabled: (onButton.checked || !root.notificationsOnModifiable) && root.enabled
|
||||
down: checked
|
||||
onToggled: {
|
||||
notificationRuleItem.notificationAction = notificationRuleItem.notifcationRuleAction()
|
||||
root.actionChanged(root.notifcationRuleAction())
|
||||
}
|
||||
|
||||
QQC2.ToolTip {
|
||||
@@ -111,13 +116,13 @@ MobileForm.AbstractFormDelegate {
|
||||
icon.name: "draw-highlight"
|
||||
display: QQC2.AbstractButton.IconOnly
|
||||
|
||||
visible: notificationRuleItem.highlightable
|
||||
visible: root.highlightable
|
||||
checkable: true
|
||||
checked: notificationRuleItem.highlightOn
|
||||
enabled: (onButton.checked || !notificationRuleItem.notificationsOnModifiable) && notificationRuleItem.enabled
|
||||
checked: root.highlightOn
|
||||
enabled: (onButton.checked || !root.notificationsOnModifiable) && root.enabled
|
||||
down: checked
|
||||
onToggled: {
|
||||
notificationRuleItem.notificationAction = notificationRuleItem.notifcationRuleAction()
|
||||
root.actionChanged(root.notifcationRuleAction())
|
||||
}
|
||||
|
||||
QQC2.ToolTip {
|
||||
@@ -131,10 +136,10 @@ MobileForm.AbstractFormDelegate {
|
||||
Accessible.name: i18n("Delete keyword")
|
||||
icon.name: "edit-delete-remove"
|
||||
|
||||
visible: notificationRuleItem.deletable
|
||||
visible: root.deletable
|
||||
|
||||
onClicked: {
|
||||
notificationRuleItem.deleteItem = !notificationRuleItem.deleteItem
|
||||
root.deleteRule()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -142,11 +147,11 @@ MobileForm.AbstractFormDelegate {
|
||||
|
||||
function notifcationRuleAction() {
|
||||
if (onButton.checked) {
|
||||
if (noisyButton.checked && highlightButton.checked) {
|
||||
if (noisyButton.checked && highlightButton.checked && root.highlightable) {
|
||||
return PushNotificationAction.NoisyHighlight
|
||||
} else if (noisyButton.checked) {
|
||||
return PushNotificationAction.Noisy
|
||||
} else if (highlightButton.checked) {
|
||||
} else if (highlightButton.checked && root.highlightable) {
|
||||
return PushNotificationAction.Highlight
|
||||
} else {
|
||||
return PushNotificationAction.On
|
||||
@@ -166,17 +171,34 @@ MobileForm.AbstractFormDelegate {
|
||||
}
|
||||
|
||||
while (!finished) {
|
||||
if (action == PushNotificationAction.Off && !notificationRuleItem.notificationsOnModifiable) {
|
||||
if (action == PushNotificationAction.Off && !root.notificationsOnModifiable) {
|
||||
action = PushNotificationAction.On
|
||||
} else if (action == PushNotificationAction.Noisy && !notificationRuleItem.noisyModifiable) {
|
||||
} else if (action == PushNotificationAction.Noisy) {
|
||||
action = PushNotificationAction.Highlight
|
||||
} else if (action == PushNotificationAction.Highlight && !notificationRuleItem.highlightable) {
|
||||
} else if (action == PushNotificationAction.Highlight && !root.highlightable) {
|
||||
action = PushNotificationAction.Off
|
||||
} else {
|
||||
finished = true
|
||||
}
|
||||
}
|
||||
|
||||
return action
|
||||
actionChanged(action)
|
||||
}
|
||||
|
||||
function isNotificationRuleOn(action) {
|
||||
return action == PushNotificationAction.On ||
|
||||
action == PushNotificationAction.Noisy ||
|
||||
action == PushNotificationAction.Highlight ||
|
||||
action == PushNotificationAction.NoisyHighlight
|
||||
}
|
||||
|
||||
function isNotificationRuleNoisy(action) {
|
||||
return action == PushNotificationAction.Noisy ||
|
||||
action == PushNotificationAction.NoisyHighlight
|
||||
}
|
||||
|
||||
function isNotificationRuleHighlight(action) {
|
||||
return action == PushNotificationAction.Highlight ||
|
||||
action == PushNotificationAction.NoisyHighlight
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user