| 1 | // SPDX-FileCopyrightText: 2018 Kitsune Ral <kitsune-ral@users.sf.net> |
| 2 | // SPDX-License-Identifier: LGPL-2.1-or-later |
| 3 | |
| 4 | #pragma once |
| 5 | |
| 6 | #include "quotient_common.h" |
| 7 | |
| 8 | #include "events/stateevent.h" |
| 9 | |
| 10 | namespace Quotient { |
| 11 | |
| 12 | constexpr inline auto UnreadNotificationsKey = "unread_notifications"_ls ; |
| 13 | constexpr inline auto PartiallyReadCountKey = "x-quotient.since_fully_read_count"_ls ; |
| 14 | constexpr inline auto NewUnreadCountKey = "org.matrix.msc2654.unread_count"_ls ; |
| 15 | constexpr inline auto HighlightCountKey = "highlight_count"_ls ; |
| 16 | |
| 17 | /// Room summary, as defined in MSC688 |
| 18 | /** |
| 19 | * Every member of this structure is an Omittable; as per the MSC, only |
| 20 | * changed values are sent from the server so if nothing is in the payload |
| 21 | * the respective member will be omitted. In particular, `heroes.omitted()` |
| 22 | * means that nothing has come from the server; heroes.value().isEmpty() |
| 23 | * means a peculiar case of a room with the only member - the current user. |
| 24 | */ |
| 25 | struct QUOTIENT_API RoomSummary { |
| 26 | Omittable<int> joinedMemberCount; |
| 27 | Omittable<int> invitedMemberCount; |
| 28 | Omittable<QStringList> heroes; //!< mxids used to form the room name |
| 29 | |
| 30 | bool isEmpty() const; |
| 31 | /// Merge the contents of another RoomSummary object into this one |
| 32 | /// \return true, if the current object has changed; false otherwise |
| 33 | bool merge(const RoomSummary& other); |
| 34 | }; |
| 35 | QDebug operator<<(QDebug dbg, const RoomSummary& rs); |
| 36 | |
| 37 | template <> |
| 38 | struct JsonObjectConverter<RoomSummary> { |
| 39 | static void dumpTo(QJsonObject& jo, const RoomSummary& rs); |
| 40 | static void fillFrom(const QJsonObject& jo, RoomSummary& rs); |
| 41 | }; |
| 42 | |
| 43 | /// Information on e2e device updates. Note: only present on an |
| 44 | /// incremental sync. |
| 45 | struct DevicesList { |
| 46 | /// List of users who have updated their device identity keys, or who |
| 47 | /// now share an encrypted room with the client since the previous |
| 48 | /// sync response. |
| 49 | QStringList changed; |
| 50 | |
| 51 | /// List of users with whom we do not share any encrypted rooms |
| 52 | /// any more since the previous sync response. |
| 53 | QStringList left; |
| 54 | }; |
| 55 | |
| 56 | QDebug operator<<(QDebug dhg, const DevicesList& devicesList); |
| 57 | |
| 58 | template <> |
| 59 | struct JsonObjectConverter<DevicesList> { |
| 60 | static void dumpTo(QJsonObject &jo, const DevicesList &dev); |
| 61 | static void fillFrom(const QJsonObject& jo, DevicesList& rs); |
| 62 | }; |
| 63 | |
| 64 | class QUOTIENT_API SyncRoomData { |
| 65 | public: |
| 66 | QString roomId; |
| 67 | JoinState joinState; |
| 68 | RoomSummary summary; |
| 69 | StateEvents state; |
| 70 | RoomEvents timeline; |
| 71 | Events ephemeral; |
| 72 | Events accountData; |
| 73 | |
| 74 | bool timelineLimited; |
| 75 | QString timelinePrevBatch; |
| 76 | Omittable<int> partiallyReadCount; |
| 77 | Omittable<int> unreadCount; |
| 78 | Omittable<int> highlightCount; |
| 79 | |
| 80 | SyncRoomData(QString roomId, JoinState joinState, |
| 81 | const QJsonObject& roomJson); |
| 82 | }; |
| 83 | |
| 84 | // QVector cannot work with non-copyable objects, std::vector can. |
| 85 | using SyncDataList = std::vector<SyncRoomData>; |
| 86 | |
| 87 | class SyncData { |
| 88 | public: |
| 89 | SyncData() = default; |
| 90 | explicit SyncData(const QString& cacheFileName); |
| 91 | //! Parse sync response into room events |
| 92 | //! \param json response from /sync or a room state cache |
| 93 | void parseJson(const QJsonObject& json, const QString& baseDir = {}); |
| 94 | |
| 95 | Events takePresenceData(); |
| 96 | Events takeAccountData(); |
| 97 | Events takeToDeviceEvents(); |
| 98 | const QHash<QString, int>& deviceOneTimeKeysCount() const |
| 99 | { |
| 100 | return deviceOneTimeKeysCount_; |
| 101 | } |
| 102 | SyncDataList takeRoomData(); |
| 103 | DevicesList takeDevicesList(); |
| 104 | |
| 105 | QString nextBatch() const { return nextBatch_; } |
| 106 | |
| 107 | QStringList unresolvedRooms() const { return unresolvedRoomIds; } |
| 108 | |
| 109 | static constexpr int MajorCacheVersion = 11; |
| 110 | static std::pair<int, int> cacheVersion(); |
| 111 | static QString fileNameForRoom(QString roomId); |
| 112 | |
| 113 | private: |
| 114 | QString nextBatch_; |
| 115 | Events presenceData; |
| 116 | Events accountData; |
| 117 | Events toDeviceEvents; |
| 118 | SyncDataList roomData; |
| 119 | QStringList unresolvedRoomIds; |
| 120 | QHash<QString, int> deviceOneTimeKeysCount_; |
| 121 | DevicesList devicesList; |
| 122 | |
| 123 | static QJsonObject loadJson(const QString& fileName); |
| 124 | }; |
| 125 | } // namespace Quotient |
| 126 | |