Page MenuHomePhorge

D85.1732340075.diff
No OneTemporary

Size
7 KB
Referenced Files
None
Subscribers
None

D85.1732340075.diff

diff --git a/src/client/actions/paginate.cpp b/src/client/actions/paginate.cpp
--- a/src/client/actions/paginate.cpp
+++ b/src/client/actions/paginate.cpp
@@ -66,18 +66,34 @@
try {
// kzo.client.dbg() << "We got " << chunk.size() << " events here" << std::endl;
auto room = m.roomList.at(roomId);
- immer::flex_vector_transient<Event> events{};
// The timeline from paginate backwards is returned
// in reversed order, so restore the order.
- zug::into(events, zug::reversed, chunk);
+ auto events = intoImmer(EventList{}, zug::reversed, chunk);
AddToTimelineAction action
- {events.persistent(), paginateBackToken, std::nullopt, gapEventId};
+ {events, paginateBackToken, std::nullopt, gapEventId};
m.roomList = RoomListModel::update(
std::move(m.roomList),
UpdateRoomAction{roomId, action});
+ m.roomList = RoomListModel::update(
+ std::move(m.roomList),
+ UpdateRoomAction{roomId, MaybeAddStateEventsAction{
+ intoImmer(EventList{},
+ zug::filter(&Event::isState),
+ events)
+ }});
+
+ // r.state() contains state events prior to the timeline
+ // we add them later than the timeline, so the states in the
+ // timeline takes priority
+ m.roomList = RoomListModel::update(
+ std::move(m.roomList),
+ UpdateRoomAction{roomId, MaybeAddStateEventsAction{
+ r.state()
+ }});
+
m.addTrigger(PaginateSuccessful{roomId});
return { std::move(m), lager::noop };
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
@@ -65,6 +65,14 @@
immer::flex_vector<Event> stateEvents;
};
+ /// Go from the back of stateEvents to the beginning,
+ /// adding the event to room state only if the room
+ /// has no state event with that state key.
+ struct MaybeAddStateEventsAction
+ {
+ immer::flex_vector<Event> stateEvents;
+ };
+
struct AddToTimelineAction
{
/// Events from oldest to latest
@@ -284,6 +292,7 @@
using Action = std::variant<
AddStateEventsAction,
+ MaybeAddStateEventsAction,
AddToTimelineAction,
AddAccountDataAction,
ChangeMembershipAction,
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
@@ -1,6 +1,6 @@
/*
* This file is part of libkazv.
- * SPDX-FileCopyrightText: 2020-2023 tusooa
+ * SPDX-FileCopyrightText: 2020-2024 tusooa <tusooa@kazv.moe>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
@@ -72,6 +72,18 @@
}
return r;
},
+ [&](MaybeAddStateEventsAction a) {
+ for (auto it = a.stateEvents.rbegin();
+ it != a.stateEvents.rend();
+ ++it) {
+ const auto &e = *it;
+ auto k = keyOfState(e);
+ if (!r.stateEvents.count(k)) {
+ r.stateEvents = std::move(r.stateEvents).set(k, e);
+ }
+ }
+ return r;
+ },
[&](AddToTimelineAction a) {
auto eventIds = intoImmer(immer::flex_vector<std::string>(),
zug::map(keyOfTimeline), a.events);
diff --git a/src/tests/client/paginate-test.cpp b/src/tests/client/paginate-test.cpp
--- a/src/tests/client/paginate-test.cpp
+++ b/src/tests/client/paginate-test.cpp
@@ -14,7 +14,7 @@
#include <cursorutil.hpp>
#include <sdk-model.hpp>
#include <client/client.hpp>
-
+#include <client/actions/paginate.hpp>
#include "client-test-util.hpp"
#include "factory.hpp"
#include <iostream>
@@ -88,6 +88,36 @@
"age": 1234
}
}
+ ],
+ "state": [
+ {
+ "content": {
+ "name": "The original room name"
+ },
+ "type": "m.room.name",
+ "event_id": "$some:example.org",
+ "room_id": "!foo:example.org",
+ "sender": "@example:example.org",
+ "origin_server_ts": 1432735824653,
+ "unsigned": {
+ "age": 1234
+ },
+ "state_key": ""
+ },
+ {
+ "content": {
+ "membership": "join"
+ },
+ "type": "m.room.member",
+ "event_id": "$some-1:example.org",
+ "room_id": "!foo:example.org",
+ "sender": "@example:example.org",
+ "origin_server_ts": 1432735824653,
+ "unsigned": {
+ "age": 1234
+ },
+ "state_key": "@example:example.org"
+ }
]
})"_json;
@@ -258,3 +288,27 @@
REQUIRE(! timelineGaps.find("$event1:example.org"));
}
+
+TEST_CASE("paginating should add the state events to room state", "[client][paginate]")
+{
+ ClientModel m = makeClient(
+ withRoom(makeRoom(
+ withRoomId("!foo:example.org")
+ | withRoomTimeline({event1, event2})
+ | withRoomTimelineGaps({{event1.id(), "prevBatchForEvent1"}})
+ ))
+ );
+
+ auto resp = makeResponse(
+ "GetRoomEvents",
+ withResponseJsonBody(paginateResponseJson)
+ | withResponseDataKV("roomId", "!foo:example.org")
+ | withResponseDataKV("gapEventId", "$event1:example.org")
+ );
+
+ auto [next, _] = processResponse(m, GetRoomEventsResponse(resp));
+ auto r = next.roomList.rooms["!foo:example.org"];
+
+ REQUIRE(r.stateEvents[KeyOfState{"m.room.name", ""}].content().get().at("name") == "The room name");
+ REQUIRE(r.stateEvents[KeyOfState{"m.room.member", "@example:example.org"}].content().get().at("membership") == "join");
+}
diff --git a/src/tests/client/room/room-actions-test.cpp b/src/tests/client/room/room-actions-test.cpp
--- a/src/tests/client/room/room-actions-test.cpp
+++ b/src/tests/client/room/room-actions-test.cpp
@@ -1,6 +1,6 @@
/*
* This file is part of libkazv.
- * SPDX-FileCopyrightText: 2021 Tusooa Zhu <tusooa@kazv.moe>
+ * SPDX-FileCopyrightText: 2021-2024 tusooa <tusooa@kazv.moe>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
@@ -9,8 +9,10 @@
#include <catch2/catch_all.hpp>
#include <room/room-model.hpp>
+#include <testfixtures/factory.hpp>
using namespace Kazv;
+using namespace Kazv::Factory;
TEST_CASE("SetHeroIdsAction", "[client][room]")
{
@@ -118,3 +120,24 @@
REQUIRE(res.messages[eventId].content().get() == json::object());
REQUIRE(res.messages[eventId].redacted());
}
+
+TEST_CASE("MaybeAddStateEventsAction", "[client][room]")
+{
+ auto r = makeRoom(withRoomState({
+ makeEvent(withEventType("m.room.member") | withStateKey("@foo:example.com") | withEventContent(json{{"membership", "join"}})),
+ }));
+
+ auto next = RoomModel::update(r, MaybeAddStateEventsAction{{
+ // already exists, should not add
+ makeEvent(withEventType("m.room.member") | withStateKey("@foo:example.com") | withEventContent(json{{"membership", "leave"}})),
+ // does not exist yet but the one below should be used
+ makeEvent(withEventType("m.room.member") | withStateKey("@bar:example.com") | withEventContent(json{{"membership", "leave"}})),
+ // does not exist, should add
+ makeEvent(withEventType("m.room.member") | withStateKey("@bar:example.com") | withEventContent(json{{"membership", "join"}})),
+ }});
+
+ REQUIRE(next.stateEvents.count(KeyOfState{"m.room.member", "@foo:example.com"}));
+ REQUIRE(next.stateEvents[KeyOfState{"m.room.member", "@foo:example.com"}].content().get()["membership"] == "join");
+ REQUIRE(next.stateEvents.count(KeyOfState{"m.room.member", "@bar:example.com"}));
+ REQUIRE(next.stateEvents[KeyOfState{"m.room.member", "@bar:example.com"}].content().get()["membership"] == "join");
+}

File Metadata

Mime Type
text/plain
Expires
Fri, Nov 22, 9:34 PM (21 m, 16 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
39116
Default Alt Text
D85.1732340075.diff (7 KB)

Event Timeline