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
132
|
#pragma once
#include <limits>
#include <string>
#include <QCache>
#include <QObject>
#include <QVariant>
#include <qhashfunctions.h>
#include <mtx/events/collections.hpp>
#include <mtx/responses/messages.hpp>
#include <mtx/responses/sync.hpp>
#include "Reaction.h"
class EventStore : public QObject
{
Q_OBJECT
public:
EventStore(std::string room_id, QObject *parent);
struct Index
{
std::string room;
uint64_t idx;
friend uint qHash(const Index &i, uint seed = 0) noexcept
{
QtPrivate::QHashCombine hash;
seed = hash(seed, QByteArray::fromRawData(i.room.data(), i.room.size()));
seed = hash(seed, i.idx);
return seed;
}
friend bool operator==(const Index &a, const Index &b) noexcept
{
return a.idx == b.idx && a.room == b.room;
}
};
struct IdIndex
{
std::string room, id;
friend uint qHash(const IdIndex &i, uint seed = 0) noexcept
{
QtPrivate::QHashCombine hash;
seed = hash(seed, QByteArray::fromRawData(i.room.data(), i.room.size()));
seed = hash(seed, QByteArray::fromRawData(i.id.data(), i.id.size()));
return seed;
}
friend bool operator==(const IdIndex &a, const IdIndex &b) noexcept
{
return a.id == b.id && a.room == b.room;
}
};
void fetchMore();
void handleSync(const mtx::responses::Timeline &events);
// optionally returns the event or nullptr and fetches it, after which it emits a
// relatedFetched event
mtx::events::collections::TimelineEvents *get(std::string_view id,
std::string_view related_to,
bool decrypt = true);
// always returns a proper event as long as the idx is valid
mtx::events::collections::TimelineEvents *get(int idx, bool decrypt = true);
QVariantList reactions(const std::string &event_id);
int size() const
{
return last != std::numeric_limits<uint64_t>::max()
? static_cast<int>(last - first) + 1
: 0;
}
int toExternalIdx(uint64_t idx) const { return static_cast<int>(idx - first); }
uint64_t toInternalIdx(int idx) const { return first + idx; }
std::optional<int> idToIndex(std::string_view id) const;
std::optional<std::string> indexToId(int idx) const;
signals:
void beginInsertRows(int from, int to);
void endInsertRows();
void beginResetModel();
void endResetModel();
void dataChanged(int from, int to);
void newEncryptedImage(mtx::crypto::EncryptedFile encryptionInfo);
void eventFetched(std::string id,
std::string relatedTo,
mtx::events::collections::TimelineEvents timeline);
void oldMessagesRetrieved(const mtx::responses::Messages &);
void fetchedMore();
void processPending();
void messageSent(std::string txn_id, std::string event_id);
void messageFailed(std::string txn_id);
void startDMVerification(
mtx::events::RoomEvent<mtx::events::msg::KeyVerificationRequest> &msg);
void updateFlowEventId(std::string event_id);
public slots:
void addPending(mtx::events::collections::TimelineEvents event);
void clearTimeline();
private:
mtx::events::collections::TimelineEvents *decryptEvent(
const IdIndex &idx,
const mtx::events::EncryptedEvent<mtx::events::msg::Encrypted> &e);
void handle_room_verification(mtx::events::collections::TimelineEvents event);
std::string room_id_;
uint64_t first = std::numeric_limits<uint64_t>::max(),
last = std::numeric_limits<uint64_t>::max();
static QCache<IdIndex, mtx::events::collections::TimelineEvents> decryptedEvents_;
static QCache<Index, mtx::events::collections::TimelineEvents> events_;
static QCache<IdIndex, mtx::events::collections::TimelineEvents> events_by_id_;
std::string current_txn;
int current_txn_error_count = 0;
// probably not the best way to do
std::optional<mtx::events::RoomEvent<mtx::events::msg::KeyVerificationRequest>>
last_verification_request_event;
mtx::events::RoomEvent<mtx::events::msg::KeyVerificationCancel>
last_verification_cancel_event;
};
|