aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/converters.h7
-rw-r--r--lib/events/receiptevent.cpp29
-rw-r--r--lib/events/receiptevent.h5
-rw-r--r--lib/room.cpp27
4 files changed, 40 insertions, 28 deletions
diff --git a/lib/converters.h b/lib/converters.h
index 2df18b03..d9a68bfb 100644
--- a/lib/converters.h
+++ b/lib/converters.h
@@ -134,7 +134,10 @@ struct JsonConverter<QString> : public TrivialJsonDumper<QString> {
template <>
struct JsonConverter<QDateTime> {
- static auto dump(const QDateTime& val) = delete; // not provided yet
+ static auto dump(const QDateTime& val)
+ {
+ return val.isValid() ? val.toMSecsSinceEpoch() : QJsonValue();
+ }
static auto load(const QJsonValue& jv)
{
return QDateTime::fromMSecsSinceEpoch(fromJson<qint64>(jv), Qt::UTC);
@@ -143,7 +146,7 @@ struct JsonConverter<QDateTime> {
template <>
struct JsonConverter<QDate> {
- static auto dump(const QDate& val) = delete; // not provided yet
+ static auto dump(const QDate& val) { return toJson(QDateTime(val)); }
static auto load(const QJsonValue& jv)
{
return fromJson<QDateTime>(jv).date();
diff --git a/lib/events/receiptevent.cpp b/lib/events/receiptevent.cpp
index 4185d92d..72dbf2e3 100644
--- a/lib/events/receiptevent.cpp
+++ b/lib/events/receiptevent.cpp
@@ -25,6 +25,27 @@ Example of a Receipt Event:
using namespace Quotient;
+// The library loads the event-ids-to-receipts JSON map into a vector because
+// map lookups are not used and vectors are massively faster. Same goes for
+// de-/serialization of ReceiptsForEvent::receipts.
+// (XXX: would this be generally preferred across CS API JSON maps?..)
+QJsonObject toJson(const EventsWithReceipts& ewrs)
+{
+ QJsonObject json;
+ for (const auto& e : ewrs) {
+ QJsonObject receiptsJson;
+ for (const auto& r : e.receipts)
+ receiptsJson.insert(r.userId,
+ QJsonObject { { "ts"_ls, toJson(r.timestamp) } });
+ json.insert(e.evtId, QJsonObject { { "m.read"_ls, receiptsJson } });
+ }
+ return json;
+}
+
+ReceiptEvent::ReceiptEvent(const EventsWithReceipts &ewrs)
+ : Event(typeId(), matrixTypeId(), toJson(ewrs))
+{}
+
EventsWithReceipts ReceiptEvent::eventsWithReceipts() const
{
EventsWithReceipts result;
@@ -39,14 +60,14 @@ EventsWithReceipts ReceiptEvent::eventsWithReceipts() const
}
const auto reads =
eventIt.value().toObject().value("m.read"_ls).toObject();
- QVector<Receipt> receipts;
- receipts.reserve(reads.size());
+ QVector<UserTimestamp> usersAtEvent;
+ usersAtEvent.reserve(reads.size());
for (auto userIt = reads.begin(); userIt != reads.end(); ++userIt) {
const auto user = userIt.value().toObject();
- receipts.push_back(
+ usersAtEvent.push_back(
{ userIt.key(), fromJson<QDateTime>(user["ts"_ls]) });
}
- result.push_back({ eventIt.key(), std::move(receipts) });
+ result.push_back({ eventIt.key(), std::move(usersAtEvent) });
}
return result;
}
diff --git a/lib/events/receiptevent.h b/lib/events/receiptevent.h
index 4feec9ea..9683deef 100644
--- a/lib/events/receiptevent.h
+++ b/lib/events/receiptevent.h
@@ -9,19 +9,20 @@
#include <QtCore/QVector>
namespace Quotient {
-struct Receipt {
+struct UserTimestamp {
QString userId;
QDateTime timestamp;
};
struct ReceiptsForEvent {
QString evtId;
- QVector<Receipt> receipts;
+ QVector<UserTimestamp> receipts;
};
using EventsWithReceipts = QVector<ReceiptsForEvent>;
class ReceiptEvent : public Event {
public:
DEFINE_EVENT_TYPEID("m.receipt", ReceiptEvent)
+ explicit ReceiptEvent(const EventsWithReceipts& ewrs);
explicit ReceiptEvent(const QJsonObject& obj) : Event(typeId(), obj) {}
EventsWithReceipts eventsWithReceipts() const;
diff --git a/lib/room.cpp b/lib/room.cpp
index 4d11878f..58950aac 100644
--- a/lib/room.cpp
+++ b/lib/room.cpp
@@ -2813,7 +2813,7 @@ Room::Changes Room::processEphemeralEvent(EventPtr&& event)
// are not supposed to move backwards. Otherwise, blindly store
// the event id for this user and update the read marker when/if
// the event is fetched later on.
- for (const Receipt& r : p.receipts)
+ for (const auto& r : p.receipts)
if (isMember(r.userId)) {
d->setLastReadReceipt(user(r.userId), newMarker,
{ p.evtId, r.timestamp });
@@ -3021,30 +3021,17 @@ QJsonObject Room::Private::toJson() const
{ QStringLiteral("events"), accountDataEvents } });
}
- if (const auto& readReceiptEventId =
- lastReadReceipts.value(q->localUser()).eventId;
- !readReceiptEventId.isEmpty()) //
+ if (const auto& readReceipt = q->lastReadReceipt(connection->userId());
+ !readReceipt.eventId.isEmpty()) //
{
- // Okay, that's a mouthful; but basically, it's simply placing an m.read
- // event in the 'ephemeral' section of the cached sync payload.
- // See also receiptevent.* and m.read example in the spec.
- // Only the local user's read receipt is saved - others' are really
- // considered ephemeral but this one is useful in understanding where
- // the user is in the timeline before any history is loaded.
result.insert(
QStringLiteral("ephemeral"),
QJsonObject {
{ QStringLiteral("events"),
- QJsonArray { QJsonObject {
- { TypeKey, ReceiptEvent::matrixTypeId() },
- { ContentKey,
- QJsonObject {
- { readReceiptEventId,
- QJsonObject {
- { QStringLiteral("m.read"),
- QJsonObject {
- { connection->userId(),
- QJsonObject {} } } } } } } } } } } });
+ QJsonArray { ReceiptEvent({ { readReceipt.eventId,
+ { { connection->userId(),
+ readReceipt.timestamp } } } })
+ .fullJson() } } });
}
QJsonObject unreadNotifObj { { SyncRoomData::UnreadCountKey,