diff options
author | Hubert Chathi <uhoreg@debian.org> | 2019-06-25 16:33:24 -0400 |
---|---|---|
committer | Hubert Chathi <uhoreg@debian.org> | 2019-06-25 16:33:24 -0400 |
commit | 72d5660efd0755bb53a8699cd39865155400d288 (patch) | |
tree | ed7e7537e6a3eb7e8b92226c4015f9bfc8e11c5a /lib/room.h | |
parent | 52407a933bfe1fcc5f3aa1dccaa0b9a8279aa634 (diff) | |
parent | 681203f951d13e9e8eaf772435cac28c6d74cd42 (diff) | |
download | libquotient-72d5660efd0755bb53a8699cd39865155400d288.tar.gz libquotient-72d5660efd0755bb53a8699cd39865155400d288.zip |
Merge branch 'upstream' (v0.5.2)
Diffstat (limited to 'lib/room.h')
-rw-r--r-- | lib/room.h | 208 |
1 files changed, 185 insertions, 23 deletions
@@ -18,7 +18,7 @@ #pragma once -#include "jobs/syncjob.h" +#include "csapi/message_pagination.h" #include "events/roommessageevent.h" #include "events/accountdataevents.h" #include "eventitem.h" @@ -33,6 +33,8 @@ namespace QMatrixClient { class Event; + class Avatar; + class SyncRoomData; class RoomMemberEvent; class Connection; class User; @@ -41,10 +43,17 @@ namespace QMatrixClient class SetRoomStateWithKeyJob; class RedactEventJob; + /** The data structure used to expose file transfer information to views + * + * This is specifically tuned to work with QML exposing all traits as + * Q_PROPERTY values. + */ class FileTransferInfo { Q_GADGET + Q_PROPERTY(bool isUpload MEMBER isUpload CONSTANT) Q_PROPERTY(bool active READ active CONSTANT) + Q_PROPERTY(bool started READ started CONSTANT) Q_PROPERTY(bool completed READ completed CONSTANT) Q_PROPERTY(bool failed READ failed CONSTANT) Q_PROPERTY(int progress MEMBER progress CONSTANT) @@ -52,16 +61,17 @@ namespace QMatrixClient Q_PROPERTY(QUrl localDir MEMBER localDir CONSTANT) Q_PROPERTY(QUrl localPath MEMBER localPath CONSTANT) public: - enum Status { None, Started, Completed, Failed }; + enum Status { None, Started, Completed, Failed, Cancelled }; Status status = None; + bool isUpload = false; int progress = 0; int total = -1; QUrl localDir { }; QUrl localPath { }; - bool active() const - { return status == Started || status == Completed; } + bool started() const { return status == Started; } bool completed() const { return status == Completed; } + bool active() const { return started() || completed(); } bool failed() const { return status == Failed; } }; @@ -71,10 +81,14 @@ namespace QMatrixClient Q_PROPERTY(Connection* connection READ connection CONSTANT) Q_PROPERTY(User* localUser READ localUser CONSTANT) Q_PROPERTY(QString id READ id CONSTANT) + Q_PROPERTY(QString version READ version NOTIFY baseStateLoaded) + Q_PROPERTY(bool isUnstable READ isUnstable NOTIFY stabilityUpdated) + Q_PROPERTY(QString predecessorId READ predecessorId NOTIFY baseStateLoaded) + Q_PROPERTY(QString successorId READ successorId NOTIFY upgraded) Q_PROPERTY(QString name READ name NOTIFY namesChanged) Q_PROPERTY(QStringList aliases READ aliases NOTIFY namesChanged) Q_PROPERTY(QString canonicalAlias READ canonicalAlias NOTIFY namesChanged) - Q_PROPERTY(QString displayName READ displayName NOTIFY namesChanged) + Q_PROPERTY(QString displayName READ displayName NOTIFY displaynameChanged) Q_PROPERTY(QString topic READ topic NOTIFY topicChanged) Q_PROPERTY(QString avatarMediaId READ avatarMediaId NOTIFY avatarChanged STORED false) Q_PROPERTY(QUrl avatarUrl READ avatarUrl NOTIFY avatarChanged) @@ -83,6 +97,9 @@ namespace QMatrixClient Q_PROPERTY(int timelineSize READ timelineSize NOTIFY addedMessages) Q_PROPERTY(QStringList memberNames READ memberNames NOTIFY memberListChanged) Q_PROPERTY(int memberCount READ memberCount NOTIFY memberListChanged) + Q_PROPERTY(int joinedCount READ joinedCount NOTIFY memberListChanged) + Q_PROPERTY(int invitedCount READ invitedCount NOTIFY memberListChanged) + Q_PROPERTY(int totalMemberCount READ totalMemberCount NOTIFY memberListChanged) Q_PROPERTY(bool displayed READ displayed WRITE setDisplayed NOTIFY displayedChanged) Q_PROPERTY(QString firstDisplayedEventId READ firstDisplayedEventId WRITE setFirstDisplayedEventId NOTIFY firstDisplayedEventChanged) @@ -95,12 +112,34 @@ namespace QMatrixClient Q_PROPERTY(bool isFavourite READ isFavourite NOTIFY tagsChanged) Q_PROPERTY(bool isLowPriority READ isLowPriority NOTIFY tagsChanged) + Q_PROPERTY(GetRoomEventsJob* eventsHistoryJob READ eventsHistoryJob NOTIFY eventsHistoryJobChanged) + public: using Timeline = std::deque<TimelineItem>; using PendingEvents = std::vector<PendingEventItem>; using rev_iter_t = Timeline::const_reverse_iterator; using timeline_iter_t = Timeline::const_iterator; + enum Change : uint { + NoChange = 0x0, + NameChange = 0x1, + CanonicalAliasChange = 0x2, + TopicChange = 0x4, + UnreadNotifsChange = 0x8, + AvatarChange = 0x10, + JoinStateChange = 0x20, + TagsChange = 0x40, + MembersChange = 0x80, + /* = 0x100, */ + AccountDataChange = 0x200, + SummaryChange = 0x400, + ReadMarkerChange = 0x800, + OtherChange = 0x8000, + AnyChange = 0xFFFF + }; + Q_DECLARE_FLAGS(Changes, Change) + Q_FLAG(Changes) + Room(Connection* connection, QString id, JoinState initialJoinState); ~Room() override; @@ -109,6 +148,10 @@ namespace QMatrixClient Connection* connection() const; User* localUser() const; const QString& id() const; + QString version() const; + bool isUnstable() const; + QString predecessorId() const; + QString successorId() const; QString name() const; QStringList aliases() const; QString canonicalAlias() const; @@ -116,15 +159,22 @@ namespace QMatrixClient QString topic() const; QString avatarMediaId() const; QUrl avatarUrl() const; + const Avatar& avatarObject() const; Q_INVOKABLE JoinState joinState() const; Q_INVOKABLE QList<User*> usersTyping() const; QList<User*> membersLeft() const; Q_INVOKABLE QList<User*> users() const; QStringList memberNames() const; + [[deprecated("Use joinedCount(), invitedCount(), totalMemberCount()")]] int memberCount() const; int timelineSize() const; bool usesEncryption() const; + int joinedCount() const; + int invitedCount() const; + int totalMemberCount() const; + + GetRoomEventsJob* eventsHistoryJob() const; /** * Returns a square room avatar with the given size and requests it @@ -177,9 +227,16 @@ namespace QMatrixClient const Timeline& messageEvents() const; const PendingEvents& pendingEvents() const; /** - * A convenience method returning the read marker to - * the before-oldest message + * A convenience method returning the read marker to the position + * before the "oldest" event; same as messageEvents().crend() */ + rev_iter_t historyEdge() const; + /** + * A convenience method returning the iterator beyond the latest + * arrived event; same as messageEvents().cend() + */ + Timeline::const_iterator syncEdge() const; + /// \deprecated Use historyEdge instead rev_iter_t timelineEdge() const; Q_INVOKABLE TimelineItem::index_t minTimelineIndex() const; Q_INVOKABLE TimelineItem::index_t maxTimelineIndex() const; @@ -187,8 +244,17 @@ namespace QMatrixClient rev_iter_t findInTimeline(TimelineItem::index_t index) const; rev_iter_t findInTimeline(const QString& evtId) const; + PendingEvents::iterator findPendingEvent(const QString & txnId); + PendingEvents::const_iterator findPendingEvent(const QString & txnId) const; bool displayed() const; + /// Mark the room as currently displayed to the user + /** + * Marking the room displayed causes the room to obtain the full + * list of members if it's been lazy-loaded before; in the future + * it may do more things bound to "screen time" of the room, e.g. + * measure that "screen time". + */ void setDisplayed(bool displayed = true); QString firstDisplayedEventId() const; rev_iter_t firstDisplayedMarker() const; @@ -288,11 +354,32 @@ namespace QMatrixClient /// Get the list of users this room is a direct chat with QList<User*> directChatUsers() const; - Q_INVOKABLE QUrl urlToThumbnail(const QString& eventId); - Q_INVOKABLE QUrl urlToDownload(const QString& eventId); - Q_INVOKABLE QString fileNameToDownload(const QString& eventId); + Q_INVOKABLE QUrl urlToThumbnail(const QString& eventId) const; + Q_INVOKABLE QUrl urlToDownload(const QString& eventId) const; + + /// Get a file name for downloading for a given event id + /*! + * The event MUST be RoomMessageEvent and have content + * for downloading. \sa RoomMessageEvent::hasContent + */ + Q_INVOKABLE QString fileNameToDownload(const QString& eventId) const; + + /// Get information on file upload/download + /*! + * \param id uploads are identified by the corresponding event's + * transactionId (because uploads are done before + * the event is even sent), while downloads are using + * the normal event id for identifier. + */ Q_INVOKABLE FileTransferInfo fileTransferInfo(const QString& id) const; + /// Get the URL to the actual file source in a unified way + /*! + * For uploads it will return a URL to a local file; for downloads + * the URL will be taken from the corresponding room event. + */ + Q_INVOKABLE QUrl fileSource(const QString& id) const; + /** Pretty-prints plain text into HTML * As of now, it's exactly the same as QMatrixClient::prettyPrint(); * in the future, it will also linkify room aliases, mxids etc. @@ -314,11 +401,17 @@ namespace QMatrixClient Q_INVOKABLE bool supportsCalls() const; public slots: + /** Check whether the room should be upgraded */ + void checkVersion(); + QString postMessage(const QString& plainText, MessageEventType type); QString postPlainText(const QString& plainText); QString postHtmlMessage(const QString& plainText, - const QString& html, MessageEventType type); + const QString& html, + MessageEventType type = MessageEventType::Text); QString postHtmlText(const QString& plainText, const QString& html); + QString postFile(const QString& plainText, const QUrl& localPath, + bool asGenericFile = false); /** Post a pre-created room message event * * Takes ownership of the event, deleting it once the matching one @@ -332,8 +425,12 @@ namespace QMatrixClient void discardMessage(const QString& txnId); void setName(const QString& newName); void setCanonicalAlias(const QString& newAlias); + void setAliases(const QStringList& aliases); void setTopic(const QString& newTopic); + /// You shouldn't normally call this method; it's here for debugging + void refreshDisplayName(); + void getPreviousContent(int limit = 10); void inviteToRoom(const QString& memberId); @@ -356,19 +453,63 @@ namespace QMatrixClient /// Mark all messages in the room as read void markAllMessagesAsRead(); + /// Whether the current user is allowed to upgrade the room + bool canSwitchVersions() const; + + /// Switch the room's version (aka upgrade) + void switchVersion(QString newVersion); + signals: + /// Initial set of state events has been loaded + /** + * The initial set is what comes from the initial sync for the room. + * This includes all basic things like RoomCreateEvent, + * RoomNameEvent, a (lazy-loaded, not full) set of RoomMemberEvents + * etc. This is a per-room reflection of Connection::loadedRoomState + * \sa Connection::loadedRoomState + */ + void baseStateLoaded(); + void eventsHistoryJobChanged(); void aboutToAddHistoricalMessages(RoomEventsRange events); void aboutToAddNewMessages(RoomEventsRange events); void addedMessages(int fromIndex, int toIndex); - void pendingEventAboutToAdd(); + /// The event is about to be appended to the list of pending events + void pendingEventAboutToAdd(RoomEvent* event); + /// An event has been appended to the list of pending events void pendingEventAdded(); + /// The remote echo has arrived with the sync and will be merged + /// with its local counterpart + /** NB: Requires a sync loop to be emitted */ void pendingEventAboutToMerge(RoomEvent* serverEvent, int pendingEventIndex); + /// The remote and local copies of the event have been merged + /** NB: Requires a sync loop to be emitted */ void pendingEventMerged(); + /// An event will be removed from the list of pending events void pendingEventAboutToDiscard(int pendingEventIndex); + /// An event has just been removed from the list of pending events void pendingEventDiscarded(); + /// The status of a pending event has changed + /** \sa PendingEventItem::deliveryStatus */ void pendingEventChanged(int pendingEventIndex); + /// The server accepted the message + /** This is emitted when an event sending request has successfully + * completed. This does not mean that the event is already in the + * local timeline, only that the server has accepted it. + * \param txnId transaction id assigned by the client during sending + * \param eventId event id assigned by the server upon acceptance + * \sa postEvent, postPlainText, postMessage, postHtmlMessage + * \sa pendingEventMerged, aboutToAddNewMessages + */ + void messageSent(QString txnId, QString eventId); + /** A common signal for various kinds of changes in the room + * Aside from all changes in the room state + * @param changes a set of flags describing what changes occured + * upon the last sync + * \sa StateChange + */ + void changed(Changes changes); /** * \brief The room name, the canonical alias or other aliases changed * @@ -383,7 +524,17 @@ namespace QMatrixClient void userRemoved(User* user); void memberAboutToRename(User* user, QString newName); void memberRenamed(User* user); + /// The list of members has changed + /** Emitted no more than once per sync, this is a good signal to + * for cases when some action should be done upon any change in + * the member list. If you need per-item granularity you should use + * userAdded, userRemoved and memberAboutToRename / memberRenamed + * instead. + */ void memberListChanged(); + /// The previously lazy-loaded members list is now loaded entirely + /// \sa setDisplayed + void allMembersLoaded(); void encryption(); void joinStateChanged(JoinState oldState, JoinState newState); @@ -415,30 +566,40 @@ namespace QMatrixClient void fileTransferCancelled(QString id); void callEvent(Room* room, const RoomEvent* event); - /// The room is about to be deleted - void beforeDestruction(Room*); - public: // Used by Connection - not a part of the client API - QJsonObject toJson() const; - void updateData(SyncRoomData&& data ); + /// The room's version stability may have changed + void stabilityUpdated(QString recommendedDefault, + QStringList stableVersions); + /// This room has been upgraded and won't receive updates anymore + void upgraded(QString serverMessage, Room* successor); + /// An attempted room upgrade has failed + void upgradeFailed(QString errorMessage); - // Clients should use Connection::joinRoom() and Room::leaveRoom() - // to change the room state - void setJoinState( JoinState state ); + /// The room is about to be deleted + void beforeDestruction(Room*); protected: /// Returns true if any of room names/aliases has changed - virtual bool processStateEvent(const RoomEvent& e); - virtual void processEphemeralEvent(EventPtr&& event); - virtual void processAccountDataEvent(EventPtr&& event); + virtual Changes processStateEvent(const RoomEvent& e); + virtual Changes processEphemeralEvent(EventPtr&& event); + virtual Changes processAccountDataEvent(EventPtr&& event); virtual void onAddNewTimelineEvents(timeline_iter_t /*from*/) { } virtual void onAddHistoricalTimelineEvents(rev_iter_t /*from*/) { } virtual void onRedaction(const RoomEvent& /*prevEvent*/, const RoomEvent& /*after*/) { } + virtual QJsonObject toJson() const; + virtual void updateData(SyncRoomData&& data, bool fromCache = false); private: + friend class Connection; + class Private; Private* d; + + // This is called from Connection, reflecting a state change that + // arrived from the server. Clients should use + // Connection::joinRoom() and Room::leaveRoom() to change the state. + void setJoinState(JoinState state); }; class MemberSorter @@ -461,3 +622,4 @@ namespace QMatrixClient }; } // namespace QMatrixClient Q_DECLARE_METATYPE(QMatrixClient::FileTransferInfo) +Q_DECLARE_OPERATORS_FOR_FLAGS(QMatrixClient::Room::Changes) |