File indexing completed on 2024-04-21 04:59:29

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