Page MenuHomePhorge

D130.1732960222.diff
No OneTemporary

Size
9 KB
Referenced Files
None
Subscribers
None

D130.1732960222.diff

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
@@ -669,12 +669,12 @@
.xform(eventContent);
}
- /* lager::reader<RangeT<std::string>> */
- inline auto pinnedEvents() const {
- return state(KeyOfState{"m.room.pinned_events", ""})
- .xform(eventContent
- | jsonAtOr("pinned", immer::flex_vector<std::string>{}));
- }
+ /**
+ * Get pinned events of this room
+ *
+ * @return A lager::reader of RangeT of the pinned event ids.
+ */
+ auto pinnedEvents() const -> lager::reader<immer::flex_vector<std::string>>;
/**
* Set pinned events of this room
@@ -686,6 +686,24 @@
*/
PromiseT setPinnedEvents(immer::flex_vector<std::string> eventIds) const;
+ /**
+ * Add eventIds to the pinned events of this room
+ *
+ * @param eventIds The ids of events you want to add to the pinned events.
+ * @return A Promise that resolves when the state event
+ * for the pinned events change has been sent, or when there is an error.
+ */
+ PromiseT pinEvents(immer::flex_vector<std::string> eventIds) const;
+
+ /**
+ * Remove eventIds from the pinned events of this room
+ *
+ * @param eventIds The ids of events you want to remove from the pinned events.
+ * @return A Promise that resolves when the state event
+ * for the pinned events change has been sent, or when there is an error.
+ */
+ PromiseT unpinEvents(immer::flex_vector<std::string> eventIds) const;
+
/**
* Get the Gaps in the timeline for this room.
*
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
@@ -756,6 +756,12 @@
});
}
+ auto Room::pinnedEvents() const -> lager::reader<immer::flex_vector<std::string>>
+ {
+ return state(KeyOfState{"m.room.pinned_events", ""})
+ .xform(eventContent | jsonAtOr("pinned", immer::flex_vector<std::string>{}));
+ }
+
auto Room::setPinnedEvents(immer::flex_vector<std::string> eventIds) const
-> PromiseT
{
@@ -770,6 +776,38 @@
return sendStateEvent(e);
}
+ auto Room::pinEvents(immer::flex_vector<std::string> eventIds) const -> PromiseT
+ {
+ return m_ctx.createResolvedPromise({})
+ .then([room=toEventLoop(), eventIds](auto) {
+ auto curPinnedEvents = room.pinnedEvents().get();
+ auto newPinnedEvents = intoImmer(
+ curPinnedEvents,
+ zug::filter([curPinnedEvents](const auto &eventId) {
+ return std::find(curPinnedEvents.begin(), curPinnedEvents.end(), eventId) == curPinnedEvents.end();
+ }),
+ eventIds
+ );
+ return room.setPinnedEvents(newPinnedEvents);
+ });
+ }
+
+ auto Room::unpinEvents(immer::flex_vector<std::string> eventIds) const -> PromiseT
+ {
+ return m_ctx.createResolvedPromise({})
+ .then([room=toEventLoop(), eventIds](auto) {
+ auto curPinnedEvents = room.pinnedEvents().get();
+ auto newPinnedEvents = intoImmer(
+ immer::flex_vector<std::string>(),
+ zug::filter([eventIds](const auto &eventId) {
+ return std::find(eventIds.begin(), eventIds.end(), eventId) == eventIds.end();
+ }),
+ curPinnedEvents
+ );
+ return room.setPinnedEvents(newPinnedEvents);
+ });
+ }
+
auto Room::timelineEventIds() const -> lager::reader<immer::flex_vector<std::string>>
{
return roomCursor()[&RoomModel::timeline];
diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt
--- a/src/tests/CMakeLists.txt
+++ b/src/tests/CMakeLists.txt
@@ -84,6 +84,7 @@
client/room/undecrypted-events-test.cpp
client/encryption-benchmark-test.cpp
client/logout-test.cpp
+ client/room/pinned-events-test.cpp
EXTRA_LINK_LIBRARIES kazvclient kazveventemitter kazvjob client-test-lib kazvtestfixtures
EXTRA_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/client
)
diff --git a/src/tests/client/room/pinned-events-test.cpp b/src/tests/client/room/pinned-events-test.cpp
new file mode 100644
--- /dev/null
+++ b/src/tests/client/room/pinned-events-test.cpp
@@ -0,0 +1,140 @@
+/*
+ * This file is part of libkazv.
+ * SPDX-FileCopyrightText: 2024 tusooa <tusooa@kazv.moe>
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+#include <libkazv-config.hpp>
+#include <catch2/catch_test_macros.hpp>
+#include <lager/event_loop/boost_asio.hpp>
+#include <cprjobhandler.hpp>
+#include <lagerstoreeventemitter.hpp>
+#include <asio-promise-handler.hpp>
+#include "client-test-util.hpp"
+#include "client/action-mock-utils.hpp"
+#include "factory.hpp"
+
+using namespace Kazv;
+using namespace Kazv::Factory;
+
+TEST_CASE("Room::pinnedEvents()", "[client][room][getter]")
+{
+ WHEN("content is valid") {
+ auto room = makeRoom(withRoomState({
+ makeEvent(withEventType("m.room.pinned_events") | withEventContent(json{{"pinned", {"$1", "$2"}}})),
+ }));
+ auto client = makeClient(withRoom(room));
+ auto cursor = lager::make_constant(SdkModel{client});
+ auto nameCursor = lager::make_constant(room.roomId);
+ auto r = Room(cursor, nameCursor, dumbContext());
+ REQUIRE(r.pinnedEvents().get() == immer::flex_vector<std::string>{"$1", "$2"});
+ }
+
+ WHEN("content is invalid") {
+ auto room = makeRoom(withRoomState({
+ makeEvent(withEventType("m.room.pinned_events") | withEventContent(json{{"pinned", {"$1", "$2", 3}}})),
+ }));
+ auto client = makeClient(withRoom(room));
+ auto cursor = lager::make_constant(SdkModel{client});
+ auto nameCursor = lager::make_constant(room.roomId);
+ auto r = Room(cursor, nameCursor, dumbContext());
+ REQUIRE(r.pinnedEvents().get() == immer::flex_vector<std::string>{});
+ }
+
+ WHEN("there is no m.room.pinned_events in state") {
+ auto room = makeRoom();
+ auto client = makeClient(withRoom(room));
+ auto cursor = lager::make_constant(SdkModel{client});
+ auto nameCursor = lager::make_constant(room.roomId);
+ auto r = Room(cursor, nameCursor, dumbContext());
+ REQUIRE(r.pinnedEvents().get() == immer::flex_vector<std::string>{});
+ }
+}
+
+TEST_CASE("Room::pinEvents()", "[client][room][getter]")
+{
+ boost::asio::io_context io;
+ SingleTypePromiseInterface<EffectStatus> sgph{AsioPromiseHandler{io.get_executor()}};
+
+ auto room = makeRoom(withRoomState({
+ makeEvent(withEventType("m.room.pinned_events") | withEventContent(json{{"pinned", {"$1", "$2"}}})),
+ }));
+ ClientModel m = makeClient(withRoom(room));
+
+ auto jh = Kazv::CprJobHandler{io.get_executor()};
+ auto ee = Kazv::LagerStoreEventEmitter(lager::with_boost_asio_event_loop{io.get_executor()});
+
+ auto sdk = Kazv::makeSdk(
+ SdkModel{m},
+ jh,
+ ee,
+ Kazv::AsioPromiseHandler{io.get_executor()},
+ zug::identity
+ );
+ auto ctx = sdk.context();
+ auto dispatcher = getMockDispatcher(
+ sgph,
+ ctx,
+ returnEmpty<SendStateEventAction>()
+ );
+ auto mockContext = getMockContext(sgph, dispatcher);
+ auto client = Client(Client::InEventLoopTag{}, mockContext, sdk.context());
+ auto r = client.room(room.roomId);
+
+ r.pinEvents({"$2", "$3", "$0"})
+ .then([&](auto stat) {
+ REQUIRE(stat.success());
+ REQUIRE(dispatcher.template calledTimes<SendStateEventAction>() == 1);
+ auto action = dispatcher.template of<SendStateEventAction>()[0];
+ REQUIRE(action.roomId == room.roomId);
+ REQUIRE(action.event.content().get().at("pinned") == immer::flex_vector<std::string>{"$1", "$2", "$3", "$0"});
+
+ io.stop();
+ });
+
+ io.run();
+}
+
+TEST_CASE("Room::unpinEvents()", "[client][room][getter]")
+{
+ boost::asio::io_context io;
+ SingleTypePromiseInterface<EffectStatus> sgph{AsioPromiseHandler{io.get_executor()}};
+
+ auto room = makeRoom(withRoomState({
+ makeEvent(withEventType("m.room.pinned_events") | withEventContent(json{{"pinned", {"$1", "$2"}}})),
+ }));
+ ClientModel m = makeClient(withRoom(room));
+
+ auto jh = Kazv::CprJobHandler{io.get_executor()};
+ auto ee = Kazv::LagerStoreEventEmitter(lager::with_boost_asio_event_loop{io.get_executor()});
+
+ auto sdk = Kazv::makeSdk(
+ SdkModel{m},
+ jh,
+ ee,
+ Kazv::AsioPromiseHandler{io.get_executor()},
+ zug::identity
+ );
+ auto ctx = sdk.context();
+ auto dispatcher = getMockDispatcher(
+ sgph,
+ ctx,
+ returnEmpty<SendStateEventAction>()
+ );
+ auto mockContext = getMockContext(sgph, dispatcher);
+ auto client = Client(Client::InEventLoopTag{}, mockContext, sdk.context());
+ auto r = client.room(room.roomId);
+
+ r.unpinEvents({"$2", "$3", "$0"})
+ .then([&](auto stat) {
+ REQUIRE(stat.success());
+ REQUIRE(dispatcher.template calledTimes<SendStateEventAction>() == 1);
+ auto action = dispatcher.template of<SendStateEventAction>()[0];
+ REQUIRE(action.roomId == room.roomId);
+ REQUIRE(action.event.content().get().at("pinned") == immer::flex_vector<std::string>{"$1"});
+
+ io.stop();
+ });
+
+ io.run();
+}

File Metadata

Mime Type
text/plain
Expires
Sat, Nov 30, 1:50 AM (15 h, 23 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
41573
Default Alt Text
D130.1732960222.diff (9 KB)

Event Timeline