Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F82478912
D245.1777850350.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Award Token
Flag For Later
Size
24 KB
Referenced Files
None
Subscribers
None
D245.1777850350.diff
View Options
diff --git a/src/client/room/local-draft.hpp b/src/client/room/local-draft.hpp
new file mode 100644
--- /dev/null
+++ b/src/client/room/local-draft.hpp
@@ -0,0 +1,41 @@
+/*
+ * This file is part of libkazv.
+ * SPDX-FileCopyrightText: 2026 nannanko <nannankokazv.moe>
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+#pragma once
+#include <libkazv-config.hpp>
+
+#include <cstdint>
+#include <string>
+
+#include <boost/serialization/split_free.hpp>
+#include <boost/serialization/version.hpp>
+
+namespace Kazv
+{
+ /**
+ * Local draft.
+ */
+ struct LocalDraft
+ {
+ std::string text;
+ std::string relType;
+ std::string relatedEventId;
+ friend bool operator==(const LocalDraft &a, const LocalDraft &b) = default;
+ friend bool operator!=(const LocalDraft &a, const LocalDraft &b) = default;
+ };
+
+ template<class Archive>
+ void serialize(Archive &ar, LocalDraft &draft, std::uint32_t const /*version*/)
+ {
+ ar
+ & draft.relType
+ & draft.relatedEventId
+ & draft.text
+ ;
+ }
+}
+
+BOOST_CLASS_VERSION(Kazv::LocalDraft, 0)
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
@@ -27,6 +27,7 @@
#include "push-rules-desc.hpp"
#include "local-echo.hpp"
#include "clientutil.hpp"
+#include "local-draft.hpp"
namespace Kazv
{
@@ -115,11 +116,35 @@
EventList events;
};
- struct SetLocalDraftAction
+ struct SetLocalDraftTextAction
{
std::string localDraft;
};
+ struct SetLocalDraftRelAction
+ {
+ std::string relType;
+ std::string relatedEventId;
+ };
+
+ struct SetLocalDraftAction
+ {
+ std::string text;
+ std::string relType;
+ std::string relatedEventId;
+ };
+
+ struct PushLocalDraftAction
+ {
+ std::string text;
+ std::string relType;
+ std::string relatedEventId;
+ };
+
+ struct PopLocalDraftAction
+ {
+ };
+
struct SetRoomEncryptionAction
{
};
@@ -256,7 +281,9 @@
immer::map<std::string, Event> ephemeral;
- std::string localDraft;
+ immer::flex_vector<LocalDraft> localDrafts{
+ Kazv::LocalDraft{"", "", ""}
+ };
bool encrypted{false};
/// a marker to indicate whether we need to rotate
@@ -386,7 +413,11 @@
ChangeMembershipAction,
ChangeInviteStateAction,
AddEphemeralAction,
+ SetLocalDraftTextAction,
+ SetLocalDraftRelAction,
SetLocalDraftAction,
+ PushLocalDraftAction,
+ PopLocalDraftAction,
SetRoomEncryptionAction,
MarkMembersFullyLoadedAction,
SetHeroIdsAction,
@@ -450,9 +481,13 @@
& r.timelineGaps
& r.ephemeral
-
- & r.localDraft
-
+ ;
+ if (version < 10) {
+ std::string oldVerLocalDraft;
+ ar & oldVerLocalDraft;
+ r.localDrafts = {LocalDraft{oldVerLocalDraft, "", ""}};
+ }
+ ar
& r.encrypted
& r.shouldRotateSessionKey
@@ -501,6 +536,9 @@
if (version >= 9) {
ar & r.nonTimelineEvents;
}
+ if (version >= 10) {
+ ar & r.localDrafts;
+ }
}
template<class Archive>
@@ -512,5 +550,5 @@
BOOST_CLASS_VERSION(Kazv::PendingRoomKeyEvent, 1)
BOOST_CLASS_VERSION(Kazv::ReadReceipt, 0)
-BOOST_CLASS_VERSION(Kazv::RoomModel, 9)
+BOOST_CLASS_VERSION(Kazv::RoomModel, 10)
BOOST_CLASS_VERSION(Kazv::RoomListModel, 0)
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
@@ -276,8 +276,55 @@
r.ephemeral = merge(std::move(r.ephemeral), a.events, keyOfEphemeral);
return r;
},
+ [&](SetLocalDraftTextAction a) {
+ r.localDrafts = r.localDrafts.update(0,
+ [&a](auto localDraft) {
+ localDraft.text = a.localDraft;
+ return localDraft;
+ });
+ return r;
+ },
+ [&](SetLocalDraftRelAction a) {
+ r.localDrafts = r.localDrafts.update(0,
+ [&a](auto localDraft) {
+ localDraft.relType = a.relType;
+ localDraft.relatedEventId = a.relatedEventId;
+ return localDraft;
+ });
+ return r;
+ },
[&](SetLocalDraftAction a) {
- r.localDraft = a.localDraft;
+ r.localDrafts = r.localDrafts.update(0,
+ [&a](auto localDraft) {
+ localDraft.text = a.text;
+ localDraft.relType = a.relType;
+ localDraft.relatedEventId = a.relatedEventId;
+ return localDraft;
+ });
+ return r;
+ },
+ [&](PushLocalDraftAction a) {
+ r.localDrafts = r.localDrafts.push_front({
+ a.text,
+ a.relType,
+ a.relatedEventId
+ });
+ return r;
+ },
+ [&](PopLocalDraftAction) {
+ r.localDrafts = r.localDrafts.drop(1);
+ if (r.localDrafts.size() == 0) {
+ r.localDrafts = r.localDrafts.push_back(LocalDraft {
+ "", "", ""
+ });
+ }
+ // If the current draft is not associated with any event,
+ // kazv cannot continue to pop the remaining drafts.
+ // Clear the remaining drafts here to avoid accumulation.
+ auto draft = r.localDrafts[0];
+ if (draft.relType == "" || draft.relatedEventId == "") {
+ r.localDrafts = {draft};
+ }
return r;
},
[&](SetRoomEncryptionAction) {
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
@@ -335,8 +335,8 @@
KAZV_WRAP_ATTR(RoomModel, roomCursor(), roomId);
/*lager::reader<RoomMembership>*/
KAZV_WRAP_ATTR(RoomModel, roomCursor(), membership);
- /*lager::reader<std::string>*/
- KAZV_WRAP_ATTR(RoomModel, roomCursor(), localDraft);
+ /*lager::reader<immer::flex_vector<Kazv::LocalDraft>>*/
+ KAZV_WRAP_ATTR(RoomModel, roomCursor(), localDrafts);
/* lager::reader<bool> */
KAZV_WRAP_ATTR(RoomModel, roomCursor(), membersFullyLoaded);
@@ -375,7 +375,7 @@
* Set local draft for this room.
*
* After the returned Promise is resolved,
- * @c localDraft() will contain @c localDraft .
+ * @c localDrafts() will contain @c localDrafts.
*
* @param localDraft The local draft to send.
* @return A Promise that resolves when the local draft
@@ -383,6 +383,61 @@
*/
PromiseT setLocalDraft(std::string localDraft) const;
+ /**
+ * Set current local draft and related event for this room.
+ *
+ * After the returned Promise is resolved,
+ * @c localDrafts() will contain @c localDrafts.
+ *
+ * @param text The local draft to send.
+ * @param relType Such as m.in_reply_to, refer to https://spec.matrix.org/
+ * @param relatedEventId The eventId related to the local draft.
+ * @return A Promise that resolves when the local draft
+ * has been set, or when there is an error.
+ */
+ PromiseT setLocalDraft(std::string text,
+ std::string relType, std::string relatedEventId) const;
+
+ /**
+ * Set event related to local draft for this room.
+ *
+ * After the returned Promise is resolved,
+ * @c localDrafts() will contain @c localDrafts.
+ *
+ * @param relType Such as m.in_reply_to, refer to https://spec.matrix.org/
+ * @param relatedEventId The eventId related to the local draft.
+ * @return A Promise that resolves when the event
+ * has been set, or when there is an error.
+ */
+ PromiseT setLocalDraftRel(std::string relType,
+ std::string relatedEventId) const;
+
+ /**
+ * Push a local draft and related event for this room.
+ *
+ * After the returned Promise is resolved,
+ * @c localDrafts() will contain @c localDrafts.
+ *
+ * @param text The local draft to send.
+ * @param relType Such as m.in_reply_to, refer to https://spec.matrix.org/
+ * @param relatedEventId The eventId related to the local draft.
+ * @return A Promise that resolves when the local draft
+ * has been set, or when there is an error.
+ */
+ PromiseT pushLocalDraft(std::string text,
+ std::string relType, std::string relatedEventId) const;
+
+ /**
+ * Pop a Kazv::LocalDraft in RoomModel::localDrafts.
+ *
+ * After the returned Promise is resolved,
+ * @c localDrafts() will contain @c localDrafts.
+ *
+ * @return A Promise that resolves when the local drafts
+ * has been popped, or when there is an error.
+ */
+ PromiseT popLocalDraft() const;
+
/**
* Send an event to 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
@@ -11,6 +11,7 @@
#include <debug.hpp>
#include "room.hpp"
+#include "sdk-model-cursor-tag.hpp"
namespace Kazv
{
@@ -320,7 +321,40 @@
-> PromiseT
{
using namespace CursorOp;
- return m_ctx.dispatch(UpdateRoomAction{+roomId(), SetLocalDraftAction{localDraft}});
+ return m_ctx.dispatch(UpdateRoomAction{
+ +roomId(), SetLocalDraftTextAction{localDraft}});
+ }
+
+ auto Room::setLocalDraft(std::string text,
+ std::string relType, std::string relatedEventId) const -> PromiseT
+ {
+ using namespace CursorOp;
+ return m_ctx.dispatch(UpdateRoomAction(
+ +roomId(), SetLocalDraftAction{text, relType, relatedEventId}
+ ));
+ }
+
+ auto Room::setLocalDraftRel(std::string relType,
+ std::string relatedEventId) const -> PromiseT
+ {
+ using namespace CursorOp;
+ return m_ctx.dispatch(UpdateRoomAction(
+ +roomId(), SetLocalDraftRelAction{relType, relatedEventId}));
+ }
+
+ auto Room::pushLocalDraft(std::string text,
+ std::string relType, std::string relatedEventId) const -> PromiseT
+ {
+ using namespace CursorOp;
+ return m_ctx.dispatch(UpdateRoomAction{+roomId(), PushLocalDraftAction{
+ text, relType, relatedEventId}});
+ }
+
+ auto Room::popLocalDraft() const -> PromiseT
+ {
+ using namespace CursorOp;
+ return m_ctx.dispatch(
+ UpdateRoomAction{+roomId(), PopLocalDraftAction{}});
}
auto Room::sendMessage(Event msg) const
diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt
--- a/src/tests/CMakeLists.txt
+++ b/src/tests/CMakeLists.txt
@@ -94,6 +94,7 @@
client/encode-test.cpp
client/maybe-add-save-events-trigger-benchmark-test.cpp
client/verification-processing-test.cpp
+ client/room/local-draft.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/local-draft.cpp b/src/tests/client/room/local-draft.cpp
new file mode 100644
--- /dev/null
+++ b/src/tests/client/room/local-draft.cpp
@@ -0,0 +1,268 @@
+/*
+ * This file is part of libkazv.
+ * SPDX-FileCopyrightText: 2026 nannanko <nannanko@kazv.moe>
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+#include <libkazv-config.hpp>
+
+#include "client/action-mock-utils.hpp"
+
+#include <promise-interface.hpp>
+#include <context.hpp>
+#include <asio-promise-handler.hpp>
+#include <cprjobhandler.hpp>
+#include <lagerstoreeventemitter.hpp>
+#include <factory.hpp>
+#include <sdk.hpp>
+#include <sdk-model.hpp>
+#include <client-model.hpp>
+#include <room/room-model.hpp>
+
+#include <catch2/catch_test_macros.hpp>
+#include <lager/event_loop/boost_asio.hpp>
+#include <boost/asio/io_context.hpp>
+
+#include <variant>
+
+TEST_CASE("Room::setLocalDraft(std::string)", "[client][room]")
+{
+ boost::asio::io_context io;
+ Kazv::SingleTypePromiseInterface<Kazv::EffectStatus> sgph{
+ Kazv::AsioPromiseHandler{io.get_executor()}
+ };
+
+ auto roomModel = Kazv::Factory::makeRoom();
+ auto clientModel = Kazv::Factory::makeClient(
+ Kazv::Factory::withRoom(roomModel));
+
+ auto jh = Kazv::CprJobHandler{io.get_executor()};
+ auto ee = Kazv::LagerStoreEventEmitter(
+ lager::with_boost_asio_event_loop{io.get_executor()});
+
+ auto sdk = Kazv::makeSdk(Kazv::SdkModel{clientModel}, jh, ee,
+ Kazv::AsioPromiseHandler{io.get_executor()}, zug::identity);
+ auto ctx = sdk.context();
+ auto dispatcher = getMockDispatcher(
+ sgph,
+ ctx,
+ passDown<Kazv::RoomListAction>()
+ );
+ auto mockContext = getMockContext(sgph, dispatcher);
+ auto client = Kazv::Client(Kazv::Client::InEventLoopTag{},
+ mockContext, sdk.context());
+ auto room = client.room(roomModel.roomId);
+
+ room.setLocalDraft("some draft")
+ .then([&](auto stat) {
+ REQUIRE(stat.success());
+ REQUIRE(dispatcher.template calledTimes<
+ Kazv::RoomListAction>() == 1);
+ auto action = dispatcher.template of<Kazv::RoomListAction>()[0];
+ REQUIRE(std::holds_alternative<Kazv::UpdateRoomAction>(action));
+ auto updateRoomAction = std::get<Kazv::UpdateRoomAction>(action);
+ REQUIRE(std::holds_alternative<Kazv::SetLocalDraftTextAction>(
+ updateRoomAction.roomAction));
+ REQUIRE(updateRoomAction.roomId == roomModel.roomId);
+ auto setLocalDraftTextAction = std::get<
+ Kazv::SetLocalDraftTextAction>(updateRoomAction.roomAction);
+ REQUIRE(setLocalDraftTextAction.localDraft == "some draft");
+ io.stop();
+ });
+
+ io.run();
+}
+
+TEST_CASE("Room::setLocalDraft(std::string, std::string, std::string)", "[client][room]")
+{
+ boost::asio::io_context io;
+ Kazv::SingleTypePromiseInterface<Kazv::EffectStatus> sgph{
+ Kazv::AsioPromiseHandler{io.get_executor()}
+ };
+
+ auto roomModel = Kazv::Factory::makeRoom();
+ auto clientModel = Kazv::Factory::makeClient(
+ Kazv::Factory::withRoom(roomModel));
+
+ auto jh = Kazv::CprJobHandler{io.get_executor()};
+ auto ee = Kazv::LagerStoreEventEmitter(
+ lager::with_boost_asio_event_loop{io.get_executor()});
+
+ auto sdk = Kazv::makeSdk(Kazv::SdkModel{clientModel}, jh, ee,
+ Kazv::AsioPromiseHandler{io.get_executor()}, zug::identity);
+ auto ctx = sdk.context();
+ auto dispatcher = getMockDispatcher(
+ sgph,
+ ctx,
+ passDown<Kazv::RoomListAction>()
+ );
+ auto mockContext = getMockContext(sgph, dispatcher);
+ auto client = Kazv::Client(Kazv::Client::InEventLoopTag{},
+ mockContext, sdk.context());
+ auto room = client.room(roomModel.roomId);
+
+ room.setLocalDraft("some draft", "m.reply", "$0")
+ .then([&](auto stat) {
+ REQUIRE(stat.success());
+ REQUIRE(dispatcher.template calledTimes<
+ Kazv::RoomListAction>() == 1);
+ auto action = dispatcher.template of<Kazv::RoomListAction>()[0];
+ REQUIRE(std::holds_alternative<Kazv::UpdateRoomAction>(action));
+ auto updateRoomAction = std::get<Kazv::UpdateRoomAction>(action);
+ REQUIRE(updateRoomAction.roomId == roomModel.roomId);
+ REQUIRE(std::holds_alternative<Kazv::SetLocalDraftAction>(
+ updateRoomAction.roomAction));
+ auto setLocalDraftAction = std::get<
+ Kazv::SetLocalDraftAction>(updateRoomAction.roomAction);
+ REQUIRE(setLocalDraftAction.text == "some draft");
+ REQUIRE(setLocalDraftAction.relType == "m.reply");
+ REQUIRE(setLocalDraftAction.relatedEventId == "$0");
+ io.stop();
+ });
+
+ io.run();
+}
+
+TEST_CASE("Room::setLocalDraftRel(std::string, std::string)", "[client][room]")
+{
+ boost::asio::io_context io;
+ Kazv::SingleTypePromiseInterface<Kazv::EffectStatus> sgph{
+ Kazv::AsioPromiseHandler{io.get_executor()}
+ };
+
+ auto roomModel = Kazv::Factory::makeRoom();
+ auto clientModel = Kazv::Factory::makeClient(
+ Kazv::Factory::withRoom(roomModel));
+
+ auto jh = Kazv::CprJobHandler{io.get_executor()};
+ auto ee = Kazv::LagerStoreEventEmitter(
+ lager::with_boost_asio_event_loop{io.get_executor()});
+
+ auto sdk = Kazv::makeSdk(Kazv::SdkModel{clientModel}, jh, ee,
+ Kazv::AsioPromiseHandler{io.get_executor()}, zug::identity);
+ auto ctx = sdk.context();
+ auto dispatcher = getMockDispatcher(
+ sgph,
+ ctx,
+ passDown<Kazv::RoomListAction>()
+ );
+ auto mockContext = getMockContext(sgph, dispatcher);
+ auto client = Kazv::Client(Kazv::Client::InEventLoopTag{},
+ mockContext, sdk.context());
+ auto room = client.room(roomModel.roomId);
+
+ room.setLocalDraftRel("m.reply", "$0")
+ .then([&](auto stat) {
+ REQUIRE(stat.success());
+ REQUIRE(dispatcher.template calledTimes<
+ Kazv::RoomListAction>() == 1);
+ auto action = dispatcher.template of<Kazv::RoomListAction>()[0];
+ REQUIRE(std::holds_alternative<Kazv::UpdateRoomAction>(action));
+ auto updateRoomAction = std::get<Kazv::UpdateRoomAction>(action);
+ REQUIRE(updateRoomAction.roomId == roomModel.roomId);
+ REQUIRE(std::holds_alternative<Kazv::SetLocalDraftRelAction>(
+ updateRoomAction.roomAction));
+ auto setLocalDraftRelAction = std::get<
+ Kazv::SetLocalDraftRelAction>(updateRoomAction.roomAction);
+ REQUIRE(setLocalDraftRelAction.relType == "m.reply");
+ REQUIRE(setLocalDraftRelAction.relatedEventId == "$0");
+ io.stop();
+ });
+
+ io.run();
+}
+
+TEST_CASE("Room::pushLocalDraft(std::string, std::string, std::string)", "[client][room]")
+{
+ boost::asio::io_context io;
+ Kazv::SingleTypePromiseInterface<Kazv::EffectStatus> sgph{
+ Kazv::AsioPromiseHandler{io.get_executor()}
+ };
+
+ auto roomModel = Kazv::Factory::makeRoom();
+ auto clientModel = Kazv::Factory::makeClient(
+ Kazv::Factory::withRoom(roomModel));
+
+ auto jh = Kazv::CprJobHandler{io.get_executor()};
+ auto ee = Kazv::LagerStoreEventEmitter(
+ lager::with_boost_asio_event_loop{io.get_executor()});
+
+ auto sdk = Kazv::makeSdk(Kazv::SdkModel{clientModel}, jh, ee,
+ Kazv::AsioPromiseHandler{io.get_executor()}, zug::identity);
+ auto ctx = sdk.context();
+ auto dispatcher = getMockDispatcher(
+ sgph,
+ ctx,
+ passDown<Kazv::RoomListAction>()
+ );
+ auto mockContext = getMockContext(sgph, dispatcher);
+ auto client = Kazv::Client(Kazv::Client::InEventLoopTag{},
+ mockContext, sdk.context());
+ auto room = client.room(roomModel.roomId);
+
+ room.pushLocalDraft("some draft", "m.reply", "$0")
+ .then([&](auto stat) {
+ REQUIRE(stat.success());
+ REQUIRE(dispatcher.template calledTimes<
+ Kazv::RoomListAction>() == 1);
+ auto action = dispatcher.template of<Kazv::RoomListAction>()[0];
+ REQUIRE(std::holds_alternative<Kazv::UpdateRoomAction>(action));
+ auto updateRoomAction = std::get<Kazv::UpdateRoomAction>(action);
+ REQUIRE(updateRoomAction.roomId == roomModel.roomId);
+ REQUIRE(std::holds_alternative<Kazv::PushLocalDraftAction>(
+ updateRoomAction.roomAction));
+ auto pushLocalDraftAction = std::get<
+ Kazv::PushLocalDraftAction>(updateRoomAction.roomAction);
+ REQUIRE(pushLocalDraftAction.text == "some draft");
+ REQUIRE(pushLocalDraftAction.relType == "m.reply");
+ REQUIRE(pushLocalDraftAction.relatedEventId == "$0");
+ io.stop();
+ });
+
+ io.run();
+}
+
+TEST_CASE("Room::popLocalDraft()", "[client][room]")
+{
+ boost::asio::io_context io;
+ Kazv::SingleTypePromiseInterface<Kazv::EffectStatus> sgph{
+ Kazv::AsioPromiseHandler{io.get_executor()}
+ };
+
+ auto roomModel = Kazv::Factory::makeRoom();
+ auto clientModel = Kazv::Factory::makeClient(
+ Kazv::Factory::withRoom(roomModel));
+
+ auto jh = Kazv::CprJobHandler{io.get_executor()};
+ auto ee = Kazv::LagerStoreEventEmitter(
+ lager::with_boost_asio_event_loop{io.get_executor()});
+
+ auto sdk = Kazv::makeSdk(Kazv::SdkModel{clientModel}, jh, ee,
+ Kazv::AsioPromiseHandler{io.get_executor()}, zug::identity);
+ auto ctx = sdk.context();
+ auto dispatcher = getMockDispatcher(
+ sgph,
+ ctx,
+ passDown<Kazv::RoomListAction>()
+ );
+ auto mockContext = getMockContext(sgph, dispatcher);
+ auto client = Kazv::Client(Kazv::Client::InEventLoopTag{},
+ mockContext, sdk.context());
+ auto room = client.room(roomModel.roomId);
+
+ room.popLocalDraft()
+ .then([&](auto stat) {
+ REQUIRE(stat.success());
+ REQUIRE(dispatcher.template calledTimes<
+ Kazv::RoomListAction>() == 1);
+ auto action = dispatcher.template of<Kazv::RoomListAction>()[0];
+ REQUIRE(std::holds_alternative<Kazv::UpdateRoomAction>(action));
+ auto updateRoomAction = std::get<Kazv::UpdateRoomAction>(action);
+ REQUIRE(updateRoomAction.roomId == roomModel.roomId);
+ REQUIRE(std::holds_alternative<Kazv::PopLocalDraftAction>(
+ updateRoomAction.roomAction));
+ io.stop();
+ });
+
+ io.run();
+}
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
@@ -141,3 +141,72 @@
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");
}
+
+TEST_CASE("SetLocalDraftTextAction", "[client][room]")
+{
+ RoomModel r;
+
+ auto res = RoomModel::update(r, SetLocalDraftTextAction("some draft"));
+
+ REQUIRE(res.localDrafts.front().text == "some draft");
+}
+
+TEST_CASE("SetLocalDraftRelAction", "[client][room]")
+{
+ RoomModel r;
+
+ auto res = RoomModel::update(r,
+ SetLocalDraftRelAction("m.replace", "$eventid"));
+
+ REQUIRE(res.localDrafts.front().text == "");
+ REQUIRE(res.localDrafts.front().relType == "m.replace");
+ REQUIRE(res.localDrafts.front().relatedEventId == "$eventid");
+}
+
+TEST_CASE("SetLocalDraftAction", "[client][room]")
+{
+ RoomModel r;
+
+ auto res = RoomModel::update(r,
+ SetLocalDraftAction("some draft", "m.replace", "$eventid"));
+
+ REQUIRE(res.localDrafts.front().text == "some draft");
+ REQUIRE(res.localDrafts.front().relType == "m.replace");
+ REQUIRE(res.localDrafts.front().relatedEventId == "$eventid");
+}
+
+TEST_CASE("pushLocalDraftAction", "[client][room]")
+{
+ RoomModel r;
+
+ auto res = RoomModel::update(r,
+ PushLocalDraftAction("some draft", "m.replace", "$eventid"));
+
+ REQUIRE(res.localDrafts.size() == 2);
+ REQUIRE(res.localDrafts.front().text == "some draft");
+ REQUIRE(res.localDrafts.front().relType == "m.replace");
+ REQUIRE(res.localDrafts.front().relatedEventId == "$eventid");
+}
+
+TEST_CASE("popLocalDraftAction", "[client][room]")
+{
+ RoomModel r;
+
+ auto res = RoomModel::update(r,
+ PushLocalDraftAction("some draft", "m.replace", "$eventid"));
+
+ REQUIRE(res.localDrafts.size() == 2);
+ REQUIRE(res.localDrafts.front().text == "some draft");
+ REQUIRE(res.localDrafts.front().relType == "m.replace");
+ REQUIRE(res.localDrafts.front().relatedEventId == "$eventid");
+
+ res = RoomModel::update(r, PopLocalDraftAction{});
+ REQUIRE(res.localDrafts.size() == 1);
+ REQUIRE(res.localDrafts.front().text == "");
+ REQUIRE(res.localDrafts.front().relType == "");
+ REQUIRE(res.localDrafts.front().relatedEventId == "");
+
+ // The size of localDrafts is at least 1
+ res = RoomModel::update(r, PopLocalDraftAction{});
+ REQUIRE(res.localDrafts.size() == 1);
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, May 3, 4:19 PM (12 h, 49 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1437959
Default Alt Text
D245.1777850350.diff (24 KB)
Attached To
Mode
D245: Restore draft after editing
Attached
Detach File
Event Timeline
Log In to Comment