aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKitsune Ral <Kitsune-Ral@users.sf.net>2017-09-19 10:54:07 +0900
committerKitsune Ral <Kitsune-Ral@users.sf.net>2017-09-19 13:01:01 +0900
commitc5c26ff4a09eecaa6d8e1507087566ccf0fd96b4 (patch)
treec64b3c0b3bdbec6bf7c634a1f302c22b202c3861
parent95e6ae003e3f5ed806bc7adf4e10713cd4e35d1f (diff)
downloadlibquotient-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.cpp3
-rw-r--r--events/receiptevent.h2
-rw-r--r--room.cpp115
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";
};
diff --git a/room.cpp b/room.cpp
index 1393e145..241a885d 100644
--- a/room.cpp
+++ b/room.cpp
@@ -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();
}