diff options
author | Kitsune Ral <Kitsune-Ral@users.sf.net> | 2017-09-19 10:54:07 +0900 |
---|---|---|
committer | Kitsune Ral <Kitsune-Ral@users.sf.net> | 2017-09-19 13:01:01 +0900 |
commit | c5c26ff4a09eecaa6d8e1507087566ccf0fd96b4 (patch) | |
tree | c64b3c0b3bdbec6bf7c634a1f302c22b202c3861 | |
parent | 95e6ae003e3f5ed806bc7adf4e10713cd4e35d1f (diff) | |
download | libquotient-c5c26ff4a09eecaa6d8e1507087566ccf0fd96b4.tar.gz libquotient-c5c26ff4a09eecaa6d8e1507087566ccf0fd96b4.zip |
Room: cache last read event and unread messages flag with the room state
Since there's no such thing as "unread messages flag" in the CS API spec, there's now a non-standard key-value in cached m.read receipts for that.
-rw-r--r-- | events/receiptevent.cpp | 3 | ||||
-rw-r--r-- | events/receiptevent.h | 2 | ||||
-rw-r--r-- | room.cpp | 115 |
3 files changed, 70 insertions, 50 deletions
diff --git a/events/receiptevent.cpp b/events/receiptevent.cpp index e3478cf1..3d6be9f1 100644 --- a/events/receiptevent.cpp +++ b/events/receiptevent.cpp @@ -46,7 +46,7 @@ ReceiptEvent::ReceiptEvent(const QJsonObject& obj) { Q_ASSERT(obj["type"].toString() == jsonType); - const QJsonObject contents = obj["content"].toObject(); + const QJsonObject contents = contentJson(); _eventsWithReceipts.reserve(static_cast<size_t>(contents.size())); for( auto eventIt = contents.begin(); eventIt != contents.end(); ++eventIt ) { @@ -66,5 +66,6 @@ ReceiptEvent::ReceiptEvent(const QJsonObject& obj) } _eventsWithReceipts.push_back({eventIt.key(), receipts}); } + _unreadMessages = obj["x-qmatrixclient.unread_messages"].toBool(); } diff --git a/events/receiptevent.h b/events/receiptevent.h index 1d280822..cbe36b10 100644 --- a/events/receiptevent.h +++ b/events/receiptevent.h @@ -41,9 +41,11 @@ namespace QMatrixClient EventsWithReceipts eventsWithReceipts() const { return _eventsWithReceipts; } + bool unreadMessages() const { return _unreadMessages; } private: EventsWithReceipts _eventsWithReceipts; + bool _unreadMessages; // Spec extension for caching purposes static constexpr const char * jsonType = "m.receipt"; }; @@ -789,6 +789,8 @@ void Room::processEphemeralEvent(Event* event) d->setLastReadEvent(m, p.evtId); } } + if (receiptEvent->unreadMessages()) + d->unreadMessages = true; break; } default: @@ -877,67 +879,81 @@ void Room::Private::updateDisplayname() emit q->displaynameChanged(q); } -QJsonObject Room::Private::toJson() const { - QJsonValue nowTimestamp { QDateTime::currentMSecsSinceEpoch() }; - QJsonArray stateEvents; - - QJsonObject nameEvent; - nameEvent.insert("type", QStringLiteral("m.room.name")); +QJsonObject stateEventToJson(const QString& type, const QString& name, + const QJsonValue& content) +{ + QJsonObject contentObj; + contentObj.insert(name, content); - QJsonObject nameEventContent; - nameEventContent.insert("name", this->name); + QJsonObject eventObj; + eventObj.insert("type", type); + eventObj.insert("content", contentObj); - nameEvent.insert("content", nameEventContent); - stateEvents.append(nameEvent); + return eventObj; +} - for (const auto &i : this->membersMap) { - QJsonObject content; - content.insert("membership", QStringLiteral("join")); - content.insert("displayname", i->displayname()); - // avatar URL is not available +QJsonObject Room::Private::toJson() const +{ + QJsonObject result; + { + QJsonArray stateEvents; - QJsonObject memberEvent; - memberEvent.insert("type", QStringLiteral("m.room.member")); - memberEvent.insert("sender", i->id()); - memberEvent.insert("state_key", i->id()); - memberEvent.insert("content", content); - memberEvent.insert("membership", QStringLiteral("join")); - memberEvent.insert("origin_server_ts", nowTimestamp); - stateEvents.append(memberEvent); - } + stateEvents.append(stateEventToJson("m.room.name", "name", name)); + stateEvents.append(stateEventToJson("m.room.topic", "topic", topic)); + stateEvents.append(stateEventToJson("m.room.aliases", "aliases", + QJsonArray::fromStringList(aliases))); + stateEvents.append(stateEventToJson("m.room.canonical_alias", "alias", + canonicalAlias)); - { - QJsonArray aliases; - for (const auto &i : this->aliases) { - aliases.append(QJsonValue(i)); + for (const auto &i : membersMap) + { + QJsonObject content; + content.insert("membership", QStringLiteral("join")); + content.insert("displayname", i->displayname()); + // avatar URL is not available + + QJsonObject memberEvent; + memberEvent.insert("type", QStringLiteral("m.room.member")); + memberEvent.insert("state_key", i->id()); + memberEvent.insert("content", content); + stateEvents.append(memberEvent); } - QJsonObject content; - content.insert("aliases", aliases); + QJsonObject roomStateObj; + roomStateObj.insert("events", stateEvents); - QJsonObject aliasEvent; - aliasEvent.insert("type", QStringLiteral("m.room.aliases")); - aliasEvent.insert("origin_server_ts", nowTimestamp); - aliasEvent.insert("content", content); - - stateEvents.append(aliasEvent); + result.insert("state", roomStateObj); } + if (!q->readMarkerEventId().isEmpty()) { - QJsonObject content; - content.insert("alias", this->canonicalAlias); - - QJsonObject canonicalAliasEvent; - canonicalAliasEvent.insert("type", QStringLiteral("m.room.canonical_alias")); - canonicalAliasEvent.insert("origin_server_ts", nowTimestamp); - stateEvents.append(canonicalAliasEvent); - } + QJsonArray ephemeralEvents; + { + // Don't dump the timestamp because it's useless in the cache. + QJsonObject user; + user.insert(connection->userId(), {}); + + QJsonObject receipt; + receipt.insert("m.read", user); + + QJsonObject lastReadEvent; + lastReadEvent.insert(q->readMarkerEventId(), receipt); + + QJsonObject receiptsObj; + receiptsObj.insert("type", QStringLiteral("m.receipt")); + receiptsObj.insert("content", lastReadEvent); + // In extension of the spec we add a hint to the receipt event + // to allow setting the unread indicator without downloading + // and analysing the timeline. + receiptsObj.insert("x-qmatrixclient.unread_messages", unreadMessages); + ephemeralEvents.append(receiptsObj); + } - QJsonObject roomStateObj; - roomStateObj.insert("events", stateEvents); + QJsonObject ephemeralObj; + ephemeralObj.insert("events", ephemeralEvents); - QJsonObject result; - result.insert("state", roomStateObj); + result.insert("ephemeral", ephemeralObj); + } QJsonObject unreadNotificationsObj; unreadNotificationsObj.insert("highlight_count", highlightCount); @@ -947,7 +963,8 @@ QJsonObject Room::Private::toJson() const { return result; } -QJsonObject Room::toJson() const { +QJsonObject Room::toJson() const +{ return d->toJson(); } |