File indexing completed on 2024-03-24 16:24:46

0001 // SPDX-FileCopyrightText: 2018-2019 Black Hat <bhat@encom.eu.org>
0002 // SPDX-License-Identifier: GPL-3.0-only
0003 
0004 #pragma once
0005 
0006 #include <Quotient/room.h>
0007 
0008 #include <QCache>
0009 #include <QObject>
0010 #include <QTextCursor>
0011 
0012 #include <QCoroTask>
0013 
0014 #include "neochatuser.h"
0015 #include "pollhandler.h"
0016 
0017 class PushNotificationState : public QObject
0018 {
0019     Q_OBJECT
0020 
0021 public:
0022     /**
0023      * @brief Describes the push notification state for the room.
0024      */
0025     enum State {
0026         Unknown, /**< The state has not yet been obtained from the server. */
0027         Default, /**< The room follows the globally configured rules for the local user. */
0028         Mute, /**< No notifications for messages in the room. */
0029         MentionKeyword, /**< Notifications only for local user mentions and keywords. */
0030         All, /**< Notifications for all messages. */
0031     };
0032     Q_ENUM(State)
0033 };
0034 
0035 /**
0036  * @brief Defines a user mention in the current chat or edit text.
0037  */
0038 struct Mention {
0039     QTextCursor cursor; /**< Contains the mention's text and position in the text.  */
0040     QString text; /**< The inserted text of the mention. */
0041     int start = 0; /**< Start position of the mention. */
0042     int position = 0; /**< End position of the mention. */
0043     QString id; /**< The id the mention (used to create link when sending the message). */
0044 };
0045 
0046 /**
0047  * @class NeoChatRoom
0048  *
0049  * This class is designed to act as a wrapper over Quotient::Room to provide API and
0050  * functionality not available in Quotient::Room.
0051  *
0052  * The functions fall into two main categories:
0053  *  - Helper functions to make functionality easily accessible in QML.
0054  *  - Implement functions not yet available in Quotient::Room.
0055  *
0056  * @sa Quotient::Room
0057  */
0058 class NeoChatRoom : public Quotient::Room
0059 {
0060     Q_OBJECT
0061 
0062     /**
0063      * @brief A list of users currently typing in the room.
0064      *
0065      * The list does not include the local user.
0066      *
0067      * This is different to getting a list of NeoChatUser objects or Quotient::User objects
0068      * as neither of those can provide details like the displayName or avatarMediaId
0069      * without the room context as these can vary from room to room. This function
0070      * provides the room context and puts the result as a list of QVariantMap objects.
0071      *
0072      * @return a QVariantMap for the user with the following
0073      * parameters:
0074      *  - id - User ID.
0075      *  - avatarMediaId - Avatar id in the context of this room.
0076      *  - displayName - Display name in the context of this room.
0077      *  - display - Name in the context of this room.
0078      *
0079      * @sa Quotient::User, NeoChatUser
0080      */
0081     Q_PROPERTY(QVariantList usersTyping READ getUsersTyping NOTIFY typingChanged)
0082 
0083     /**
0084      * @brief Convenience function to get the QDateTime of the last event.
0085      *
0086      * @sa lastEvent()
0087      */
0088     Q_PROPERTY(QDateTime lastActiveTime READ lastActiveTime NOTIFY lastActiveTimeChanged)
0089 
0090     /**
0091      * @brief Whether a file is being uploaded to the server.
0092      */
0093     Q_PROPERTY(bool hasFileUploading READ hasFileUploading WRITE setHasFileUploading NOTIFY hasFileUploadingChanged)
0094 
0095     /**
0096      * @brief Progress of a file upload as a percentage 0 - 100%.
0097      *
0098      * The value will be 0 if no file is uploading.
0099      *
0100      * @sa hasFileUploading
0101      */
0102     Q_PROPERTY(int fileUploadingProgress READ fileUploadingProgress NOTIFY fileUploadingProgressChanged)
0103 
0104     /**
0105      * @brief Whether the read marker should be shown.
0106      */
0107     Q_PROPERTY(bool readMarkerLoaded READ readMarkerLoaded NOTIFY readMarkerLoadedChanged)
0108 
0109     /**
0110      * @brief Display name with any html special characters escaped.
0111      */
0112     Q_PROPERTY(QString htmlSafeDisplayName READ htmlSafeDisplayName NOTIFY displayNameChanged)
0113 
0114     /**
0115      * @brief The avatar image to be used for the room.
0116      */
0117     Q_PROPERTY(QString avatarMediaId READ avatarMediaId NOTIFY avatarChanged STORED false)
0118 
0119     /**
0120      * @brief Get a user object for the other person in a direct chat.
0121      */
0122     Q_PROPERTY(NeoChatUser *directChatRemoteUser READ directChatRemoteUser CONSTANT)
0123 
0124     /**
0125      * @brief If the room is a space.
0126      */
0127     Q_PROPERTY(bool isSpace READ isSpace CONSTANT)
0128 
0129     /**
0130      * @brief Whether the local user has an invite to the room.
0131      *
0132      * False for any other state including if the local user is a member.
0133      */
0134     Q_PROPERTY(bool isInvite READ isInvite NOTIFY isInviteChanged)
0135 
0136     /**
0137      * @brief The current join rule for the room as a QString.
0138      *
0139      * Possible values are [public, knock, invite, private, restricted].
0140      *
0141      * @sa https://spec.matrix.org/v1.5/client-server-api/#mroomjoin_rules
0142      */
0143     Q_PROPERTY(QString joinRule READ joinRule WRITE setJoinRule NOTIFY joinRuleChanged)
0144 
0145     /**
0146      * @brief Get the maximum room version that the server supports.
0147      *
0148      * Only returns main integer room versions (i.e. no msc room versions).
0149      */
0150     Q_PROPERTY(int maxRoomVersion READ maxRoomVersion NOTIFY maxRoomVersionChanged)
0151 
0152     /**
0153      * @brief The rule for which messages should generate notifications for the room.
0154      *
0155      * @sa PushNotificationState::State
0156      */
0157     Q_PROPERTY(PushNotificationState::State pushNotificationState READ pushNotificationState WRITE setPushNotificationState NOTIFY pushNotificationStateChanged)
0158 
0159     /**
0160      * @brief The current history visibilty setting for the room.
0161      *
0162      * Possible values are [invited, joined, shared, world_readable].
0163      *
0164      * @sa https://spec.matrix.org/v1.5/client-server-api/#room-history-visibility
0165      */
0166     Q_PROPERTY(QString historyVisibility READ historyVisibility WRITE setHistoryVisibility NOTIFY historyVisibilityChanged)
0167 
0168     /**
0169      * @brief Set the default URL preview state for room members.
0170      *
0171      * Assumed false if the org.matrix.room.preview_urls state message has never been
0172      * set. Can only be set if the calling user has a high enough power level.
0173      */
0174     Q_PROPERTY(bool defaultUrlPreviewState READ defaultUrlPreviewState WRITE setDefaultUrlPreviewState NOTIFY defaultUrlPreviewStateChanged)
0175 
0176     /**
0177      * @brief Enable URL previews for the local user.
0178      */
0179     Q_PROPERTY(bool urlPreviewEnabled READ urlPreviewEnabled WRITE setUrlPreviewEnabled NOTIFY urlPreviewEnabledChanged)
0180 
0181     /**
0182      * @brief Whether the local user can encrypt the room.
0183      *
0184      * Requires libQuotient 0.7 compiled with the Quotient_E2EE_ENABLED parameter to
0185      * be able to return true.
0186      *
0187      * A local user can encrypt a room if they have permission to send the m.room.encryption
0188      * state event.
0189      *
0190      * @sa https://spec.matrix.org/v1.5/client-server-api/#mroomencryption
0191      */
0192     Q_PROPERTY(bool canEncryptRoom READ canEncryptRoom NOTIFY canEncryptRoomChanged)
0193 
0194     /**
0195      * @brief The default power level in the room for new users.
0196      */
0197     Q_PROPERTY(int defaultUserPowerLevel READ defaultUserPowerLevel WRITE setDefaultUserPowerLevel NOTIFY defaultUserPowerLevelChanged)
0198 
0199     /**
0200      * @brief The power level required to invite users to the room.
0201      */
0202     Q_PROPERTY(int invitePowerLevel READ invitePowerLevel WRITE setInvitePowerLevel NOTIFY invitePowerLevelChanged)
0203 
0204     /**
0205      * @brief The power level required to kick users from the room.
0206      */
0207     Q_PROPERTY(int kickPowerLevel READ kickPowerLevel WRITE setKickPowerLevel NOTIFY kickPowerLevelChanged)
0208 
0209     /**
0210      * @brief The power level required to ban users from the room.
0211      */
0212     Q_PROPERTY(int banPowerLevel READ banPowerLevel WRITE setBanPowerLevel NOTIFY banPowerLevelChanged)
0213 
0214     /**
0215      * @brief The power level required to delete other user messages.
0216      */
0217     Q_PROPERTY(int redactPowerLevel READ redactPowerLevel WRITE setRedactPowerLevel NOTIFY redactPowerLevelChanged)
0218 
0219     /**
0220      * @brief The default power level for state events that are not explicitly specified.
0221      */
0222     Q_PROPERTY(int statePowerLevel READ statePowerLevel WRITE setStatePowerLevel NOTIFY statePowerLevelChanged)
0223 
0224     /**
0225      * @brief The default power level for event that are not explicitly specified.
0226      */
0227     Q_PROPERTY(int defaultEventPowerLevel READ defaultEventPowerLevel WRITE setDefaultEventPowerLevel NOTIFY defaultEventPowerLevelChanged)
0228 
0229     /**
0230      * @brief The power level required to change power levels for the room.
0231      */
0232     Q_PROPERTY(int powerLevelPowerLevel READ powerLevelPowerLevel WRITE setPowerLevelPowerLevel NOTIFY powerLevelPowerLevelChanged)
0233 
0234     /**
0235      * @brief The power level required to change the room name.
0236      */
0237     Q_PROPERTY(int namePowerLevel READ namePowerLevel WRITE setNamePowerLevel NOTIFY namePowerLevelChanged)
0238 
0239     /**
0240      * @brief The power level required to change the room avatar.
0241      */
0242     Q_PROPERTY(int avatarPowerLevel READ avatarPowerLevel WRITE setAvatarPowerLevel NOTIFY avatarPowerLevelChanged)
0243 
0244     /**
0245      * @brief The power level required to change the room aliases.
0246      */
0247     Q_PROPERTY(int canonicalAliasPowerLevel READ canonicalAliasPowerLevel WRITE setCanonicalAliasPowerLevel NOTIFY canonicalAliasPowerLevelChanged)
0248 
0249     /**
0250      * @brief The power level required to change the room topic.
0251      */
0252     Q_PROPERTY(int topicPowerLevel READ topicPowerLevel WRITE setTopicPowerLevel NOTIFY topicPowerLevelChanged)
0253 
0254     /**
0255      * @brief The power level required to encrypt the room.
0256      */
0257     Q_PROPERTY(int encryptionPowerLevel READ encryptionPowerLevel WRITE setEncryptionPowerLevel NOTIFY encryptionPowerLevelChanged)
0258 
0259     /**
0260      * @brief The power level required to change the room history visibility.
0261      */
0262     Q_PROPERTY(int historyVisibilityPowerLevel READ historyVisibilityPowerLevel WRITE setHistoryVisibilityPowerLevel NOTIFY historyVisibilityPowerLevelChanged)
0263 
0264     /**
0265      * @brief The power level required to pin events in the room.
0266      */
0267     Q_PROPERTY(int pinnedEventsPowerLevel READ pinnedEventsPowerLevel WRITE setPinnedEventsPowerLevel NOTIFY pinnedEventsPowerLevelChanged)
0268 
0269     /**
0270      * @brief The power level required to upgrade the room.
0271      */
0272     Q_PROPERTY(int tombstonePowerLevel READ tombstonePowerLevel WRITE setTombstonePowerLevel NOTIFY tombstonePowerLevelChanged)
0273 
0274     /**
0275      * @brief The power level required to set the room server access control list (ACL).
0276      */
0277     Q_PROPERTY(int serverAclPowerLevel READ serverAclPowerLevel WRITE setServerAclPowerLevel NOTIFY serverAclPowerLevelChanged)
0278 
0279     /**
0280      * @brief The power level required to add children to a space.
0281      */
0282     Q_PROPERTY(int spaceChildPowerLevel READ spaceChildPowerLevel WRITE setSpaceChildPowerLevel NOTIFY spaceChildPowerLevelChanged)
0283 
0284     /**
0285      * @brief The power level required to set the room parent space.
0286      */
0287     Q_PROPERTY(int spaceParentPowerLevel READ spaceParentPowerLevel WRITE setSpaceParentPowerLevel NOTIFY spaceParentPowerLevelChanged)
0288 
0289     /**
0290      * @brief The current text in the chatbox for the room.
0291      *
0292      * Due to problems with QTextDocument, unlike the other properties here,
0293      * chatBoxText is *not* used to store the text when switching rooms.
0294      */
0295     Q_PROPERTY(QString chatBoxText READ chatBoxText WRITE setChatBoxText NOTIFY chatBoxTextChanged)
0296 
0297     /**
0298      * @brief The text for any message currently being edited in the room.
0299      */
0300     Q_PROPERTY(QString editText READ editText WRITE setEditText NOTIFY editTextChanged)
0301 
0302     /**
0303      * @brief The event id of a message being replied to.
0304      *
0305      * Will be QString() if not replying to a message.
0306      */
0307     Q_PROPERTY(QString chatBoxReplyId READ chatBoxReplyId WRITE setChatBoxReplyId NOTIFY chatBoxReplyIdChanged)
0308 
0309     /**
0310      * @brief The event id of a message being edited.
0311      *
0312      * Will be QString() if not editing to a message.
0313      */
0314     Q_PROPERTY(QString chatBoxEditId READ chatBoxEditId WRITE setChatBoxEditId NOTIFY chatBoxEditIdChanged)
0315 
0316     /**
0317      * @brief Get the user for the message being replied to.
0318      *
0319      * This is different to getting a NeoChatUser object or Quotient::User object
0320      * as neither of those can provide details like the displayName or avatarMediaId
0321      * without the room context as these can vary from room to room.
0322      *
0323      * Returns an empty user if not replying to a message.
0324      *
0325      * The user QVariantMap has the following properties:
0326      *  - isLocalUser - Whether the user is the local user.
0327      *  - id - The matrix ID of the user.
0328      *  - displayName - Display name in the context of this room.
0329      *  - avatarSource - The mxc URL for the user's avatar in the current room.
0330      *  - avatarMediaId - Avatar id in the context of this room.
0331      *  - color - Color for the user.
0332      *  - object - The NeoChatUser object for the user.
0333      *
0334      * @sa getUser, Quotient::User, NeoChatUser
0335      */
0336     Q_PROPERTY(QVariantMap chatBoxReplyUser READ chatBoxReplyUser NOTIFY chatBoxReplyIdChanged)
0337 
0338     /**
0339      * @brief The content of the message being replied to.
0340      *
0341      * Will be QString() if not replying to a message.
0342      */
0343     Q_PROPERTY(QString chatBoxReplyMessage READ chatBoxReplyMessage NOTIFY chatBoxReplyIdChanged)
0344 
0345     /**
0346      * @brief Get the user for the message being edited.
0347      *
0348      * This is different to getting a NeoChatUser object or Quotient::User object
0349      * as neither of those can provide details like the displayName or avatarMediaId
0350      * without the room context as these can vary from room to room.
0351      *
0352      * Returns an empty user if not replying to a message.
0353      *
0354      * The user QVariantMap has the following properties:
0355      *  - isLocalUser - Whether the user is the local user.
0356      *  - id - The matrix ID of the user.
0357      *  - displayName - Display name in the context of this room.
0358      *  - avatarSource - The mxc URL for the user's avatar in the current room.
0359      *  - avatarMediaId - Avatar id in the context of this room.
0360      *  - color - Color for the user.
0361      *  - object - The NeoChatUser object for the user.
0362      *
0363      * @sa getUser, Quotient::User, NeoChatUser
0364      */
0365     Q_PROPERTY(QVariantMap chatBoxEditUser READ chatBoxEditUser NOTIFY chatBoxEditIdChanged)
0366 
0367     /**
0368      * @brief The content of the message being edited.
0369      *
0370      * Will be QString() if not editing a message.
0371      */
0372     Q_PROPERTY(QString chatBoxEditMessage READ chatBoxEditMessage NOTIFY chatBoxEditIdChanged)
0373 
0374     /**
0375      * @brief The file path of the attachment to be sent.
0376      */
0377     Q_PROPERTY(QString chatBoxAttachmentPath READ chatBoxAttachmentPath WRITE setChatBoxAttachmentPath NOTIFY chatBoxAttachmentPathChanged)
0378 
0379 public:
0380     /**
0381      * @brief Define the types on inline messages that can be shown.
0382      */
0383     enum MessageType {
0384         Positive, /**< Positive message, typically green. */
0385         Info, /**< Info message, typically highlight color. */
0386         Error, /**< Error message, typically red. */
0387     };
0388     Q_ENUM(MessageType)
0389 
0390     explicit NeoChatRoom(Quotient::Connection *connection, QString roomId, Quotient::JoinState joinState = {});
0391 
0392     /**
0393      * @brief Get a list of users in the context of this room.
0394      *
0395      * This is different to getting a list of NeoChatUser objects or Quotient::User objects
0396      * as neither of those can provide details like the displayName or avatarMediaId
0397      * without the room context as these can vary from room to room. This function
0398      * provides the room context and returns the result as a list of QVariantMap objects.
0399      *
0400      * @param keyword filters the users based on the displayname containing keyword.
0401      * @param limit max number of user returned, -1 is infinite.
0402      *
0403      * @return a QVariantList containing a QVariantMap for each user with the following
0404      * properties:
0405      *  - id - User ID.
0406      *  - displayName - Display name in the context of this room.
0407      *  - avatarMediaId - Avatar id in the context of this room.
0408      *  - color - Color for the user.
0409      *
0410      * @sa Quotient::User, NeoChatUser
0411      */
0412     Q_INVOKABLE [[nodiscard]] QVariantList getUsers(const QString &keyword, int limit = -1) const;
0413 
0414     /**
0415      * @brief Get a user in the context of this room.
0416      *
0417      * This is different to getting a NeoChatUser object or Quotient::User object
0418      * as neither of those can provide details like the displayName or avatarMediaId
0419      * without the room context as these can vary from room to room. This function
0420      * provides the room context and outputs the result as QVariantMap.
0421      *
0422      * Can be called with an empty QString to return an empty user, which is a useful return
0423      * from models to avoid undefined properties.
0424      *
0425      * @param userID the ID of the user to output.
0426      *
0427      * @return a QVariantMap for the user with the following properties:
0428      *  - isLocalUser - Whether the user is the local user.
0429      *  - id - The matrix ID of the user.
0430      *  - displayName - Display name in the context of this room.
0431      *  - avatarSource - The mxc URL for the user's avatar in the current room.
0432      *  - avatarMediaId - Avatar id in the context of this room.
0433      *  - color - Color for the user.
0434      *  - object - The NeoChatUser object for the user.
0435      *
0436      * @sa Quotient::User, NeoChatUser
0437      */
0438     Q_INVOKABLE [[nodiscard]] QVariantMap getUser(const QString &userID) const;
0439 
0440     /**
0441      * @brief Get a user in the context of this room.
0442      *
0443      * This is different to getting a NeoChatUser object or Quotient::User object
0444      * as neither of those can provide details like the displayName or avatarMediaId
0445      * without the room context as these can vary from room to room. This function
0446      * provides the room context and outputs the result as QVariantMap.
0447      *
0448      * Can be called with a nullptr to return an empty user, which is a useful return
0449      * from models to avoid undefined properties.
0450      *
0451      * @param user the user to output.
0452      *
0453      * @return a QVariantMap for the user with the following properties:
0454      *  - isLocalUser - Whether the user is the local user.
0455      *  - id - The matrix ID of the user.
0456      *  - displayName - Display name in the context of this room.
0457      *  - avatarSource - The mxc URL for the user's avatar in the current room.
0458      *  - avatarMediaId - Avatar id in the context of this room.
0459      *  - color - Color for the user.
0460      *  - object - The NeoChatUser object for the user.
0461      *
0462      * @sa Quotient::User, NeoChatUser
0463      */
0464     Q_INVOKABLE [[nodiscard]] QVariantMap getUser(NeoChatUser *user) const;
0465 
0466     [[nodiscard]] QVariantList getUsersTyping() const;
0467 
0468     [[nodiscard]] QDateTime lastActiveTime();
0469 
0470     /**
0471      * @brief Get the last interesting event.
0472      *
0473      * This function respects the user's state event setting and discards
0474      * other not interesting events.
0475      *
0476      * @warning This function can return an empty pointer if the room does not have
0477      *          any RoomMessageEvents loaded.
0478      */
0479     [[nodiscard]] const Quotient::RoomEvent *lastEvent() const;
0480 
0481     /**
0482      * @brief Output a string for the message content ready for display.
0483      *
0484      * The output string is dependant upon the event type and the desired output format.
0485      *
0486      * For most messages this is the body content of the message. For media messages
0487      * This will be the caption and for state events it will be a string specific
0488      * to that event with some dynamic details about the event added.
0489      *
0490      * E.g. For a room topic state event the text will be:
0491      *      "set the topic to: <new topic text>"
0492      *
0493      * @param evt the event for which a string is desired.
0494      * @param format the output format, usually Qt::PlainText or Qt::RichText.
0495      * @param stripNewlines whether the output should have new lines in it.
0496      */
0497     [[nodiscard]] QString eventToString(const Quotient::RoomEvent &evt, Qt::TextFormat format = Qt::PlainText, bool stripNewlines = false) const;
0498 
0499     /**
0500      * @brief Output a generic string for the message content ready for display.
0501      *
0502      * The output string is dependant upon the event type.
0503      *
0504      * Unlike NeoChatRoom::eventToString the string is the same for all events of
0505      * the same type
0506      *
0507      * E.g. For a message the text will be:
0508      *      "sent a message"
0509      *
0510      * @sa eventToString()
0511      */
0512     [[nodiscard]] QString eventToGenericString(const Quotient::RoomEvent &evt) const;
0513 
0514     /**
0515      * @brief Convenient way to call eventToString on the last event.
0516      *
0517      * @sa lastEvent()
0518      * @sa eventToString()
0519      */
0520     [[nodiscard]] QString lastEventToString(Qt::TextFormat format = Qt::PlainText, bool stripNewlines = false) const;
0521 
0522     /**
0523      * @brief Convenient way to check if the last event looks like it has spoilers.
0524      *
0525      * This does a basic check to see if the message contains a data-mx-spoiler
0526      * attribute within the text which makes it likely that the message has a spoiler
0527      * section. However this is not 100% reliable as during parsing it may be
0528      * removed if used within an illegal tag or on a tag for which data-mx-spoiler
0529      * is not a valid attribute.
0530      *
0531      * @sa lastEvent()
0532      */
0533     [[nodiscard]] bool lastEventIsSpoiler() const;
0534 
0535     [[nodiscard]] bool hasFileUploading() const;
0536     void setHasFileUploading(bool value);
0537 
0538     [[nodiscard]] int fileUploadingProgress() const;
0539     void setFileUploadingProgress(int value);
0540 
0541     /**
0542      * @brief Download a file for the given event to a local file location.
0543      */
0544     Q_INVOKABLE void download(const QString &eventId, const QUrl &localFilename = {});
0545 
0546     /**
0547      * @brief Download a file for the given event as a temporary file.
0548      */
0549     Q_INVOKABLE bool downloadTempFile(const QString &eventId);
0550 
0551     /**
0552      * @brief Check if the given event is highlighted.
0553      *
0554      * An event is highlighted if it contains the local user's id but was not sent by the
0555      * local user.
0556      */
0557     bool isEventHighlighted(const Quotient::RoomEvent *e) const;
0558 
0559     /**
0560      * @brief Convenience function to find out if the room contains the given user.
0561      *
0562      * A room contains the user if the user can be found and their JoinState is
0563      * not JoinState::Leave.
0564      */
0565     Q_INVOKABLE [[nodiscard]] bool containsUser(const QString &userID) const;
0566 
0567     /**
0568      * @brief True if the given user ID is banned from the room.
0569      */
0570     Q_INVOKABLE [[nodiscard]] bool isUserBanned(const QString &user) const;
0571 
0572     /**
0573      * @brief True if the local user can send the given event type.
0574      */
0575     Q_INVOKABLE [[nodiscard]] bool canSendEvent(const QString &eventType) const;
0576 
0577     /**
0578      * @brief True if the local user can send the given state event type.
0579      */
0580     Q_INVOKABLE [[nodiscard]] bool canSendState(const QString &eventType) const;
0581 
0582     /**
0583      * @brief Send a report to the server for an event.
0584      *
0585      * @param eventId the ID of the event being reported.
0586      * @param reason the reason given for reporting the event.
0587      */
0588     Q_INVOKABLE void reportEvent(const QString &eventId, const QString &reason);
0589 
0590     [[nodiscard]] bool readMarkerLoaded() const;
0591 
0592     QString htmlSafeDisplayName() const;
0593 
0594     /**
0595      * @brief Get subtitle text for room
0596      *
0597      * Fetches last event and removes markdown formatting
0598      *
0599      * @see lastEventToString()
0600      */
0601     [[nodiscard]] QString subtitleText();
0602 
0603     [[nodiscard]] QString avatarMediaId() const;
0604 
0605     NeoChatUser *directChatRemoteUser() const;
0606 
0607     [[nodiscard]] bool isSpace();
0608 
0609     bool isInvite() const;
0610 
0611     Q_INVOKABLE void clearInvitationNotification();
0612 
0613     [[nodiscard]] QString joinRule() const;
0614     void setJoinRule(const QString &joinRule);
0615 
0616     int maxRoomVersion() const;
0617 
0618     /**
0619      * @brief Map an alias to the room and publish.
0620      *
0621      * The alias is first mapped to the room and then published as an
0622      * alternate alias. Publishing the alias will fail if the user does not have
0623      * permission to send m.room.canonical_alias event messages.
0624      *
0625      * @note This is different to Quotient::Room::setLocalAliases() as that can only
0626      * get the room to publish an alias that is already mapped.
0627      *
0628      * @property alias QString in the form #new_alias:server.org
0629      *
0630      * @sa Quotient::Room::setLocalAliases()
0631      */
0632     Q_INVOKABLE void mapAlias(const QString &alias);
0633 
0634     /**
0635      * @brief Unmap an alias from the room.
0636      *
0637      * An unmapped alias is also removed as either the canonical alias or an alternate
0638      * alias.
0639      *
0640      * @note This is different to Quotient::Room::setLocalAliases() as that can only
0641      * get the room to un-publish an alias, while the mapping still exists.
0642      *
0643      * @property alias QString in the form #mapped_alias:server.org
0644      *
0645      * @sa Quotient::Room::setLocalAliases()
0646      */
0647     Q_INVOKABLE void unmapAlias(const QString &alias);
0648 
0649     /**
0650      * @brief Set the canonical alias of the room to an available mapped alias.
0651      *
0652      * If the new alias was already published as an alternate alias it will be removed
0653      * from that list.
0654      *
0655      * @note This is an overload of the function Quotient::Room::setCanonicalAlias().
0656      * This is to provide the functionality to remove the new canonical alias as a
0657      * published alt alias when set.
0658      *
0659      * @property newAlias QString in the form #new_alias:server.org
0660      *
0661      * @sa Quotient::Room::setCanonicalAlias()
0662      * */
0663     Q_INVOKABLE void setCanonicalAlias(const QString &newAlias);
0664 
0665     PushNotificationState::State pushNotificationState() const;
0666     void setPushNotificationState(PushNotificationState::State state);
0667 
0668     [[nodiscard]] QString historyVisibility() const;
0669     void setHistoryVisibility(const QString &historyVisibilityRule);
0670 
0671     [[nodiscard]] bool defaultUrlPreviewState() const;
0672     void setDefaultUrlPreviewState(const bool &defaultUrlPreviewState);
0673 
0674     [[nodiscard]] bool urlPreviewEnabled() const;
0675     void setUrlPreviewEnabled(const bool &urlPreviewEnabled);
0676 
0677     bool canEncryptRoom() const;
0678 
0679     /**
0680      * @brief Get the power level for the given user ID in the room.
0681      *
0682      * Returns the default value for a user in the room if they have no escalated
0683      * privileges or if they are not a member so membership should be known before using.
0684      */
0685     Q_INVOKABLE [[nodiscard]] int getUserPowerLevel(const QString &userId) const;
0686 
0687     Q_INVOKABLE void setUserPowerLevel(const QString &userID, const int &powerLevel);
0688 
0689     [[nodiscard]] int powerLevel(const QString &eventName, const bool &isStateEvent = false) const;
0690     void setPowerLevel(const QString &eventName, const int &newPowerLevel, const bool &isStateEvent = false);
0691 
0692     [[nodiscard]] int defaultUserPowerLevel() const;
0693     void setDefaultUserPowerLevel(const int &newPowerLevel);
0694 
0695     [[nodiscard]] int invitePowerLevel() const;
0696     void setInvitePowerLevel(const int &newPowerLevel);
0697 
0698     [[nodiscard]] int kickPowerLevel() const;
0699     void setKickPowerLevel(const int &newPowerLevel);
0700 
0701     [[nodiscard]] int banPowerLevel() const;
0702     void setBanPowerLevel(const int &newPowerLevel);
0703 
0704     [[nodiscard]] int redactPowerLevel() const;
0705     void setRedactPowerLevel(const int &newPowerLevel);
0706 
0707     [[nodiscard]] int statePowerLevel() const;
0708     void setStatePowerLevel(const int &newPowerLevel);
0709 
0710     [[nodiscard]] int defaultEventPowerLevel() const;
0711     void setDefaultEventPowerLevel(const int &newPowerLevel);
0712 
0713     [[nodiscard]] int powerLevelPowerLevel() const;
0714     void setPowerLevelPowerLevel(const int &newPowerLevel);
0715 
0716     [[nodiscard]] int namePowerLevel() const;
0717     void setNamePowerLevel(const int &newPowerLevel);
0718 
0719     [[nodiscard]] int avatarPowerLevel() const;
0720     void setAvatarPowerLevel(const int &newPowerLevel);
0721 
0722     [[nodiscard]] int canonicalAliasPowerLevel() const;
0723     void setCanonicalAliasPowerLevel(const int &newPowerLevel);
0724 
0725     [[nodiscard]] int topicPowerLevel() const;
0726     void setTopicPowerLevel(const int &newPowerLevel);
0727 
0728     [[nodiscard]] int encryptionPowerLevel() const;
0729     void setEncryptionPowerLevel(const int &newPowerLevel);
0730 
0731     [[nodiscard]] int historyVisibilityPowerLevel() const;
0732     void setHistoryVisibilityPowerLevel(const int &newPowerLevel);
0733 
0734     [[nodiscard]] int pinnedEventsPowerLevel() const;
0735     void setPinnedEventsPowerLevel(const int &newPowerLevel);
0736 
0737     [[nodiscard]] int tombstonePowerLevel() const;
0738     void setTombstonePowerLevel(const int &newPowerLevel);
0739 
0740     [[nodiscard]] int serverAclPowerLevel() const;
0741     void setServerAclPowerLevel(const int &newPowerLevel);
0742 
0743     [[nodiscard]] int spaceChildPowerLevel() const;
0744     void setSpaceChildPowerLevel(const int &newPowerLevel);
0745 
0746     [[nodiscard]] int spaceParentPowerLevel() const;
0747     void setSpaceParentPowerLevel(const int &newPowerLevel);
0748 
0749     QString chatBoxText() const;
0750     void setChatBoxText(const QString &text);
0751 
0752     QString editText() const;
0753     void setEditText(const QString &text);
0754 
0755     QString chatBoxReplyId() const;
0756     void setChatBoxReplyId(const QString &replyId);
0757 
0758     QVariantMap chatBoxReplyUser() const;
0759     QString chatBoxReplyMessage() const;
0760 
0761     QString chatBoxEditId() const;
0762     void setChatBoxEditId(const QString &editId);
0763 
0764     QVariantMap chatBoxEditUser() const;
0765     QString chatBoxEditMessage() const;
0766 
0767     QString chatBoxAttachmentPath() const;
0768     void setChatBoxAttachmentPath(const QString &attachmentPath);
0769 
0770     /**
0771      * @brief Retrieve the mentions for the current chatbox text.
0772      */
0773     QVector<Mention> *mentions();
0774 
0775     /**
0776      * @brief Retrieve the mentions for the current edit text.
0777      */
0778     QVector<Mention> *editMentions();
0779 
0780     /**
0781      * @brief Get the saved chatbox text for the room.
0782      */
0783     QString savedText() const;
0784 
0785     /**
0786      * @brief Save the chatbox text for the room.
0787      */
0788     void setSavedText(const QString &savedText);
0789 
0790     /**
0791      * @brief Reply to the last message sent in the timeline.
0792      *
0793      * @note This checks a maximum of the previous 35 message for performance reasons.
0794      */
0795     Q_INVOKABLE void replyLastMessage();
0796 
0797     /**
0798      * @brief Edit the last message sent by the local user.
0799      *
0800      * @note This checks a maximum of the previous 35 message for performance reasons.
0801      */
0802     Q_INVOKABLE void editLastMessage();
0803 
0804     /**
0805      * @brief Get a PollHandler object for the given event Id.
0806      *
0807      * Will return an existing PollHandler if one already exists for the event ID.
0808      * A new PollHandler will be created if one doesn't exist.
0809      *
0810      * @note Requires libQuotient 0.7.
0811      *
0812      * @sa PollHandler
0813      */
0814     Q_INVOKABLE PollHandler *poll(const QString &eventId);
0815 
0816     /**
0817      * @brief Get the full Json data for a given room account data event.
0818      */
0819     Q_INVOKABLE QByteArray roomAcountDataJson(const QString &eventType);
0820 
0821     Q_INVOKABLE [[nodiscard]] QUrl avatarForMember(NeoChatUser *user) const;
0822 
0823     /**
0824      * @brief Returns the event that is being replied to. This includes events that were manually loaded using NeoChatRoom::loadReply.
0825      */
0826     const Quotient::RoomEvent *getReplyForEvent(const Quotient::RoomEvent &event) const;
0827 
0828     /**
0829      * Loads the event replyId with the given id from the server and saves it locally.
0830      * For models to update correctly, eventId must be the event that is replying to replyId.
0831      * Intended to load the replied-to event when it isn't available locally.
0832      */
0833     Q_INVOKABLE void loadReply(const QString &eventId, const QString &replyId);
0834 
0835 private:
0836     QSet<const Quotient::RoomEvent *> highlights;
0837 
0838     bool m_hasFileUploading = false;
0839     int m_fileUploadingProgress = 0;
0840 
0841     PushNotificationState::State m_currentPushNotificationState = PushNotificationState::Unknown;
0842     bool m_pushNotificationStateUpdating = false;
0843 
0844     void checkForHighlights(const Quotient::TimelineItem &ti);
0845 
0846     void onAddNewTimelineEvents(timeline_iter_t from) override;
0847     void onAddHistoricalTimelineEvents(rev_iter_t from) override;
0848     void onRedaction(const Quotient::RoomEvent &prevEvent, const Quotient::RoomEvent &after) override;
0849 
0850     QCoro::Task<void> doDeleteMessagesByUser(const QString &user, QString reason);
0851     QCoro::Task<void> doUploadFile(QUrl url, QString body = QString());
0852 
0853     std::unique_ptr<Quotient::RoomEvent> m_cachedEvent;
0854 
0855     QString m_chatBoxText;
0856     QString m_editText;
0857     QString m_chatBoxReplyId;
0858     QString m_chatBoxEditId;
0859     QString m_chatBoxAttachmentPath;
0860     QVector<Mention> m_mentions;
0861     QVector<Mention> m_editMentions;
0862     QString m_savedText;
0863     QCache<QString, PollHandler> m_polls;
0864     std::vector<Quotient::event_ptr_tt<Quotient::RoomEvent>> m_extraEvents;
0865 
0866 private Q_SLOTS:
0867     void updatePushNotificationState(QString type);
0868 
0869     void cacheLastEvent();
0870 
0871 Q_SIGNALS:
0872     void cachedInputChanged();
0873     void busyChanged();
0874     void hasFileUploadingChanged();
0875     void fileUploadingProgressChanged();
0876     void backgroundChanged();
0877     void readMarkerLoadedChanged();
0878     void lastActiveTimeChanged();
0879     void isInviteChanged();
0880     void displayNameChanged();
0881     void pushNotificationStateChanged(PushNotificationState::State state);
0882     void showMessage(MessageType messageType, const QString &message);
0883     void chatBoxTextChanged();
0884     void editTextChanged();
0885     void chatBoxReplyIdChanged();
0886     void chatBoxEditIdChanged();
0887     void chatBoxAttachmentPathChanged();
0888     void canEncryptRoomChanged();
0889     void joinRuleChanged();
0890     void historyVisibilityChanged();
0891     void defaultUrlPreviewStateChanged();
0892     void urlPreviewEnabledChanged();
0893     void maxRoomVersionChanged();
0894     void defaultUserPowerLevelChanged();
0895     void invitePowerLevelChanged();
0896     void kickPowerLevelChanged();
0897     void banPowerLevelChanged();
0898     void redactPowerLevelChanged();
0899     void statePowerLevelChanged();
0900     void defaultEventPowerLevelChanged();
0901     void powerLevelPowerLevelChanged();
0902     void namePowerLevelChanged();
0903     void avatarPowerLevelChanged();
0904     void canonicalAliasPowerLevelChanged();
0905     void topicPowerLevelChanged();
0906     void encryptionPowerLevelChanged();
0907     void historyVisibilityPowerLevelChanged();
0908     void pinnedEventsPowerLevelChanged();
0909     void tombstonePowerLevelChanged();
0910     void serverAclPowerLevelChanged();
0911     void spaceChildPowerLevelChanged();
0912     void spaceParentPowerLevelChanged();
0913     void replyLoaded(const QString &eventId, const QString &replyId);
0914 
0915 public Q_SLOTS:
0916     /**
0917      * @brief Upload a file to the matrix server and post the file to the room.
0918      *
0919      * @param url the location of the file to be uploaded.
0920      * @param body the caption that is to be given to the file.
0921      */
0922     void uploadFile(const QUrl &url, const QString &body = QString());
0923 
0924     /**
0925      * @brief Accept an invitation for the local user to join the room.
0926      */
0927     void acceptInvitation();
0928 
0929     /**
0930      * @brief Leave and forget the room for the local user.
0931      *
0932      * @note This means that not only will the user no longer receive events in
0933      *       the room but the will forget any history up to this point.
0934      *
0935      * @sa https://spec.matrix.org/latest/client-server-api/#leaving-rooms
0936      */
0937     void forget();
0938 
0939     /**
0940      * @brief Set the typing notification state on the room for the local user.
0941      */
0942     void sendTypingNotification(bool isTyping);
0943 
0944     /**
0945      * @brief Send a message to the room.
0946      *
0947      * @param rawText the text as it was typed.
0948      * @param cleanedText the text marked up as html.
0949      * @param type the type of message being sent.
0950      * @param replyEventId the id of the message being replied to if a reply.
0951      * @param relateToEventId the id of the message being edited if an edit.
0952      */
0953     void postMessage(const QString &rawText,
0954                      const QString &cleanedText,
0955                      Quotient::MessageEventType type = Quotient::MessageEventType::Text,
0956                      const QString &replyEventId = QString(),
0957                      const QString &relateToEventId = QString());
0958 
0959     /**
0960      * @brief Send an html message to the room.
0961      *
0962      * @param text the text as it was typed.
0963      * @param html the text marked up as html.
0964      * @param type the type of message being sent.
0965      * @param replyEventId the id of the message being replied to if a reply.
0966      * @param relateToEventId the id of the message being edited if an edit.
0967      */
0968     void postHtmlMessage(const QString &text,
0969                          const QString &html,
0970                          Quotient::MessageEventType type = Quotient::MessageEventType::Text,
0971                          const QString &replyEventId = QString(),
0972                          const QString &relateToEventId = QString());
0973 
0974     /**
0975      * @brief Set the room avatar.
0976      */
0977     void changeAvatar(const QUrl &localFile);
0978 
0979     /**
0980      * @brief Toggle the reaction state of the given reaction for the local user.
0981      */
0982     void toggleReaction(const QString &eventId, const QString &reaction);
0983 
0984     /**
0985      * @brief Delete recent messages by the given user.
0986      *
0987      * This will delete all messages by that user in this room that are currently loaded.
0988      */
0989     void deleteMessagesByUser(const QString &user, const QString &reason);
0990 
0991     /**
0992      *  @brief Sends a location to a room
0993      *  The event is sent in the migration format as specified in MSC3488
0994      * @param lat latitude
0995      * @param lon longitude
0996      * @param description description for the location
0997      */
0998     void sendLocation(float lat, float lon, const QString &description);
0999 };