Move all the enums for push rules into their own header file

This commit is contained in:
James Graham
2023-12-31 19:49:19 +00:00
parent 7e9f206348
commit 612b5d7f47
9 changed files with 294 additions and 263 deletions

View File

@@ -143,6 +143,7 @@ add_library(neochat STATIC
models/notificationsmodel.h models/notificationsmodel.h
models/timelinemodel.cpp models/timelinemodel.cpp
models/timelinemodel.h models/timelinemodel.h
enums/pushrule.h
) )
qt_add_qml_module(neochat URI org.kde.neochat NO_PLUGIN qt_add_qml_module(neochat URI org.kde.neochat NO_PLUGIN

186
src/enums/pushrule.h Normal file
View File

@@ -0,0 +1,186 @@
// SPDX-FileCopyrightText: 2023 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 <QObject>
#include <QQmlEngine>
/**
* @class PushRuleKind
*
* A class with the Kind enum for push notifications and helper functions.
*
* The kind relates to the kinds of push rule defined in the matrix spec, see
* https://spec.matrix.org/v1.7/client-server-api/#push-rules for full details.
*/
class PushRuleKind : public QObject
{
Q_OBJECT
QML_ELEMENT
QML_UNCREATABLE("")
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 PushRuleAction
*
* A class with the Action enum for push notifications.
*
* The action relates to the actions of push rule defined in the matrix spec, see
* https://spec.matrix.org/v1.7/client-server-api/#push-rules for full details.
*/
class PushRuleAction : public QObject
{
Q_OBJECT
QML_ELEMENT
QML_UNCREATABLE("")
public:
/**
* @brief Defines the global push notification actions.
*/
enum Action {
Unknown = 0, /**< The action has not yet been obtained from the server. */
Off, /**< No push notifications are to be sent. */
On, /**< Push notifications are on. */
Noisy, /**< Push notifications are on, also trigger a notification sound. */
Highlight, /**< Push notifications are on, also the event should be highlighted in chat. */
NoisyHighlight, /**< Push notifications are on, also trigger a notification sound and highlight in chat. */
};
Q_ENUM(Action)
};
/**
* @class PushNotificationState
*
* A class with the State enum for room push notification state.
*
* The state define whether the room adheres to the global push rule states for the
* account or is overridden for a room.
*
* @note This is different to the PushRuleAction which defines the type of notification
* for an individual rule.
*
* @sa PushRuleAction
*/
class PushNotificationState : public QObject
{
Q_OBJECT
QML_ELEMENT
QML_UNCREATABLE("")
public:
/**
* @brief Describes the push notification state for the room.
*/
enum State {
Unknown, /**< The state has not yet been obtained from the server. */
Default, /**< The room follows the globally configured rules for the local user. */
Mute, /**< No notifications for messages in the room. */
MentionKeyword, /**< Notifications only for local user mentions and keywords. */
All, /**< Notifications for all messages. */
};
Q_ENUM(State)
};
/**
* @class PushRuleSection
*
* A class with the Section enum for push notifications and helper functions.
*
* @note This is different from the PushRuleKind and instead is used for sorting
* in the settings page which is not necessarily by Kind.
*
* @sa PushRuleKind
*/
class PushRuleSection : public QObject
{
Q_OBJECT
QML_ELEMENT
QML_UNCREATABLE("")
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. */
Unknown, /**< New default push rules that have not been added to the model yet. */
/**
* @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.
*
* This is specifically different to unknown which are just new default push
* rule that haven't been added to the model yet.
*/
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 {};
}
};
};

View File

@@ -34,25 +34,25 @@ static const QHash<QString, KLazyLocalizedString> defaultRuleNames = {
}; };
// Sections for default rules. // Sections for default rules.
static const QHash<QString, PushNotificationSection::Section> defaultSections = { static const QHash<QString, PushRuleSection::Section> defaultSections = {
{QStringLiteral(".m.rule.master"), PushNotificationSection::Master}, {QStringLiteral(".m.rule.master"), PushRuleSection::Master},
{QStringLiteral(".m.rule.room_one_to_one"), PushNotificationSection::Room}, {QStringLiteral(".m.rule.room_one_to_one"), PushRuleSection::Room},
{QStringLiteral(".m.rule.encrypted_room_one_to_one"), PushNotificationSection::Room}, {QStringLiteral(".m.rule.encrypted_room_one_to_one"), PushRuleSection::Room},
{QStringLiteral(".m.rule.message"), PushNotificationSection::Room}, {QStringLiteral(".m.rule.message"), PushRuleSection::Room},
{QStringLiteral(".m.rule.encrypted"), PushNotificationSection::Room}, {QStringLiteral(".m.rule.encrypted"), PushRuleSection::Room},
{QStringLiteral(".m.rule.tombstone"), PushNotificationSection::Room}, {QStringLiteral(".m.rule.tombstone"), PushRuleSection::Room},
{QStringLiteral(".m.rule.contains_display_name"), PushNotificationSection::Mentions}, {QStringLiteral(".m.rule.contains_display_name"), PushRuleSection::Mentions},
{QStringLiteral(".m.rule.is_user_mention"), PushNotificationSection::Mentions}, {QStringLiteral(".m.rule.is_user_mention"), PushRuleSection::Mentions},
{QStringLiteral(".m.rule.is_room_mention"), PushNotificationSection::Mentions}, {QStringLiteral(".m.rule.is_room_mention"), PushRuleSection::Mentions},
{QStringLiteral(".m.rule.contains_user_name"), PushNotificationSection::Mentions}, {QStringLiteral(".m.rule.contains_user_name"), PushRuleSection::Mentions},
{QStringLiteral(".m.rule.roomnotif"), PushNotificationSection::Mentions}, {QStringLiteral(".m.rule.roomnotif"), PushRuleSection::Mentions},
{QStringLiteral(".m.rule.invite_for_me"), PushNotificationSection::Invites}, {QStringLiteral(".m.rule.invite_for_me"), PushRuleSection::Invites},
{QStringLiteral(".m.rule.call"), PushNotificationSection::Undefined}, // TODO: make invites when VOIP added. {QStringLiteral(".m.rule.call"), PushRuleSection::Undefined}, // TODO: make invites when VOIP added.
{QStringLiteral(".m.rule.suppress_notices"), PushNotificationSection::Undefined}, {QStringLiteral(".m.rule.suppress_notices"), PushRuleSection::Undefined},
{QStringLiteral(".m.rule.member_event"), PushNotificationSection::Undefined}, {QStringLiteral(".m.rule.member_event"), PushRuleSection::Undefined},
{QStringLiteral(".m.rule.reaction"), PushNotificationSection::Undefined}, {QStringLiteral(".m.rule.reaction"), PushRuleSection::Undefined},
{QStringLiteral(".m.rule.room.server_acl"), PushNotificationSection::Undefined}, {QStringLiteral(".m.rule.room.server_acl"), PushRuleSection::Undefined},
{QStringLiteral(".im.vector.jitsi"), PushNotificationSection::Undefined}, {QStringLiteral(".im.vector.jitsi"), PushRuleSection::Undefined},
}; };
// Default rules that don't have a highlight option as it would lead to all messages // Default rules that don't have a highlight option as it would lead to all messages
@@ -67,7 +67,7 @@ static const QStringList noHighlight = {
PushRuleModel::PushRuleModel(QObject *parent) PushRuleModel::PushRuleModel(QObject *parent)
: QAbstractListModel(parent) : QAbstractListModel(parent)
{ {
m_defaultKeywordAction = static_cast<PushNotificationAction::Action>(NeoChatConfig::self()->keywordPushRuleDefault()); m_defaultKeywordAction = static_cast<PushRuleAction::Action>(NeoChatConfig::self()->keywordPushRuleDefault());
} }
void PushRuleModel::updateNotificationRules(const QString &type) void PushRuleModel::updateNotificationRules(const QString &type)
@@ -83,11 +83,11 @@ void PushRuleModel::updateNotificationRules(const QString &type)
m_rules.clear(); m_rules.clear();
// Doing this 5 times because PushRuleset is a struct. // Doing this 5 times because PushRuleset is a struct.
setRules(ruleData.override, PushNotificationKind::Override); setRules(ruleData.override, PushRuleKind::Override);
setRules(ruleData.content, PushNotificationKind::Content); setRules(ruleData.content, PushRuleKind::Content);
setRules(ruleData.room, PushNotificationKind::Room); setRules(ruleData.room, PushRuleKind::Room);
setRules(ruleData.sender, PushNotificationKind::Sender); setRules(ruleData.sender, PushRuleKind::Sender);
setRules(ruleData.underride, PushNotificationKind::Underride); setRules(ruleData.underride, PushRuleKind::Underride);
Q_EMIT globalNotificationsEnabledChanged(); Q_EMIT globalNotificationsEnabledChanged();
Q_EMIT globalNotificationsSetChanged(); Q_EMIT globalNotificationsSetChanged();
@@ -95,7 +95,7 @@ void PushRuleModel::updateNotificationRules(const QString &type)
endResetModel(); endResetModel();
} }
void PushRuleModel::setRules(QList<Quotient::PushRule> rules, PushNotificationKind::Kind kind) void PushRuleModel::setRules(QList<Quotient::PushRule> rules, PushRuleKind::Kind kind)
{ {
for (const auto &rule : rules) { for (const auto &rule : rules) {
QString roomId; QString roomId;
@@ -128,7 +128,7 @@ int PushRuleModel::getRuleIndex(const QString &ruleId) const
return -1; return -1;
} }
PushNotificationSection::Section PushRuleModel::getSection(Quotient::PushRule rule) PushRuleSection::Section PushRuleModel::getSection(Quotient::PushRule rule)
{ {
auto ruleId = rule.ruleId; auto ruleId = rule.ruleId;
@@ -136,7 +136,7 @@ PushNotificationSection::Section PushRuleModel::getSection(Quotient::PushRule ru
return defaultSections.value(ruleId); return defaultSections.value(ruleId);
} else { } else {
if (rule.ruleId.startsWith(u'.')) { if (rule.ruleId.startsWith(u'.')) {
return PushNotificationSection::Unknown; return PushRuleSection::Unknown;
} }
/** /**
* If the rule name resolves to a matrix id for a room that the user is part * If the rule name resolves to a matrix id for a room that the user is part
@@ -146,7 +146,7 @@ PushNotificationSection::Section PushRuleModel::getSection(Quotient::PushRule ru
* Rooms that the user hasn't joined shouldn't have a rule. * Rooms that the user hasn't joined shouldn't have a rule.
*/ */
if (m_connection->room(ruleId) != nullptr) { if (m_connection->room(ruleId) != nullptr) {
return PushNotificationSection::Undefined; return PushRuleSection::Undefined;
} }
/** /**
* If the rule name resolves to a matrix id for a user it shouldn't appear * If the rule name resolves to a matrix id for a user it shouldn't appear
@@ -160,26 +160,26 @@ PushNotificationSection::Section PushRuleModel::getSection(Quotient::PushRule ru
testUserId.prepend(u'@'); testUserId.prepend(u'@');
} }
if (testUserId.startsWith(u'@') && !Quotient::serverPart(testUserId).isEmpty() && m_connection->user(testUserId) != nullptr) { if (testUserId.startsWith(u'@') && !Quotient::serverPart(testUserId).isEmpty() && m_connection->user(testUserId) != nullptr) {
return PushNotificationSection::Undefined; return PushRuleSection::Undefined;
} }
// If the rule has push conditions and one is a room ID it is a room only keyword. // If the rule has push conditions and one is a room ID it is a room only keyword.
if (!rule.conditions.isEmpty()) { if (!rule.conditions.isEmpty()) {
for (auto condition : rule.conditions) { for (auto condition : rule.conditions) {
if (condition.key == QStringLiteral("room_id")) { if (condition.key == QStringLiteral("room_id")) {
return PushNotificationSection::RoomKeywords; return PushRuleSection::RoomKeywords;
} }
} }
} }
return PushNotificationSection::Keywords; return PushRuleSection::Keywords;
} }
} }
PushNotificationAction::Action PushRuleModel::defaultState() const PushRuleAction::Action PushRuleModel::defaultState() const
{ {
return m_defaultKeywordAction; return m_defaultKeywordAction;
} }
void PushRuleModel::setDefaultState(PushNotificationAction::Action defaultState) void PushRuleModel::setDefaultState(PushRuleAction::Action defaultState)
{ {
if (defaultState == m_defaultKeywordAction) { if (defaultState == m_defaultKeywordAction) {
return; return;
@@ -273,7 +273,7 @@ QHash<int, QByteArray> PushRuleModel::roleNames() const
return roles; return roles;
} }
void PushRuleModel::setPushRuleAction(const QString &id, PushNotificationAction::Action action) void PushRuleModel::setPushRuleAction(const QString &id, PushRuleAction::Action action)
{ {
int index = getRuleIndex(id); int index = getRuleIndex(id);
if (index == -1) { if (index == -1) {
@@ -283,22 +283,22 @@ void PushRuleModel::setPushRuleAction(const QString &id, PushNotificationAction:
auto rule = m_rules[index]; auto rule = m_rules[index];
// Override rules need to be disabled when off so that other rules can match the message if they apply. // 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) { if (action == PushRuleAction::Off && rule.kind == PushRuleKind::Override) {
setNotificationRuleEnabled(PushNotificationKind::kindString(rule.kind), rule.id, false); setNotificationRuleEnabled(PushRuleKind::kindString(rule.kind), rule.id, false);
} else if (rule.kind == PushNotificationKind::Override) { } else if (rule.kind == PushRuleKind::Override) {
setNotificationRuleEnabled(PushNotificationKind::kindString(rule.kind), rule.id, true); setNotificationRuleEnabled(PushRuleKind::kindString(rule.kind), rule.id, true);
} }
setNotificationRuleActions(PushNotificationKind::kindString(rule.kind), rule.id, action); setNotificationRuleActions(PushRuleKind::kindString(rule.kind), rule.id, action);
} }
void PushRuleModel::addKeyword(const QString &keyword, const QString &roomId) void PushRuleModel::addKeyword(const QString &keyword, const QString &roomId)
{ {
PushNotificationKind::Kind kind = PushNotificationKind::Content; PushRuleKind::Kind kind = PushRuleKind::Content;
const QList<QVariant> actions = actionToVariant(m_defaultKeywordAction); const QList<QVariant> actions = actionToVariant(m_defaultKeywordAction);
QList<Quotient::PushCondition> pushConditions; QList<Quotient::PushCondition> pushConditions;
if (!roomId.isEmpty()) { if (!roomId.isEmpty()) {
kind = PushNotificationKind::Override; kind = PushRuleKind::Override;
Quotient::PushCondition roomCondition; Quotient::PushCondition roomCondition;
roomCondition.kind = QStringLiteral("event_match"); roomCondition.kind = QStringLiteral("event_match");
@@ -314,7 +314,7 @@ void PushRuleModel::addKeyword(const QString &keyword, const QString &roomId)
} }
auto job = m_connection->callApi<Quotient::SetPushRuleJob>(QLatin1String("global"), auto job = m_connection->callApi<Quotient::SetPushRuleJob>(QLatin1String("global"),
PushNotificationKind::kindString(kind), PushRuleKind::kindString(kind),
keyword, keyword,
actions, actions,
QString(), QString(),
@@ -338,7 +338,7 @@ void PushRuleModel::removeKeyword(const QString &keyword)
return; return;
} }
auto kind = PushNotificationKind::kindString(m_rules[index].kind); auto kind = PushRuleKind::kindString(m_rules[index].kind);
auto job = m_connection->callApi<Quotient::DeletePushRuleJob>(QStringLiteral("global"), kind, m_rules[index].id); auto job = m_connection->callApi<Quotient::DeletePushRuleJob>(QStringLiteral("global"), kind, m_rules[index].id);
connect(job, &Quotient::BaseJob::failure, this, [this, job, index]() { 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(); qWarning() << QLatin1String("Unable to remove push rule for keyword %1: ").arg(m_rules[index].id) << job->errorString();
@@ -355,7 +355,7 @@ void PushRuleModel::setNotificationRuleEnabled(const QString &kind, const QStrin
}); });
} }
void PushRuleModel::setNotificationRuleActions(const QString &kind, const QString &ruleId, PushNotificationAction::Action action) void PushRuleModel::setNotificationRuleActions(const QString &kind, const QString &ruleId, PushRuleAction::Action action)
{ {
QList<QVariant> actions; QList<QVariant> actions;
if (ruleId == QStringLiteral(".m.rule.call")) { if (ruleId == QStringLiteral(".m.rule.call")) {
@@ -367,7 +367,7 @@ void PushRuleModel::setNotificationRuleActions(const QString &kind, const QStrin
m_connection->callApi<Quotient::SetPushRuleActionsJob>(QStringLiteral("global"), kind, ruleId, actions); m_connection->callApi<Quotient::SetPushRuleActionsJob>(QStringLiteral("global"), kind, ruleId, actions);
} }
PushNotificationAction::Action PushRuleModel::variantToAction(const QList<QVariant> &actions, bool enabled) PushRuleAction::Action PushRuleModel::variantToAction(const QList<QVariant> &actions, bool enabled)
{ {
bool notify = false; bool notify = false;
bool isNoisy = false; bool isNoisy = false;
@@ -392,47 +392,47 @@ PushNotificationAction::Action PushRuleModel::variantToAction(const QList<QVaria
} }
if (!enabled) { if (!enabled) {
return PushNotificationAction::Off; return PushRuleAction::Off;
} }
if (notify) { if (notify) {
if (isNoisy && highlightEnabled) { if (isNoisy && highlightEnabled) {
return PushNotificationAction::NoisyHighlight; return PushRuleAction::NoisyHighlight;
} else if (isNoisy) { } else if (isNoisy) {
return PushNotificationAction::Noisy; return PushRuleAction::Noisy;
} else if (highlightEnabled) { } else if (highlightEnabled) {
return PushNotificationAction::Highlight; return PushRuleAction::Highlight;
} else { } else {
return PushNotificationAction::On; return PushRuleAction::On;
} }
} else { } else {
return PushNotificationAction::Off; return PushRuleAction::Off;
} }
} }
QList<QVariant> PushRuleModel::actionToVariant(PushNotificationAction::Action action, const QString &sound) QList<QVariant> PushRuleModel::actionToVariant(PushRuleAction::Action action, const QString &sound)
{ {
// The caller should never try to set the state to unknown. // 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. // 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) { if (action == PushRuleAction::Unknown) {
Q_ASSERT(false); Q_ASSERT(false);
return QList<QVariant>(); return QList<QVariant>();
} }
QList<QVariant> actions; QList<QVariant> actions;
if (action != PushNotificationAction::Off) { if (action != PushRuleAction::Off) {
actions.append(QStringLiteral("notify")); actions.append(QStringLiteral("notify"));
} else { } else {
actions.append(QStringLiteral("dont_notify")); actions.append(QStringLiteral("dont_notify"));
} }
if (action == PushNotificationAction::Noisy || action == PushNotificationAction::NoisyHighlight) { if (action == PushRuleAction::Noisy || action == PushRuleAction::NoisyHighlight) {
QJsonObject soundTweak; QJsonObject soundTweak;
soundTweak.insert(QStringLiteral("set_tweak"), QStringLiteral("sound")); soundTweak.insert(QStringLiteral("set_tweak"), QStringLiteral("sound"));
soundTweak.insert(QStringLiteral("value"), sound); soundTweak.insert(QStringLiteral("value"), sound);
actions.append(soundTweak); actions.append(soundTweak);
} }
if (action == PushNotificationAction::Highlight || action == PushNotificationAction::NoisyHighlight) { if (action == PushRuleAction::Highlight || action == PushRuleAction::NoisyHighlight) {
QJsonObject highlightTweak; QJsonObject highlightTweak;
highlightTweak.insert(QStringLiteral("set_tweak"), QStringLiteral("highlight")); highlightTweak.insert(QStringLiteral("set_tweak"), QStringLiteral("highlight"));
actions.append(highlightTweak); actions.append(highlightTweak);

View File

@@ -8,124 +8,8 @@
#include <Quotient/csapi/definitions/push_rule.h> #include <Quotient/csapi/definitions/push_rule.h>
#include "notificationsmanager.h" #include "enums/pushrule.h"
#include "neochatconnection.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
QML_ELEMENT
QML_UNCREATABLE("")
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
QML_ELEMENT
QML_UNCREATABLE("")
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. */
Unknown, /**< New default push rules that have not been added to the model yet. */
/**
* @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.
*
* This is specifically different to unknown which are just new default push
* rule that haven't been added to the model yet.
*/
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 * @class PushRuleModel
@@ -140,7 +24,7 @@ class PushRuleModel : public QAbstractListModel
/** /**
* @brief The default state for any newly created keyword rule. * @brief The default state for any newly created keyword rule.
*/ */
Q_PROPERTY(PushNotificationAction::Action defaultState READ defaultState WRITE setDefaultState NOTIFY defaultStateChanged) Q_PROPERTY(PushRuleAction::Action defaultState READ defaultState WRITE setDefaultState NOTIFY defaultStateChanged)
/** /**
* @brief The global notification state. * @brief The global notification state.
@@ -153,7 +37,7 @@ class PushRuleModel : public QAbstractListModel
/** /**
* @brief Whether the global notification state has been retrieved from the server. * @brief Whether the global notification state has been retrieved from the server.
* *
* @sa globalNotificationsEnabled, PushNotificationAction::Action * @sa globalNotificationsEnabled, PushRuleAction::Action
*/ */
Q_PROPERTY(bool globalNotificationsSet READ globalNotificationsSet NOTIFY globalNotificationsSetChanged) Q_PROPERTY(bool globalNotificationsSet READ globalNotificationsSet NOTIFY globalNotificationsSetChanged)
@@ -162,9 +46,9 @@ class PushRuleModel : public QAbstractListModel
public: public:
struct Rule { struct Rule {
QString id; QString id;
PushNotificationKind::Kind kind; PushRuleKind::Kind kind;
PushNotificationAction::Action action; PushRuleAction::Action action;
PushNotificationSection::Section section; PushRuleSection::Section section;
bool enabled; bool enabled;
QString roomId; QString roomId;
}; };
@@ -176,7 +60,7 @@ public:
NameRole = Qt::DisplayRole, /**< The push rule name. */ NameRole = Qt::DisplayRole, /**< The push rule name. */
IdRole, /**< The push rule ID. */ IdRole, /**< The push rule ID. */
KindRole, /**< The kind of notification rule; override, content, etc. */ KindRole, /**< The kind of notification rule; override, content, etc. */
ActionRole, /**< The PushNotificationAction for the rule. */ ActionRole, /**< The PushRuleAction for the rule. */
HighlightableRole, /**< Whether the rule can have a highlight action. */ HighlightableRole, /**< Whether the rule can have a highlight action. */
DeletableRole, /**< Whether the rule can be deleted the rule. */ DeletableRole, /**< Whether the rule can be deleted the rule. */
SectionRole, /**< The section to sort into in the settings page. */ SectionRole, /**< The section to sort into in the settings page. */
@@ -186,8 +70,8 @@ public:
explicit PushRuleModel(QObject *parent = nullptr); explicit PushRuleModel(QObject *parent = nullptr);
[[nodiscard]] PushNotificationAction::Action defaultState() const; [[nodiscard]] PushRuleAction::Action defaultState() const;
void setDefaultState(PushNotificationAction::Action defaultState); void setDefaultState(PushRuleAction::Action defaultState);
[[nodiscard]] bool globalNotificationsEnabled() const; [[nodiscard]] bool globalNotificationsEnabled() const;
void setGlobalNotificationsEnabled(bool enabled); void setGlobalNotificationsEnabled(bool enabled);
@@ -215,7 +99,7 @@ public:
*/ */
[[nodiscard]] QHash<int, QByteArray> roleNames() const override; [[nodiscard]] QHash<int, QByteArray> roleNames() const override;
Q_INVOKABLE void setPushRuleAction(const QString &id, PushNotificationAction::Action action); Q_INVOKABLE void setPushRuleAction(const QString &id, PushRuleAction::Action action);
/** /**
* @brief Add a new keyword to the model. * @brief Add a new keyword to the model.
@@ -240,18 +124,18 @@ private Q_SLOTS:
void updateNotificationRules(const QString &type); void updateNotificationRules(const QString &type);
private: private:
PushNotificationAction::Action m_defaultKeywordAction; PushRuleAction::Action m_defaultKeywordAction;
QList<Rule> m_rules; QList<Rule> m_rules;
NeoChatConnection *m_connection; NeoChatConnection *m_connection;
void setRules(QList<Quotient::PushRule> rules, PushNotificationKind::Kind kind); void setRules(QList<Quotient::PushRule> rules, PushRuleKind::Kind kind);
int getRuleIndex(const QString &ruleId) const; int getRuleIndex(const QString &ruleId) const;
PushNotificationSection::Section getSection(Quotient::PushRule rule); PushRuleSection::Section getSection(Quotient::PushRule rule);
void setNotificationRuleEnabled(const QString &kind, const QString &ruleId, bool enabled); void setNotificationRuleEnabled(const QString &kind, const QString &ruleId, bool enabled);
void setNotificationRuleActions(const QString &kind, const QString &ruleId, PushNotificationAction::Action action); void setNotificationRuleActions(const QString &kind, const QString &ruleId, PushRuleAction::Action action);
PushNotificationAction::Action variantToAction(const QList<QVariant> &actions, bool enabled); PushRuleAction::Action variantToAction(const QList<QVariant> &actions, bool enabled);
QList<QVariant> actionToVariant(PushNotificationAction::Action action, const QString &sound = QStringLiteral("default")); QList<QVariant> actionToVariant(PushRuleAction::Action action, const QString &sound = QStringLiteral("default"));
}; };
Q_DECLARE_METATYPE(PushRuleModel *) Q_DECLARE_METATYPE(PushRuleModel *)

View File

@@ -13,6 +13,7 @@
#include <QCoroTask> #include <QCoroTask>
#include <Quotient/user.h> #include <Quotient/user.h>
#include "enums/pushrule.h"
#include "pollhandler.h" #include "pollhandler.h"
namespace Quotient namespace Quotient
@@ -22,26 +23,6 @@ class User;
class ChatBarCache; class ChatBarCache;
class PushNotificationState : public QObject
{
Q_OBJECT
QML_ELEMENT
QML_UNCREATABLE("")
public:
/**
* @brief Describes the push notification state for the room.
*/
enum State {
Unknown, /**< The state has not yet been obtained from the server. */
Default, /**< The room follows the globally configured rules for the local user. */
Mute, /**< No notifications for messages in the room. */
MentionKeyword, /**< Notifications only for local user mentions and keywords. */
All, /**< Notifications for all messages. */
};
Q_ENUM(State)
};
/** /**
* @class NeoChatRoom * @class NeoChatRoom
* *

View File

@@ -17,27 +17,6 @@ class NeoChatConnection;
class KNotification; class KNotification;
class NeoChatRoom; class NeoChatRoom;
class PushNotificationAction : public QObject
{
Q_OBJECT
QML_ELEMENT
QML_UNCREATABLE("")
public:
/**
* @brief Defines the global push notification actions.
*/
enum Action {
Unknown = 0, /**< The action has not yet been obtained from the server. */
Off, /**< No push notifications are to be sent. */
On, /**< Push notifications are on. */
Noisy, /**< Push notifications are on, also trigger a notification sound. */
Highlight, /**< Push notifications are on, also the event should be highlighted in chat. */
NoisyHighlight, /**< Push notifications are on, also trigger a notification sound and highlight in chat. */
};
Q_ENUM(Action)
};
/** /**
* @class NotificationsManager * @class NotificationsManager
* *

View File

@@ -44,7 +44,7 @@ FormCard.FormCardPage {
sourceModel: root.pushRuleModel sourceModel: root.pushRuleModel
filterRowCallback: function(source_row, source_parent) { filterRowCallback: function(source_row, source_parent) {
let sectionRole = sourceModel.data(sourceModel.index(source_row, 0, source_parent), PushRuleModel.SectionRole) let sectionRole = sourceModel.data(sourceModel.index(source_row, 0, source_parent), PushRuleModel.SectionRole)
return sectionRole == PushNotificationSection.Room; return sectionRole == PushRuleSection.Room;
} }
} }
@@ -61,7 +61,7 @@ FormCard.FormCardPage {
sourceModel: root.pushRuleModel sourceModel: root.pushRuleModel
filterRowCallback: function(source_row, source_parent) { filterRowCallback: function(source_row, source_parent) {
let sectionRole = sourceModel.data(sourceModel.index(source_row, 0, source_parent), PushRuleModel.SectionRole) let sectionRole = sourceModel.data(sourceModel.index(source_row, 0, source_parent), PushRuleModel.SectionRole)
return sectionRole == PushNotificationSection.Mentions; return sectionRole == PushRuleSection.Mentions;
} }
} }
@@ -79,7 +79,7 @@ FormCard.FormCardPage {
filterRowCallback: function(source_row, source_parent) { filterRowCallback: function(source_row, source_parent) {
let sectionRole = sourceModel.data(sourceModel.index(source_row, 0, source_parent), PushRuleModel.SectionRole) let sectionRole = sourceModel.data(sourceModel.index(source_row, 0, source_parent), PushRuleModel.SectionRole)
return sectionRole == PushNotificationSection.Keywords; return sectionRole == PushRuleSection.Keywords;
} }
} }
@@ -95,7 +95,7 @@ FormCard.FormCardPage {
Layout.fillWidth: true Layout.fillWidth: true
placeholderText: i18n("Keyword…") placeholderText: i18n("Keyword…")
enabled: NotificationsManager.keywordNotificationAction !== PushNotificationAction.Unknown enabled: NotificationsManager.keywordNotificationAction !== PushRuleAction.Unknown
rightActions: Kirigami.Action { rightActions: Kirigami.Action {
icon.name: "edit-clear" icon.name: "edit-clear"
@@ -117,7 +117,7 @@ FormCard.FormCardPage {
Accessible.name: text Accessible.name: text
icon.name: "list-add" icon.name: "list-add"
display: QQC2.AbstractButton.IconOnly display: QQC2.AbstractButton.IconOnly
enabled: NotificationsManager.keywordNotificationAction !== PushNotificationAction.Unknown enabled: NotificationsManager.keywordNotificationAction !== PushRuleAction.Unknown
onClicked: { onClicked: {
root.pushRuleModel.addKeyword(keywordAddField.text) root.pushRuleModel.addKeyword(keywordAddField.text)
@@ -142,7 +142,7 @@ FormCard.FormCardPage {
sourceModel: root.pushRuleModel sourceModel: root.pushRuleModel
filterRowCallback: function(source_row, source_parent) { filterRowCallback: function(source_row, source_parent) {
let sectionRole = sourceModel.data(sourceModel.index(source_row, 0, source_parent), PushRuleModel.SectionRole) let sectionRole = sourceModel.data(sourceModel.index(source_row, 0, source_parent), PushRuleModel.SectionRole)
return sectionRole == PushNotificationSection.Invites; return sectionRole == PushRuleSection.Invites;
} }
} }
@@ -163,7 +163,7 @@ FormCard.FormCardPage {
sourceModel: root.pushRuleModel sourceModel: root.pushRuleModel
filterRowCallback: function(source_row, source_parent) { filterRowCallback: function(source_row, source_parent) {
let sectionRole = sourceModel.data(sourceModel.index(source_row, 0, source_parent), PushRuleModel.SectionRole) let sectionRole = sourceModel.data(sourceModel.index(source_row, 0, source_parent), PushRuleModel.SectionRole)
return sectionRole == PushNotificationSection.Unknown; return sectionRole == PushRuleSection.Unknown;
} }
} }

View File

@@ -26,7 +26,7 @@ FormCard.AbstractFormDelegate {
signal actionChanged(int action) signal actionChanged(int action)
signal deleteRule() signal deleteRule()
enabled: ruleAction !== PushNotificationAction.Unknown enabled: ruleAction !== PushRuleAction.Unknown
text: name text: name
@@ -147,35 +147,35 @@ FormCard.AbstractFormDelegate {
function notifcationRuleAction() { function notifcationRuleAction() {
if (onButton.checked) { if (onButton.checked) {
if (noisyButton.checked && highlightButton.checked && root.highlightable) { if (noisyButton.checked && highlightButton.checked && root.highlightable) {
return PushNotificationAction.NoisyHighlight return PushRuleAction.NoisyHighlight
} else if (noisyButton.checked) { } else if (noisyButton.checked) {
return PushNotificationAction.Noisy return PushRuleAction.Noisy
} else if (highlightButton.checked && root.highlightable) { } else if (highlightButton.checked && root.highlightable) {
return PushNotificationAction.Highlight return PushRuleAction.Highlight
} else { } else {
return PushNotificationAction.On return PushRuleAction.On
} }
} else { } else {
return PushNotificationAction.Off return PushRuleAction.Off
} }
} }
function nextNotificationRuleAction(action) { function nextNotificationRuleAction(action) {
let finished = false let finished = false
if (action == PushNotificationAction.NoisyHighlight) { if (action == PushRuleAction.NoisyHighlight) {
action = PushNotificationAction.Off action = PushRuleAction.Off
} else { } else {
action += 1 action += 1
} }
while (!finished) { while (!finished) {
if (action == PushNotificationAction.Off && !root.notificationsOnModifiable) { if (action == PushRuleAction.Off && !root.notificationsOnModifiable) {
action = PushNotificationAction.On action = PushRuleAction.On
} else if (action == PushNotificationAction.Noisy) { } else if (action == PushRuleAction.Noisy) {
action = PushNotificationAction.Highlight action = PushRuleAction.Highlight
} else if (action == PushNotificationAction.Highlight && !root.highlightable) { } else if (action == PushRuleAction.Highlight && !root.highlightable) {
action = PushNotificationAction.Off action = PushRuleAction.Off
} else { } else {
finished = true finished = true
} }
@@ -185,19 +185,19 @@ FormCard.AbstractFormDelegate {
} }
function isNotificationRuleOn(action) { function isNotificationRuleOn(action) {
return action == PushNotificationAction.On || return action == PushRuleAction.On ||
action == PushNotificationAction.Noisy || action == PushRuleAction.Noisy ||
action == PushNotificationAction.Highlight || action == PushRuleAction.Highlight ||
action == PushNotificationAction.NoisyHighlight action == PushRuleAction.NoisyHighlight
} }
function isNotificationRuleNoisy(action) { function isNotificationRuleNoisy(action) {
return action == PushNotificationAction.Noisy || return action == PushRuleAction.Noisy ||
action == PushNotificationAction.NoisyHighlight action == PushRuleAction.NoisyHighlight
} }
function isNotificationRuleHighlight(action) { function isNotificationRuleHighlight(action) {
return action == PushNotificationAction.Highlight || return action == PushRuleAction.Highlight ||
action == PushNotificationAction.NoisyHighlight action == PushRuleAction.NoisyHighlight
} }
} }

View File

@@ -72,7 +72,7 @@ FormCard.FormCardPage {
filterRowCallback: function(source_row, source_parent) { filterRowCallback: function(source_row, source_parent) {
let sectionRole = sourceModel.data(sourceModel.index(source_row, 0, source_parent), PushRuleModel.SectionRole) 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) let roomIdRole = sourceModel.data(sourceModel.index(source_row, 0, source_parent), PushRuleModel.RoomIdRole)
return sectionRole == PushNotificationSection.RoomKeywords && roomIdRole == root.room.id; return sectionRole == PushRuleSection.RoomKeywords && roomIdRole == root.room.id;
} }
} }
@@ -98,7 +98,7 @@ FormCard.FormCardPage {
Layout.fillWidth: true Layout.fillWidth: true
placeholderText: i18n("Keyword…") placeholderText: i18n("Keyword…")
enabled: NotificationsManager.keywordNotificationAction !== PushNotificationAction.Unknown enabled: NotificationsManager.keywordNotificationAction !== PushRuleAction.Unknown
rightActions: Kirigami.Action { rightActions: Kirigami.Action {
icon.name: "edit-clear" icon.name: "edit-clear"
@@ -120,7 +120,7 @@ FormCard.FormCardPage {
Accessible.name: text Accessible.name: text
icon.name: "list-add" icon.name: "list-add"
display: QQC2.AbstractButton.IconOnly display: QQC2.AbstractButton.IconOnly
enabled: NotificationsManager.keywordNotificationAction !== PushNotificationAction.Unknown && keywordAddField.text.length > 0 enabled: NotificationsManager.keywordNotificationAction !== PushRuleAction.Unknown && keywordAddField.text.length > 0
onClicked: { onClicked: {
root.pushRuleModel.addKeyword(keywordAddField.text, root.room.id) root.pushRuleModel.addKeyword(keywordAddField.text, root.room.id)