From 5ad5010b01f2fe1f2bf8b4bd0a9ac85b42889602 Mon Sep 17 00:00:00 2001 From: James Graham Date: Sat, 21 Sep 2024 09:32:47 +0100 Subject: [PATCH 1/4] Move the EventRelation out of TextContent and into RoomMessageEvent as any message can now be replied to. --- Quotient/events/eventrelation.cpp | 6 +- Quotient/events/roommessageevent.cpp | 84 ++++++++++++---------------- Quotient/events/roommessageevent.h | 16 +++--- 3 files changed, 47 insertions(+), 59 deletions(-) diff --git a/Quotient/events/eventrelation.cpp b/Quotient/events/eventrelation.cpp index 357498bc5..fa600a0f7 100644 --- a/Quotient/events/eventrelation.cpp +++ b/Quotient/events/eventrelation.cpp @@ -17,7 +17,7 @@ void JsonObjectConverter::dumpTo(QJsonObject& jo, } if (pod.type == EventRelation::ReplyType) { - jo.insert(EventRelation::ReplyType, {{EventIdKey, pod.eventId}}); + jo.insert(EventRelation::ReplyType, {QJsonObject{{EventIdKey, pod.eventId}}}); return; } @@ -26,9 +26,9 @@ void JsonObjectConverter::dumpTo(QJsonObject& jo, if (pod.type == EventRelation::AnnotationType) jo.insert("key"_L1, pod.key); if (pod.type == EventRelation::ThreadType) { - jo.insert(EventRelation::ReplyType, {{EventIdKey, pod.inThreadReplyEventId}}); + jo.insert(EventRelation::ReplyType, {QJsonObject{{EventIdKey, pod.inThreadReplyEventId}}}); + jo.insert(IsFallingBackKey, pod.isFallingBack); } - jo.insert(IsFallingBackKey, pod.isFallingBack); } void JsonObjectConverter::fillFrom(const QJsonObject& jo, diff --git a/Quotient/events/roommessageevent.cpp b/Quotient/events/roommessageevent.cpp index 1e75b54c7..591943454 100644 --- a/Quotient/events/roommessageevent.cpp +++ b/Quotient/events/roommessageevent.cpp @@ -6,7 +6,9 @@ #include "roommessageevent.h" #include "../logging_categories_p.h" +#include #include "eventrelation.h" +#include #include #include @@ -86,49 +88,47 @@ inline bool isReplacement(const std::optional& rel) QJsonObject RoomMessageEvent::assembleContentJson(const QString& plainBody, const QString& jsonMsgType, - TypedBase* content) + TypedBase* content, + std::optional relatesTo) { QJsonObject json; if (content) { // TODO: replace with content->fillJson(json) when it starts working json = content->toJson(); - if (jsonMsgType != TextTypeKey && jsonMsgType != NoticeTypeKey - && jsonMsgType != EmoteTypeKey) { - if (json.contains(RelatesToKey)) { - json.remove(RelatesToKey); - qCWarning(EVENTS) - << RelatesToKey << "cannot be used in" << jsonMsgType - << "messages; the relation has been stripped off"; + } + json.insert(MsgTypeKey, jsonMsgType); + json.insert(BodyKey, plainBody); + if (relatesTo.has_value()) { + json.insert(RelatesToKey, toJson(relatesTo.value())); + // JsonObjectConverter::dumpTo(json, relatesTo.value()); + if (auto* textContent = static_cast(content); relatesTo->type == EventRelation::ReplacementType) { + QJsonObject newContentJson; + if (content && textContent->mimeType.inherits("text/html"_L1)) { + newContentJson.insert("format"_L1, HtmlContentTypeId); + newContentJson.insert(FormattedBodyKey, textContent->body); } - } else if (auto* textContent = static_cast(content); - textContent->relatesTo - && textContent->relatesTo->type - == EventRelation::ReplacementType) { - auto newContentJson = json.take("m.new_content"_L1).toObject(); newContentJson.insert(BodyKey, plainBody); newContentJson.insert(MsgTypeKey, jsonMsgType); json.insert("m.new_content"_L1, newContentJson); - json[MsgTypeKey] = jsonMsgType; - json[BodyKey] = "* "_L1 + plainBody; - return json; + json.insert(BodyKey, "* "_L1 + plainBody); } } - json.insert(MsgTypeKey, jsonMsgType); - json.insert(BodyKey, plainBody); return json; } RoomMessageEvent::RoomMessageEvent(const QString& plainBody, const QString& jsonMsgType, - TypedBase* content) + TypedBase* content, + std::optional relatesTo) : RoomEvent( - basicJson(TypeId, assembleContentJson(plainBody, jsonMsgType, content))) + basicJson(TypeId, assembleContentJson(plainBody, jsonMsgType, content, relatesTo))) , _content(content) + , _relatesTo(relatesTo) {} RoomMessageEvent::RoomMessageEvent(const QString& plainBody, MsgType msgType, - TypedBase* content) - : RoomMessageEvent(plainBody, msgTypeToJson(msgType), content) + TypedBase* content, std::optional relatesTo) + : RoomMessageEvent(plainBody, msgTypeToJson(msgType), content, relatesTo) {} RoomMessageEvent::RoomMessageEvent(const QJsonObject& obj) @@ -140,16 +140,22 @@ RoomMessageEvent::RoomMessageEvent(const QJsonObject& obj) if (content.contains(MsgTypeKey) && content.contains(BodyKey)) { auto msgtype = content[MsgTypeKey].toString(); bool msgTypeFound = false; - for (const auto& mt : msgTypes) + for (const auto& mt : msgTypes) { if (mt.matrixType == msgtype) { _content = mt.maker(content); msgTypeFound = true; } + } if (!msgTypeFound) { qCWarning(EVENTS) << "RoomMessageEvent: unknown msg_type," << " full content dump follows"; qCWarning(EVENTS) << formatJson << content; + return; + } + + if (content.contains(RelatesToKey)) { + _relatesTo = fromJson>(content[RelatesToKey]); } } else { qCWarning(EVENTS) << "No body or msgtype in room message event"; @@ -198,7 +204,7 @@ bool RoomMessageEvent::hasThumbnail() const std::optional RoomMessageEvent::relatesTo() const { - return content() && hasTextContent() ? static_cast(content())->relatesTo : std::nullopt; + return _relatesTo; } QString RoomMessageEvent::upstreamEventId() const @@ -212,8 +218,7 @@ QString RoomMessageEvent::replacedEvent() const if (!content() || !hasTextContent()) return {}; - const auto& rel = static_cast(content())->relatesTo; - return isReplacement(rel) ? rel->eventId : QString(); + return isReplacement(_relatesTo) ? _relatesTo->eventId : QString(); } bool RoomMessageEvent::isReplaced() const @@ -319,23 +324,22 @@ QString RoomMessageEvent::rawMsgTypeForFile(const QFileInfo& fi) return rawMsgTypeForMimeType(QMimeDatabase().mimeTypeForFile(fi)); } -TextContent::TextContent(QString text, const QString& contentType, - std::optional relatesTo) +TextContent::TextContent(QString text, const QString& contentType) : mimeType(QMimeDatabase().mimeTypeForName(contentType)) , body(std::move(text)) - , relatesTo(std::move(relatesTo)) { if (contentType == HtmlContentTypeId) mimeType = QMimeDatabase().mimeTypeForName("text/html"_L1); } TextContent::TextContent(const QJsonObject& json) - : relatesTo(fromJson>(json[RelatesToKey])) { QMimeDatabase db; static const auto PlainTextMimeType = db.mimeTypeForName("text/plain"_L1); static const auto HtmlMimeType = db.mimeTypeForName("text/html"_L1); + const auto relatesTo = fromJson>(json[RelatesToKey]); + const auto actualJson = isReplacement(relatesTo) ? json.value("m.new_content"_L1).toObject() : json; @@ -354,28 +358,10 @@ TextContent::TextContent(const QJsonObject& json) void TextContent::fillJson(QJsonObject &json) const { - static const auto FormatKey = "format"_L1; - if (mimeType.inherits("text/html"_L1)) { - json.insert(FormatKey, HtmlContentTypeId); + json.insert("format"_L1, HtmlContentTypeId); json.insert(FormattedBodyKey, body); } - if (relatesTo) { - json.insert("m.relates_to"_L1, - relatesTo->type == EventRelation::ReplyType - ? QJsonObject{ { relatesTo->type, - QJsonObject{ { EventIdKey, relatesTo->eventId } } } } - : QJsonObject{ { RelTypeKey, relatesTo->type }, - { EventIdKey, relatesTo->eventId } }); - if (relatesTo->type == EventRelation::ReplacementType) { - QJsonObject newContentJson; - if (mimeType.inherits("text/html"_L1)) { - newContentJson.insert(FormatKey, HtmlContentTypeId); - newContentJson.insert(FormattedBodyKey, body); - } - json.insert("m.new_content"_L1, newContentJson); - } - } } LocationContent::LocationContent(const QString& geoUri, diff --git a/Quotient/events/roommessageevent.h b/Quotient/events/roommessageevent.h index c3e94782a..97c56013b 100644 --- a/Quotient/events/roommessageevent.h +++ b/Quotient/events/roommessageevent.h @@ -34,10 +34,12 @@ class QUOTIENT_API RoomMessageEvent : public RoomEvent { }; RoomMessageEvent(const QString& plainBody, const QString& jsonMsgType, - EventContent::TypedBase* content = nullptr); + EventContent::TypedBase* content = nullptr, + std::optional relatesTo = std:: nullopt); explicit RoomMessageEvent(const QString& plainBody, MsgType msgType = MsgType::Text, - EventContent::TypedBase* content = nullptr); + EventContent::TypedBase* content = nullptr, + std::optional relatesTo = std:: nullopt); explicit RoomMessageEvent(const QJsonObject& obj); @@ -48,7 +50,7 @@ class QUOTIENT_API RoomMessageEvent : public RoomEvent { void editContent(auto visitor) { visitor(*_content); - editJson()[ContentKey] = assembleContentJson(plainBody(), rawMsgtype(), _content.get()); + editJson()[ContentKey] = assembleContentJson(plainBody(), rawMsgtype(), _content.get(), _relatesTo); } QMimeType mimeType() const; //! \brief Determine whether the message has text content @@ -141,11 +143,13 @@ class QUOTIENT_API RoomMessageEvent : public RoomEvent { private: std::unique_ptr _content; + std::optional _relatesTo; // FIXME: should it really be static? static QJsonObject assembleContentJson(const QString& plainBody, const QString& jsonMsgType, - EventContent::TypedBase* content); + EventContent::TypedBase* content, + std::optional relatesTo); Q_ENUM(MsgType) }; @@ -164,15 +168,13 @@ namespace EventContent { */ class QUOTIENT_API TextContent : public TypedBase { public: - TextContent(QString text, const QString& contentType, - std::optional relatesTo = {}); + TextContent(QString text, const QString& contentType); explicit TextContent(const QJsonObject& json); QMimeType type() const override { return mimeType; } QMimeType mimeType; QString body; - std::optional relatesTo; protected: void fillJson(QJsonObject& json) const override; From e1b06908b64b62132502c73d4c3114e4b463aa6c Mon Sep 17 00:00:00 2001 From: James Graham Date: Sat, 28 Sep 2024 09:58:14 +0100 Subject: [PATCH 2/4] Use fromJson --- Quotient/events/roommessageevent.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Quotient/events/roommessageevent.cpp b/Quotient/events/roommessageevent.cpp index 591943454..c89f9c3d5 100644 --- a/Quotient/events/roommessageevent.cpp +++ b/Quotient/events/roommessageevent.cpp @@ -154,9 +154,7 @@ RoomMessageEvent::RoomMessageEvent(const QJsonObject& obj) return; } - if (content.contains(RelatesToKey)) { - _relatesTo = fromJson>(content[RelatesToKey]); - } + fromJson(content[RelatesToKey], _relatesTo); } else { qCWarning(EVENTS) << "No body or msgtype in room message event"; qCWarning(EVENTS) << formatJson << obj; From 36412907ba9a2e5adc0e5a7550ca68b615f4a743 Mon Sep 17 00:00:00 2001 From: James Graham Date: Wed, 2 Oct 2024 18:44:06 +0100 Subject: [PATCH 3/4] Comment updates --- Quotient/events/eventrelation.cpp | 4 ++-- Quotient/events/roommessageevent.cpp | 17 ++++++++--------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/Quotient/events/eventrelation.cpp b/Quotient/events/eventrelation.cpp index fa600a0f7..b708ca876 100644 --- a/Quotient/events/eventrelation.cpp +++ b/Quotient/events/eventrelation.cpp @@ -17,7 +17,7 @@ void JsonObjectConverter::dumpTo(QJsonObject& jo, } if (pod.type == EventRelation::ReplyType) { - jo.insert(EventRelation::ReplyType, {QJsonObject{{EventIdKey, pod.eventId}}}); + jo.insert(EventRelation::ReplyType, QJsonObject{{EventIdKey, pod.eventId}}); return; } @@ -26,7 +26,7 @@ void JsonObjectConverter::dumpTo(QJsonObject& jo, if (pod.type == EventRelation::AnnotationType) jo.insert("key"_L1, pod.key); if (pod.type == EventRelation::ThreadType) { - jo.insert(EventRelation::ReplyType, {QJsonObject{{EventIdKey, pod.inThreadReplyEventId}}}); + jo.insert(EventRelation::ReplyType, QJsonObject{{EventIdKey, pod.inThreadReplyEventId}}); jo.insert(IsFallingBackKey, pod.isFallingBack); } } diff --git a/Quotient/events/roommessageevent.cpp b/Quotient/events/roommessageevent.cpp index c89f9c3d5..be1aeb78e 100644 --- a/Quotient/events/roommessageevent.cpp +++ b/Quotient/events/roommessageevent.cpp @@ -6,9 +6,7 @@ #include "roommessageevent.h" #include "../logging_categories_p.h" -#include #include "eventrelation.h" -#include #include #include @@ -24,6 +22,7 @@ namespace { // Supporting internal definitions constexpr auto RelatesToKey = "m.relates_to"_L1; constexpr auto MsgTypeKey = "msgtype"_L1; constexpr auto FormattedBodyKey = "formatted_body"_L1; +constexpr auto FormatKey = "format"_L1; constexpr auto TextTypeKey = "m.text"_L1; constexpr auto EmoteTypeKey = "m.emote"_L1; constexpr auto NoticeTypeKey = "m.notice"_L1; @@ -99,12 +98,12 @@ QJsonObject RoomMessageEvent::assembleContentJson(const QString& plainBody, json.insert(MsgTypeKey, jsonMsgType); json.insert(BodyKey, plainBody); if (relatesTo.has_value()) { - json.insert(RelatesToKey, toJson(relatesTo.value())); - // JsonObjectConverter::dumpTo(json, relatesTo.value()); - if (auto* textContent = static_cast(content); relatesTo->type == EventRelation::ReplacementType) { + json.insert(RelatesToKey, toJson(relatesTo.value())); + if (relatesTo->type == EventRelation::ReplacementType) { QJsonObject newContentJson; - if (content && textContent->mimeType.inherits("text/html"_L1)) { - newContentJson.insert("format"_L1, HtmlContentTypeId); + if (auto* textContent = static_cast(content); + textContent && textContent->mimeType.inherits("text/html"_L1)) { + newContentJson.insert(FormatKey, HtmlContentTypeId); newContentJson.insert(FormattedBodyKey, textContent->body); } newContentJson.insert(BodyKey, plainBody); @@ -221,7 +220,7 @@ QString RoomMessageEvent::replacedEvent() const bool RoomMessageEvent::isReplaced() const { - return unsignedPart("m.relations"_L1).contains("m.replace"_L1); + return unsignedPart("m.relations"_L1).contains("m.replace"_L1);"format"_L1 } QString RoomMessageEvent::replacedBy() const @@ -357,7 +356,7 @@ TextContent::TextContent(const QJsonObject& json) void TextContent::fillJson(QJsonObject &json) const { if (mimeType.inherits("text/html"_L1)) { - json.insert("format"_L1, HtmlContentTypeId); + json.insert(FormatKey, HtmlContentTypeId); json.insert(FormattedBodyKey, body); } } From fee5b8e8bc36d7c69ffb1dd47c89ae9a9ac62c08 Mon Sep 17 00:00:00 2001 From: James Graham Date: Wed, 2 Oct 2024 18:49:20 +0100 Subject: [PATCH 4/4] Fix typo --- Quotient/events/roommessageevent.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Quotient/events/roommessageevent.cpp b/Quotient/events/roommessageevent.cpp index be1aeb78e..47c872152 100644 --- a/Quotient/events/roommessageevent.cpp +++ b/Quotient/events/roommessageevent.cpp @@ -220,7 +220,7 @@ QString RoomMessageEvent::replacedEvent() const bool RoomMessageEvent::isReplaced() const { - return unsignedPart("m.relations"_L1).contains("m.replace"_L1);"format"_L1 + return unsignedPart("m.relations"_L1).contains("m.replace"_L1); } QString RoomMessageEvent::replacedBy() const