Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F62284111
D297.1775878978.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Award Token
Flag For Later
Size
5 KB
Referenced Files
None
Subscribers
None
D297.1775878978.diff
View Options
diff --git a/src/client/room/room-model.hpp b/src/client/room/room-model.hpp
--- a/src/client/room/room-model.hpp
+++ b/src/client/room/room-model.hpp
@@ -367,6 +367,16 @@
*/
bool isInTimeline(const std::string &eventId) const;
+
+ /**
+ * Check if an event has been read by the given user
+ *
+ * @param eventId eventId of the event to check
+ * @param userId userId of the given user
+ * @return true iff the event is read by the user
+ */
+ bool isReadBy(const std::string &eventId, const std::string &userId) const;
+
using Action = std::variant<
AddStateEventsAction,
MaybeAddStateEventsAction,
diff --git a/src/client/room/room-model.cpp b/src/client/room/room-model.cpp
--- a/src/client/room/room-model.cpp
+++ b/src/client/room/room-model.cpp
@@ -761,4 +761,11 @@
{
return !nonTimelineEvents.count(eventId) && messages.count(eventId);
}
+
+ bool RoomModel::isReadBy(const std::string &eventId, const std::string &userId) const
+ {
+ auto readReceiptAt = messages[readReceipts[userId].eventId];
+ auto event = messages[eventId];
+ return sortKeyForTimelineEvent(readReceiptAt) >= sortKeyForTimelineEvent(event);
+ }
}
diff --git a/src/client/room/room.hpp b/src/client/room/room.hpp
--- a/src/client/room/room.hpp
+++ b/src/client/room/room.hpp
@@ -812,6 +812,15 @@
*/
auto unreadNotificationEventIds() const -> lager::reader<immer::flex_vector<std::string>>;
+ /**
+ * Check if an event has been read by the given user
+ *
+ * @param eventId eventId of the event to check
+ * @param userId userId of the given user
+ * @return true iff the event is read by the user
+ */
+ bool isReadBy(const std::string &eventId, const std::string &userId);
+
private:
const lager::reader<SdkModel> &sdkCursor() const;
const lager::reader<RoomModel> &roomCursor() const;
diff --git a/src/client/room/room.cpp b/src/client/room/room.cpp
--- a/src/client/room/room.cpp
+++ b/src/client/room/room.cpp
@@ -944,4 +944,9 @@
{
return m_roomCursor[&RoomModel::unreadNotificationEventIds];
}
+
+ bool Room::isReadBy(const std::string &eventId, const std::string &userId)
+ {
+ return m_roomCursor.get().isReadBy(eventId, userId);
+ }
}
diff --git a/src/testfixtures/factory.hpp b/src/testfixtures/factory.hpp
--- a/src/testfixtures/factory.hpp
+++ b/src/testfixtures/factory.hpp
@@ -84,6 +84,7 @@
Event makeMemberEvent(const ComposedModifier<Event> &mod = {});
ComposedModifier<Event> withEventJson(const json &j);
ComposedModifier<Event> withEventKV(const json::json_pointer &k, const json &v);
+ ComposedModifier<Event> withEventTs(Timestamp ts);
ComposedModifier<Event> withEventId(std::string id);
ComposedModifier<Event> withEventType(std::string type);
ComposedModifier<Event> withEventContent(const json &content);
diff --git a/src/testfixtures/factory.cpp b/src/testfixtures/factory.cpp
--- a/src/testfixtures/factory.cpp
+++ b/src/testfixtures/factory.cpp
@@ -222,6 +222,11 @@
};
}
+ ComposedModifier<Event> withEventTs(Timestamp ts)
+ {
+ return withEventKV("/origin_server_ts"_json_pointer, ts);
+ }
+
ComposedModifier<Event> withEventId(std::string id)
{
return withEventKV("/event_id"_json_pointer, id);
diff --git a/src/tests/client/room/read-receipt-test.cpp b/src/tests/client/room/read-receipt-test.cpp
--- a/src/tests/client/room/read-receipt-test.cpp
+++ b/src/tests/client/room/read-receipt-test.cpp
@@ -408,3 +408,31 @@
REQUIRE(r.unreadNotificationEventIds().get()
== room.unreadNotificationEventIds);
}
+
+TEST_CASE("RoomModel::isReadBy", "[client][room][receipt]")
+{
+ auto room = makeRoom();
+ auto receiptEvent = makeEvent(
+ withEventType("m.receipt")
+ // https://spec.matrix.org/v1.8/client-server-api/#events-5
+ | withEventContent(R"({
+ "$Rqnc-F-dvnEYJTyHq_iKxU2bZ1CI92-kuZq3a5lr5Z2": {
+ "m.read": {
+ "@rikj:jki.re": {
+ "ts": 1145141919810
+ }
+ }
+ }
+ })"_json));
+ auto timeline = EventList{makeEvent(withEventTs(1436451550452) | withEventId("$Rqnc-F-dvnEYJTyHq_iKxU2bZ1CI92-kuZq3a5lr5Z0")),
+ makeEvent(withEventTs(1436451550453) | withEventId("$Rqnc-F-dvnEYJTyHq_iKxU2bZ1CI92-kuZq3a5lr5Z7")),
+ makeEvent(withEventTs(1436451550453) | withEventId("$Rqnc-F-dvnEYJTyHq_iKxU2bZ1CI92-kuZq3a5lr5Z2")),
+ makeEvent(withEventTs(1436451550454) | withEventId("$Rqnc-F-dvnEYJTyHq_iKxU2bZ1CI92-kuZq3a5lr5Z1"))
+ };
+ room = RoomModel::update(std::move(room), AddMessagesAction{timeline});
+ room = RoomModel::update(std::move(room), AddEphemeralAction({receiptEvent}));
+ REQUIRE(room.isReadBy("$Rqnc-F-dvnEYJTyHq_iKxU2bZ1CI92-kuZq3a5lr5Z0", "@rikj:jki.re") == true);
+ REQUIRE(room.isReadBy("$Rqnc-F-dvnEYJTyHq_iKxU2bZ1CI92-kuZq3a5lr5Z7", "@rikj:jki.re") == false);
+ REQUIRE(room.isReadBy("$Rqnc-F-dvnEYJTyHq_iKxU2bZ1CI92-kuZq3a5lr5Z2", "@rikj:jki.re") == true);
+ REQUIRE(room.isReadBy("$Rqnc-F-dvnEYJTyHq_iKxU2bZ1CI92-kuZq3a5lr5Z1", "@rikj:jki.re") == false);
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Apr 10, 8:42 PM (11 h, 52 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1305127
Default Alt Text
D297.1775878978.diff (5 KB)
Attached To
Mode
D297: Implement RoomModel::isReadBy
Attached
Detach File
Event Timeline
Log In to Comment