File indexing completed on 2024-04-28 16:10:11

0001 // SPDX-FileCopyrightText: 2022 James Graham <james.h.graham@protonmail.com>
0002 // SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0003 
0004 #pragma once
0005 
0006 #include <QAbstractListModel>
0007 
0008 #include <Quotient/csapi/definitions/push_rule.h>
0009 
0010 #include "notificationsmanager.h"
0011 
0012 /**
0013  * @class PushNotificationKind
0014  *
0015  * A class with the Kind enum for push notifications and helper functions.
0016  *
0017  * The kind relates to the kinds of push rule definied in the matrix spec, see
0018  * https://spec.matrix.org/v1.7/client-server-api/#push-rules for full details.
0019  */
0020 class PushNotificationKind : public QObject
0021 {
0022     Q_OBJECT
0023 
0024 public:
0025     /**
0026      * @brief Defines the different kinds of push rule.
0027      */
0028     enum Kind {
0029         Override = 0, /**< The highest priority rules. */
0030         Content, /**< These configure behaviour for messages that match certain patterns. */
0031         Room, /**< These rules change the behaviour of all messages for a given room. */
0032         Sender, /**< These rules configure notification behaviour for messages from a specific Matrix user ID. */
0033         Underride, /**< These are identical to override rules, but have a lower priority than content, room and sender rules. */
0034     };
0035     Q_ENUM(Kind)
0036 
0037     /**
0038      * @brief Translate the Kind enum value to a human readable string.
0039      *
0040      * @sa Kind
0041      */
0042     static QString kindString(Kind kind)
0043     {
0044         switch (kind) {
0045         case Kind::Override:
0046             return QLatin1String("override");
0047         case Kind::Content:
0048             return QLatin1String("content");
0049         case Kind::Room:
0050             return QLatin1String("room");
0051         case Kind::Sender:
0052             return QLatin1String("sender");
0053         case Kind::Underride:
0054             return QLatin1String("underride");
0055         default:
0056             return {};
0057         }
0058     };
0059 };
0060 
0061 /**
0062  * @class PushNotificationSection
0063  *
0064  * A class with the Section enum for push notifications and helper functions.
0065  *
0066  * @note This is different from the PushNotificationKind and instead is used for sorting
0067  *       in the settings page which is not necessarily by Kind.
0068  *
0069  * @sa PushNotificationKind
0070  */
0071 class PushNotificationSection : public QObject
0072 {
0073     Q_OBJECT
0074 
0075 public:
0076     /**
0077      * @brief Defines the sections to sort push rules into.
0078      */
0079     enum Section {
0080         Master = 0, /**< The master push rule */
0081         Room, /**< Push rules relating to all rooms. */
0082         Mentions, /**< Push rules relating to user mentions. */
0083         Keywords, /**< Global Keyword push rules. */
0084         RoomKeywords, /**< Keyword push rules that only apply to a specific room. */
0085         Invites, /**< Push rules relating to invites. */
0086         /**
0087          * @brief Push rules that should never be shown.
0088          *
0089          * There are numerous rules that get set that shouldn't be shown in the general
0090          * list e.g. The array of rules used to override global settings in individual
0091          * rooms.
0092          */
0093         Undefined,
0094     };
0095     Q_ENUM(Section)
0096 
0097     /**
0098      * @brief Translate the Section enum value to a human readable string.
0099      *
0100      * @sa Section
0101      */
0102     static QString sectionString(Section section)
0103     {
0104         switch (section) {
0105         case Section::Master:
0106             return QLatin1String("Master");
0107         case Section::Room:
0108             return QLatin1String("Room Notifications");
0109         case Section::Mentions:
0110             return QLatin1String("@Mentions");
0111         case Section::Keywords:
0112             return QLatin1String("Keywords");
0113         case Section::Invites:
0114             return QLatin1String("Invites");
0115         default:
0116             return {};
0117         }
0118     };
0119 };
0120 
0121 /**
0122  * @class PushRuleModel
0123  *
0124  * This class defines the model for managing notification push rule keywords.
0125  */
0126 class PushRuleModel : public QAbstractListModel
0127 {
0128     Q_OBJECT
0129 
0130     /**
0131      * @brief The default state for any newly created keyword rule.
0132      */
0133     Q_PROPERTY(PushNotificationAction::Action defaultState READ defaultState WRITE setDefaultState NOTIFY defaultStateChanged)
0134 
0135     /**
0136      * @brief The global notification state.
0137      *
0138      * If this rule is set to off all push notifications are disabled regardless
0139      * of other settings.
0140      */
0141     Q_PROPERTY(bool globalNotificationsEnabled READ globalNotificationsEnabled WRITE setGlobalNotificationsEnabled NOTIFY globalNotificationsEnabledChanged)
0142 
0143     /**
0144      * @brief Whether the global notification state has been retrieved from the server.
0145      *
0146      * @sa globalNotificationsEnabled, PushNotificationAction::Action
0147      */
0148     Q_PROPERTY(bool globalNotificationsSet READ globalNotificationsSet NOTIFY globalNotificationsSetChanged)
0149 
0150 public:
0151     struct Rule {
0152         QString id;
0153         PushNotificationKind::Kind kind;
0154         PushNotificationAction::Action action;
0155         PushNotificationSection::Section section;
0156         bool enabled;
0157         QString roomId;
0158     };
0159 
0160     /**
0161      * @brief Defines the model roles.
0162      */
0163     enum EventRoles {
0164         NameRole = Qt::DisplayRole, /**< The push rule name. */
0165         IdRole, /**< The push rule ID. */
0166         KindRole, /**< The kind of notification rule; override, content, etc. */
0167         ActionRole, /**< The PushNotificationAction for the rule. */
0168         HighlightableRole, /**< Whether the rule can have a highlight action. */
0169         DeletableRole, /**< Whether the rule can be deleted the rule. */
0170         SectionRole, /**< The section to sort into in the settings page. */
0171         RoomIdRole, /**< The room the rule applies to (blank if global). */
0172     };
0173     Q_ENUM(EventRoles)
0174 
0175     explicit PushRuleModel(QObject *parent = nullptr);
0176 
0177     [[nodiscard]] PushNotificationAction::Action defaultState() const;
0178     void setDefaultState(PushNotificationAction::Action defaultState);
0179 
0180     [[nodiscard]] bool globalNotificationsEnabled() const;
0181     void setGlobalNotificationsEnabled(bool enabled);
0182 
0183     [[nodiscard]] bool globalNotificationsSet() const;
0184 
0185     /**
0186      * @brief Get the given role value at the given index.
0187      *
0188      * @sa QAbstractItemModel::data
0189      */
0190     [[nodiscard]] QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
0191 
0192     /**
0193      * @brief Number of rows in the model.
0194      *
0195      * @sa QAbstractItemModel::rowCount
0196      */
0197     [[nodiscard]] int rowCount(const QModelIndex &parent = QModelIndex()) const override;
0198 
0199     /**
0200      * @brief Returns a mapping from Role enum values to role names.
0201      *
0202      * @sa EventRoles, QAbstractItemModel::roleNames()
0203      */
0204     [[nodiscard]] QHash<int, QByteArray> roleNames() const override;
0205 
0206     Q_INVOKABLE void setPushRuleAction(const QString &id, PushNotificationAction::Action action);
0207 
0208     /**
0209      * @brief Add a new keyword to the model.
0210      */
0211     Q_INVOKABLE void addKeyword(const QString &keyword, const QString &roomId = {});
0212 
0213     /**
0214      * @brief Remove a keyword from the model.
0215      */
0216     Q_INVOKABLE void removeKeyword(const QString &keyword);
0217 
0218 Q_SIGNALS:
0219     void defaultStateChanged();
0220     void globalNotificationsEnabledChanged();
0221     void globalNotificationsSetChanged();
0222 
0223 private Q_SLOTS:
0224     void controllerConnectionChanged();
0225     void updateNotificationRules(const QString &type);
0226 
0227 private:
0228     PushNotificationAction::Action m_defaultKeywordAction;
0229     QList<Rule> m_rules;
0230 
0231     void setRules(QVector<Quotient::PushRule> rules, PushNotificationKind::Kind kind);
0232 
0233     int getRuleIndex(const QString &ruleId) const;
0234     PushNotificationSection::Section getSection(Quotient::PushRule rule);
0235 
0236     void setNotificationRuleEnabled(const QString &kind, const QString &ruleId, bool enabled);
0237     void setNotificationRuleActions(const QString &kind, const QString &ruleId, PushNotificationAction::Action action);
0238     PushNotificationAction::Action variantToAction(const QVector<QVariant> &actions, bool enabled);
0239     QVector<QVariant> actionToVariant(PushNotificationAction::Action action, const QString &sound = "default");
0240 };
0241 Q_DECLARE_METATYPE(PushRuleModel *)