aboutsummaryrefslogtreecommitdiff
path: root/lib/syncdata.h
blob: 6b70140d134b8604bd06e7bd303f8194f74a1861 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
// SPDX-FileCopyrightText: 2018 Kitsune Ral <kitsune-ral@users.sf.net>
// SPDX-License-Identifier: LGPL-2.1-or-later

#pragma once

#include "quotient_common.h"

#include "events/stateevent.h"

namespace Quotient {

constexpr auto UnreadNotificationsKey = "unread_notifications"_ls;
constexpr auto PartiallyReadCountKey = "x-quotient.since_fully_read_count"_ls;
constexpr auto NewUnreadCountKey = "org.matrix.msc2654.unread_count"_ls;
constexpr auto HighlightCountKey = "highlight_count"_ls;

/// Room summary, as defined in MSC688
/**
 * Every member of this structure is an Omittable; as per the MSC, only
 * changed values are sent from the server so if nothing is in the payload
 * the respective member will be omitted. In particular, `heroes.omitted()`
 * means that nothing has come from the server; heroes.value().isEmpty()
 * means a peculiar case of a room with the only member - the current user.
 */
struct QUOTIENT_API RoomSummary {
    Omittable<int> joinedMemberCount;
    Omittable<int> invitedMemberCount;
    Omittable<QStringList> heroes; //< mxids of users to take part in the room
                                   // name

    bool isEmpty() const;
    /// Merge the contents of another RoomSummary object into this one
    /// \return true, if the current object has changed; false otherwise
    bool merge(const RoomSummary& other);
};
QDebug operator<<(QDebug dbg, const RoomSummary& rs);

template <>
struct JsonObjectConverter<RoomSummary> {
    static void dumpTo(QJsonObject& jo, const RoomSummary& rs);
    static void fillFrom(const QJsonObject& jo, RoomSummary& rs);
};

/// Information on e2e device updates. Note: only present on an
/// incremental sync.
struct DevicesList {
    /// List of users who have updated their device identity keys, or who
    /// now share an encrypted room with the client since the previous
    /// sync response.
    QStringList changed;

    /// List of users with whom we do not share any encrypted rooms
    /// anymore since the previous sync response.
    QStringList left;
};

QDebug operator<<(QDebug dhg, const DevicesList& devicesList);

template <>
struct JsonObjectConverter<DevicesList> {
    static void dumpTo(QJsonObject &jo, const DevicesList &dev);
    static void fillFrom(const QJsonObject& jo, DevicesList& rs);
};

class SyncRoomData {
public:
    QString roomId;
    JoinState joinState;
    RoomSummary summary;
    StateEvents state;
    RoomEvents timeline;
    Events ephemeral;
    Events accountData;

    bool timelineLimited;
    QString timelinePrevBatch;
    Omittable<int> partiallyReadCount;
    Omittable<int> unreadCount;
    Omittable<int> highlightCount;

    SyncRoomData(QString roomId, JoinState joinState,
                 const QJsonObject& roomJson);
    SyncRoomData(SyncRoomData&&) = default;
    SyncRoomData& operator=(SyncRoomData&&) = default;
};

// QVector cannot work with non-copyable objects, std::vector can.
using SyncDataList = std::vector<SyncRoomData>;

class SyncData {
public:
    SyncData() = default;
    explicit SyncData(const QString& cacheFileName);
    /** Parse sync response into room events
     * \param json response from /sync or a room state cache
     * \return the list of rooms with missing cache files; always
     *         empty when parsing response from /sync
     */
    void parseJson(const QJsonObject& json, const QString& baseDir = {});

    Events&& takePresenceData();
    Events&& takeAccountData();
    Events&& takeToDeviceEvents();
    const QHash<QString, int>& deviceOneTimeKeysCount() const
    {
        return deviceOneTimeKeysCount_;
    }
    SyncDataList&& takeRoomData();
    DevicesList&& takeDevicesList();

    QString nextBatch() const { return nextBatch_; }

    QStringList unresolvedRooms() const { return unresolvedRoomIds; }

    static constexpr int MajorCacheVersion = 11;
    static std::pair<int, int> cacheVersion();
    static QString fileNameForRoom(QString roomId);

private:
    QString nextBatch_;
    Events presenceData;
    Events accountData;
    Events toDeviceEvents;
    SyncDataList roomData;
    QStringList unresolvedRoomIds;
    QHash<QString, int> deviceOneTimeKeysCount_;
    DevicesList devicesList;

    static QJsonObject loadJson(const QString& fileName);
};
} // namespace Quotient