From eecba5196c89863332d6789f6f84395c17451d7f Mon Sep 17 00:00:00 2001 From: James Graham Date: Fri, 4 Oct 2024 18:41:27 +0100 Subject: [PATCH 1/4] Support event relations on all post message functions --- Quotient/room.cpp | 23 +++++++++++++---------- Quotient/room.h | 12 +++++++----- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/Quotient/room.cpp b/Quotient/room.cpp index e48e20736..d963655fd 100644 --- a/Quotient/room.cpp +++ b/Quotient/room.cpp @@ -2121,27 +2121,28 @@ void Room::discardMessage(const QString& txnId) emit pendingEventDiscarded(); } -QString Room::postMessage(const QString& plainText, MessageEventType type) +QString Room::postMessage(const QString& plainText, MessageEventType type, std::optional relatesTo) { - return post(plainText, type)->transactionId(); + return post(plainText, type, nullptr, relatesTo)->transactionId(); } -QString Room::postPlainText(const QString& plainText) +QString Room::postPlainText(const QString& plainText, std::optional relatesTo) { - return postMessage(plainText, MessageEventType::Text); + return postMessage(plainText, MessageEventType::Text, relatesTo); } QString Room::postHtmlMessage(const QString& plainText, const QString& html, - MessageEventType type) + MessageEventType type, std::optional relatesTo) { return post(plainText, type, - std::make_unique(html, u"text/html"_s)) + std::make_unique(html, u"text/html"_s), + relatesTo) ->transactionId(); } -QString Room::postHtmlText(const QString& plainText, const QString& html) +QString Room::postHtmlText(const QString& plainText, const QString& html, std::optional relatesTo) { - return postHtmlMessage(plainText, html); + return postHtmlMessage(plainText, html, MessageEventType::Text, relatesTo); } QString Room::postReaction(const QString& eventId, const QString& key) @@ -2198,7 +2199,8 @@ QString Room::Private::doPostFile(event_ptr_tt fileEvent, cons } QString Room::postFile(const QString& plainText, - std::unique_ptr fileContent) + std::unique_ptr fileContent, + std::optional relatesTo) { Q_ASSERT(fileContent != nullptr); const auto url = fileContent->url(); @@ -2208,7 +2210,8 @@ QString Room::postFile(const QString& plainText, return d->doPostFile(makeEvent(plainText, RoomMessageEvent::rawMsgTypeForFile(localFile), - std::move(fileContent)), + std::move(fileContent), + relatesTo), url); } diff --git a/Quotient/room.h b/Quotient/room.h index 1059266e5..27d53269e 100644 --- a/Quotient/room.h +++ b/Quotient/room.h @@ -722,7 +722,8 @@ class QUOTIENT_API Room : public QObject { } QString postFile(const QString& plainText, - std::unique_ptr fileContent); + std::unique_ptr fileContent, + std::optional relatesTo = std::nullopt); PendingEventItem::future_type whenMessageMerged(QString txnId) const; @@ -749,11 +750,12 @@ public Q_SLOTS: /** Check whether the room should be upgraded */ void checkVersion(); - QString postMessage(const QString& plainText, MessageEventType type); - QString postPlainText(const QString& plainText); + QString postMessage(const QString& plainText, MessageEventType type, std::optional relatesTo = std::nullopt); + QString postPlainText(const QString& plainText, std::optional relatesTo = std::nullopt); QString postHtmlMessage(const QString& plainText, const QString& html, - MessageEventType type = MessageEventType::Text); - QString postHtmlText(const QString& plainText, const QString& html); + MessageEventType type = MessageEventType::Text, + std::optional relatesTo = std::nullopt); + QString postHtmlText(const QString& plainText, const QString& html, std::optional relatesTo = std::nullopt); /// Send a reaction on a given event with a given key QString postReaction(const QString& eventId, const QString& key); From 1b217c52adfee22e6832a86e6da2297d97eb1cf6 Mon Sep 17 00:00:00 2001 From: James Graham Date: Tue, 19 Nov 2024 21:12:43 +0000 Subject: [PATCH 2/4] Make all the functions non-callable from QML and remove postMessage because we probably shouldn't allow someone to send a message with an arbritary type but not the correct content. This is replaced by postEmote and postNotice the two types that are probably valid from the original postMessage function. --- Quotient/room.cpp | 37 +++++++++++++++++++++---------------- Quotient/room.h | 37 +++++++++++++++++++------------------ quotest/quotest.cpp | 3 +-- 3 files changed, 41 insertions(+), 36 deletions(-) diff --git a/Quotient/room.cpp b/Quotient/room.cpp index d963655fd..bca9abb83 100644 --- a/Quotient/room.cpp +++ b/Quotient/room.cpp @@ -52,6 +52,7 @@ #include "events/roomcanonicalaliasevent.h" #include "events/roomcreateevent.h" #include "events/roommemberevent.h" +#include "events/roommessageevent.h" #include "events/roompowerlevelsevent.h" #include "events/roomtombstoneevent.h" #include "events/simplestateevents.h" @@ -2121,28 +2122,37 @@ void Room::discardMessage(const QString& txnId) emit pendingEventDiscarded(); } -QString Room::postMessage(const QString& plainText, MessageEventType type, std::optional relatesTo) +QString Room::postEmote(const QString& plainText, std::optional html, std::optional relatesTo) { - return post(plainText, type, nullptr, relatesTo)->transactionId(); + std::unique_ptr content = nullptr; + if (html) { + content = std::make_unique(*html, u"text/html"_s); + } + + return post(plainText, MessageEventType::Emote, std::move(content), relatesTo)->transactionId(); } -QString Room::postPlainText(const QString& plainText, std::optional relatesTo) +QString Room::postNotice(const QString& plainText, std::optional html, std::optional relatesTo) { - return postMessage(plainText, MessageEventType::Text, relatesTo); + std::unique_ptr content = nullptr; + if (html) { + content = std::make_unique(*html, u"text/html"_s); + } + + return post(plainText, MessageEventType::Notice, std::move(content), relatesTo)->transactionId(); } -QString Room::postHtmlMessage(const QString& plainText, const QString& html, - MessageEventType type, std::optional relatesTo) +QString Room::postPlainText(const QString& plainText, std::optional relatesTo) { - return post(plainText, type, - std::make_unique(html, u"text/html"_s), - relatesTo) - ->transactionId(); + return post(plainText, MessageEventType::Text, nullptr, relatesTo)->transactionId(); } QString Room::postHtmlText(const QString& plainText, const QString& html, std::optional relatesTo) { - return postHtmlMessage(plainText, html, MessageEventType::Text, relatesTo); + return post(plainText, MessageEventType::Text, + std::make_unique(html, u"text/html"_s), + relatesTo) + ->transactionId(); } QString Room::postReaction(const QString& eventId, const QString& key) @@ -2215,11 +2225,6 @@ QString Room::postFile(const QString& plainText, url); } -QString Room::postEvent(RoomEvent* event) -{ - return d->sendEvent(RoomEventPtr(event))->transactionId(); -} - const PendingEventItem& Room::post(RoomEventPtr event) { return d->sendEvent(std::move(event)); diff --git a/Quotient/room.h b/Quotient/room.h index 27d53269e..e13f20b78 100644 --- a/Quotient/room.h +++ b/Quotient/room.h @@ -721,10 +721,29 @@ class QUOTIENT_API Room : public QObject { return post(makeEvent(std::forward(args)...)); } + /// Send a plain text message + QString postPlainText(const QString& plainText, std::optional relatesTo = std::nullopt); + + /// Send a rich text message + QString postHtmlText(const QString& plainText, const QString& html, std::optional relatesTo = std::nullopt); + + /// Send a m.emote message + QString postEmote(const QString& plainText, std::optional html = std::nullopt, std::optional relatesTo = std::nullopt); + + /// Send an m.notice message + QString postNotice(const QString& plainText, std::optional html = std::nullopt, std::optional relatesTo = std::nullopt); + + /// Send a file with the given content QString postFile(const QString& plainText, std::unique_ptr fileContent, std::optional relatesTo = std::nullopt); + /// Send the given Json as a message + QString postJson(const QString& matrixType, const QJsonObject& eventContent); + + /// Send a reaction on a given event with a given key + QString postReaction(const QString& eventId, const QString& key); + PendingEventItem::future_type whenMessageMerged(QString txnId) const; //! Send a request to update the room state with the given event @@ -750,24 +769,6 @@ public Q_SLOTS: /** Check whether the room should be upgraded */ void checkVersion(); - QString postMessage(const QString& plainText, MessageEventType type, std::optional relatesTo = std::nullopt); - QString postPlainText(const QString& plainText, std::optional relatesTo = std::nullopt); - QString postHtmlMessage(const QString& plainText, const QString& html, - MessageEventType type = MessageEventType::Text, - std::optional relatesTo = std::nullopt); - QString postHtmlText(const QString& plainText, const QString& html, std::optional relatesTo = std::nullopt); - /// Send a reaction on a given event with a given key - QString postReaction(const QString& eventId, const QString& key); - - /** Post a pre-created room message event - * - * Takes ownership of the event, deleting it once the matching one - * arrives with the sync - * \return transaction id associated with the event. - */ - [[deprecated("Use post() instead")]] - QString postEvent(RoomEvent* event); - QString postJson(const QString& matrixType, const QJsonObject& eventContent); QString retryMessage(const QString& txnId); void discardMessage(const QString& txnId); diff --git a/quotest/quotest.cpp b/quotest/quotest.cpp index 2c982c92c..36aefc7e6 100644 --- a/quotest/quotest.cpp +++ b/quotest/quotest.cpp @@ -169,8 +169,7 @@ void TestSuite::finishTest(const TestToken& token, bool condition, if (condition) { clog << item << " successful" << endl; if (targetRoom) - targetRoom->postMessage(origin % ": "_L1 % QString::fromUtf8(item) % " successful"_L1, - MessageEventType::Notice); + targetRoom->postNotice(origin % ": "_L1 % QString::fromUtf8(item) % " successful"_L1); } else { clog << item << " FAILED at " << file << ":" << line << endl; if (targetRoom) From d4bb17229561d3a454258dd985d8915e62de0ed6 Mon Sep 17 00:00:00 2001 From: James Graham Date: Sun, 1 Dec 2024 12:55:35 +0000 Subject: [PATCH 3/4] Comment updates --- Quotient/room.cpp | 50 ++++++++++++++++++++++----------------------- Quotient/room.h | 17 +++++++-------- quotest/quotest.cpp | 8 ++++---- 3 files changed, 36 insertions(+), 39 deletions(-) diff --git a/Quotient/room.cpp b/Quotient/room.cpp index bca9abb83..cf18238b1 100644 --- a/Quotient/room.cpp +++ b/Quotient/room.cpp @@ -52,7 +52,6 @@ #include "events/roomcanonicalaliasevent.h" #include "events/roomcreateevent.h" #include "events/roommemberevent.h" -#include "events/roommessageevent.h" #include "events/roompowerlevelsevent.h" #include "events/roomtombstoneevent.h" #include "events/simplestateevents.h" @@ -294,6 +293,25 @@ class Q_DECL_HIDDEN Room::Private { const PendingEventItem& sendEvent(RoomEventPtr&& event); + // template + template + QString postAllText(const QString& plainText, + std::optional html, + std::optional relatesTo) + { + static_assert(type == MessageEventType::Text || + type == MessageEventType::Emote || + type == MessageEventType::Notice , + "MessageEvent type is not a text message" + ); + + std::unique_ptr content = nullptr; + if (html) { + content = std::make_unique(*html, u"text/html"_s); + } + return q->post(plainText, type, std::move(content), relatesTo)->transactionId(); + } + QString doPostFile(event_ptr_tt fileEvent, const QUrl& localUrl); PendingEvents::iterator addAsPending(RoomEventPtr&& event); @@ -2122,37 +2140,19 @@ void Room::discardMessage(const QString& txnId) emit pendingEventDiscarded(); } -QString Room::postEmote(const QString& plainText, std::optional html, std::optional relatesTo) +QString Room::postText(const QString& plainText, std::optional html, std::optional relatesTo) { - std::unique_ptr content = nullptr; - if (html) { - content = std::make_unique(*html, u"text/html"_s); - } - - return post(plainText, MessageEventType::Emote, std::move(content), relatesTo)->transactionId(); + return d->postAllText(plainText, html, relatesTo); } -QString Room::postNotice(const QString& plainText, std::optional html, std::optional relatesTo) -{ - std::unique_ptr content = nullptr; - if (html) { - content = std::make_unique(*html, u"text/html"_s); - } - - return post(plainText, MessageEventType::Notice, std::move(content), relatesTo)->transactionId(); -} - -QString Room::postPlainText(const QString& plainText, std::optional relatesTo) +QString Room::postEmote(const QString& plainText, std::optional html, std::optional relatesTo) { - return post(plainText, MessageEventType::Text, nullptr, relatesTo)->transactionId(); + return d->postAllText(plainText, html, relatesTo); } -QString Room::postHtmlText(const QString& plainText, const QString& html, std::optional relatesTo) +QString Room::postNotice(const QString& plainText, std::optional html, std::optional relatesTo) { - return post(plainText, MessageEventType::Text, - std::make_unique(html, u"text/html"_s), - relatesTo) - ->transactionId(); + return d->postAllText(plainText, html, relatesTo); } QString Room::postReaction(const QString& eventId, const QString& key) diff --git a/Quotient/room.h b/Quotient/room.h index e13f20b78..d5f53527e 100644 --- a/Quotient/room.h +++ b/Quotient/room.h @@ -721,27 +721,24 @@ class QUOTIENT_API Room : public QObject { return post(makeEvent(std::forward(args)...)); } - /// Send a plain text message - QString postPlainText(const QString& plainText, std::optional relatesTo = std::nullopt); + //! Send a text message + QString postText(const QString& plainText, std::optional html = std::nullopt, std::optional relatesTo = std::nullopt); - /// Send a rich text message - QString postHtmlText(const QString& plainText, const QString& html, std::optional relatesTo = std::nullopt); - - /// Send a m.emote message + //! Send a m.emote message QString postEmote(const QString& plainText, std::optional html = std::nullopt, std::optional relatesTo = std::nullopt); - /// Send an m.notice message + //! Send an m.notice message QString postNotice(const QString& plainText, std::optional html = std::nullopt, std::optional relatesTo = std::nullopt); - /// Send a file with the given content + //! Send a file with the given content QString postFile(const QString& plainText, std::unique_ptr fileContent, std::optional relatesTo = std::nullopt); - /// Send the given Json as a message + //! Send the given Json as a message QString postJson(const QString& matrixType, const QJsonObject& eventContent); - /// Send a reaction on a given event with a given key + //! Send a reaction on a given event with a given key QString postReaction(const QString& eventId, const QString& key); PendingEventItem::future_type whenMessageMerged(QString txnId) const; diff --git a/quotest/quotest.cpp b/quotest/quotest.cpp index 36aefc7e6..21dfd17f1 100644 --- a/quotest/quotest.cpp +++ b/quotest/quotest.cpp @@ -173,7 +173,7 @@ void TestSuite::finishTest(const TestToken& token, bool condition, } else { clog << item << " FAILED at " << file << ":" << line << endl; if (targetRoom) - targetRoom->postPlainText(origin % ": "_L1 % QString::fromUtf8(item) % " FAILED at "_L1 + targetRoom->postText(origin % ": "_L1 % QString::fromUtf8(item) % " FAILED at "_L1 % QString::fromUtf8(file) % ", line "_L1 % QString::number(line)); } @@ -363,7 +363,7 @@ TEST_IMPL(loadMembers) TEST_IMPL(sendMessage) { - auto txnId = targetRoom->postPlainText("Hello, "_L1 % origin % " is here"_L1); + auto txnId = targetRoom->postText("Hello, "_L1 % origin % " is here"_L1); if (!validatePendingEvent(txnId)) { clog << "Invalid pending event right after submitting" << endl; FAIL_TEST(); @@ -462,7 +462,7 @@ TEST_IMPL(sendFile) if (id != txnId) return false; - targetRoom->postPlainText(origin % ": File upload failed: "_L1 % error); + targetRoom->postText(origin % ": File upload failed: "_L1 % error); tf->deleteLater(); FAIL_TEST(); }); @@ -922,7 +922,7 @@ void TestManager::conclude() htmlReport += "
Did not finish:"_L1 + QString::fromUtf8(dnfList); } - auto txnId = room->postHtmlText(plainReport, htmlReport); + auto txnId = room->postText(plainReport, htmlReport); // Now just wait until all the pending events reach the server connectUntil(room, &Room::messageSent, this, [this, txnId, room, plainReport] { From 9c2ec97861ea44cfbb2e232b9e2fedb27d7b7e47 Mon Sep 17 00:00:00 2001 From: James Graham Date: Mon, 2 Dec 2024 17:07:05 +0000 Subject: [PATCH 4/4] Further comments --- Quotient/room.cpp | 34 ---------------------------------- Quotient/room.h | 28 ++++++++++++++++++++-------- quotest/quotest.cpp | 2 +- 3 files changed, 21 insertions(+), 43 deletions(-) diff --git a/Quotient/room.cpp b/Quotient/room.cpp index cf18238b1..5f28bad27 100644 --- a/Quotient/room.cpp +++ b/Quotient/room.cpp @@ -293,25 +293,6 @@ class Q_DECL_HIDDEN Room::Private { const PendingEventItem& sendEvent(RoomEventPtr&& event); - // template - template - QString postAllText(const QString& plainText, - std::optional html, - std::optional relatesTo) - { - static_assert(type == MessageEventType::Text || - type == MessageEventType::Emote || - type == MessageEventType::Notice , - "MessageEvent type is not a text message" - ); - - std::unique_ptr content = nullptr; - if (html) { - content = std::make_unique(*html, u"text/html"_s); - } - return q->post(plainText, type, std::move(content), relatesTo)->transactionId(); - } - QString doPostFile(event_ptr_tt fileEvent, const QUrl& localUrl); PendingEvents::iterator addAsPending(RoomEventPtr&& event); @@ -2140,21 +2121,6 @@ void Room::discardMessage(const QString& txnId) emit pendingEventDiscarded(); } -QString Room::postText(const QString& plainText, std::optional html, std::optional relatesTo) -{ - return d->postAllText(plainText, html, relatesTo); -} - -QString Room::postEmote(const QString& plainText, std::optional html, std::optional relatesTo) -{ - return d->postAllText(plainText, html, relatesTo); -} - -QString Room::postNotice(const QString& plainText, std::optional html, std::optional relatesTo) -{ - return d->postAllText(plainText, html, relatesTo); -} - QString Room::postReaction(const QString& eventId, const QString& key) { return post(eventId, key)->transactionId(); diff --git a/Quotient/room.h b/Quotient/room.h index d5f53527e..fe36f408b 100644 --- a/Quotient/room.h +++ b/Quotient/room.h @@ -721,14 +721,26 @@ class QUOTIENT_API Room : public QObject { return post(makeEvent(std::forward(args)...)); } - //! Send a text message - QString postText(const QString& plainText, std::optional html = std::nullopt, std::optional relatesTo = std::nullopt); - - //! Send a m.emote message - QString postEmote(const QString& plainText, std::optional html = std::nullopt, std::optional relatesTo = std::nullopt); - - //! Send an m.notice message - QString postNotice(const QString& plainText, std::optional html = std::nullopt, std::optional relatesTo = std::nullopt); + //! \brief Send a text type message + //! + //! This means MessageEventType Text, Emote or Notice. + template + QString postText(const QString& plainText, + const std::optional& html = std::nullopt, + const std::optional& relatesTo = std::nullopt) + { + static_assert(type == MessageEventType::Text || + type == MessageEventType::Emote || + type == MessageEventType::Notice , + "MessageEvent type is not a text message" + ); + + std::unique_ptr content = nullptr; + if (html) { + content = std::make_unique(*html, u"text/html"_s); + } + return post(plainText, type, std::move(content), relatesTo)->transactionId(); + } //! Send a file with the given content QString postFile(const QString& plainText, diff --git a/quotest/quotest.cpp b/quotest/quotest.cpp index 21dfd17f1..ad1e4dfca 100644 --- a/quotest/quotest.cpp +++ b/quotest/quotest.cpp @@ -169,7 +169,7 @@ void TestSuite::finishTest(const TestToken& token, bool condition, if (condition) { clog << item << " successful" << endl; if (targetRoom) - targetRoom->postNotice(origin % ": "_L1 % QString::fromUtf8(item) % " successful"_L1); + targetRoom->postText(origin % ": "_L1 % QString::fromUtf8(item) % " successful"_L1); } else { clog << item << " FAILED at " << file << ":" << line << endl; if (targetRoom)