diff --git a/Quotient/events/encryptedevent.cpp b/Quotient/events/encryptedevent.cpp index ad6bbd60..bc81a98d 100644 --- a/Quotient/events/encryptedevent.cpp +++ b/Quotient/events/encryptedevent.cpp @@ -4,6 +4,8 @@ #include "encryptedevent.h" #include +#include "eventrelation.h" + using namespace Quotient; EncryptedEvent::EncryptedEvent(const QJsonObject& ciphertexts, diff --git a/Quotient/events/event.h b/Quotient/events/event.h index b7172370..b146dfb9 100644 --- a/Quotient/events/event.h +++ b/Quotient/events/event.h @@ -19,7 +19,6 @@ using event_ptr_tt = std::unique_ptr; // === Standard Matrix key names === constexpr inline auto TypeKey = "type"_L1; -constexpr inline auto BodyKey = "body"_L1; constexpr inline auto ContentKey = "content"_L1; constexpr inline auto SenderKey = "sender"_L1; constexpr inline auto UnsignedKey = "unsigned"_L1; diff --git a/Quotient/events/eventcontent.cpp b/Quotient/events/eventcontent.cpp index 5fb5a079..4ef6554c 100644 --- a/Quotient/events/eventcontent.cpp +++ b/Quotient/events/eventcontent.cpp @@ -6,6 +6,7 @@ #include "../logging_categories_p.h" #include "../converters.h" +#include "eventrelation.h" #include #include @@ -115,3 +116,63 @@ void Thumbnail::dumpTo(QJsonObject& infoJson) const if (!imageSize.isEmpty()) infoJson.insert("thumbnail_info"_L1, toInfoJson(*this)); } + +TextContent::TextContent(QString text, const QString& contentType) + : mimeType(QMimeDatabase().mimeTypeForName(contentType)), body(std::move(text)) +{ + if (contentType == HtmlContentTypeId) + mimeType = QMimeDatabase().mimeTypeForName("text/html"_L1); +} + +TextContent::TextContent(const QJsonObject& json) +{ + 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 = relatesTo.has_value() && relatesTo->type == EventRelation::ReplacementType + ? json.value("m.new_content"_L1).toObject() + : json; + // Special-casing the custom matrix.org's (actually, Element's) way + // of sending HTML messages. + if (actualJson["format"_L1].toString() == HtmlContentTypeId) { + mimeType = HtmlMimeType; + body = actualJson[FormattedBodyKey].toString(); + } else { + // Falling back to plain text, as there's no standard way to describe + // rich text in messages. + mimeType = PlainTextMimeType; + body = actualJson[BodyKey].toString(); + } +} + +void TextContent::fillJson(QJsonObject &json) const +{ + if (mimeType.inherits("text/html"_L1)) { + json.insert(FormatKey, HtmlContentTypeId); + json.insert(FormattedBodyKey, body); + } +} + +LocationContent::LocationContent(const QString& geoUri, const Thumbnail& thumbnail) + : geoUri(geoUri), thumbnail(thumbnail) +{} + +LocationContent::LocationContent(const QJsonObject& json) + : Base(json) + , geoUri(json["geo_uri"_L1].toString()) + , thumbnail(json[InfoKey].toObject()) +{} + +QMimeType LocationContent::type() const +{ + return QMimeDatabase().mimeTypeForData(geoUri.toLatin1()); +} + +void LocationContent::fillJson(QJsonObject& o) const +{ + o.insert("geo_uri"_L1, geoUri); + o.insert(InfoKey, toInfoJson(thumbnail)); +} diff --git a/Quotient/events/eventcontent.h b/Quotient/events/eventcontent.h index f07af85a..8f338a9f 100644 --- a/Quotient/events/eventcontent.h +++ b/Quotient/events/eventcontent.h @@ -17,6 +17,10 @@ class QFileInfo; namespace Quotient { +constexpr inline auto BodyKey = "body"_L1; +constexpr inline auto FormatKey = "format"_L1; +constexpr inline auto FormattedBodyKey = "formatted_body"_L1; +constexpr inline auto HtmlContentTypeId = "org.matrix.custom.html"_L1; constexpr inline auto InfoKey = "info"_L1; } diff --git a/Quotient/events/eventrelation.h b/Quotient/events/eventrelation.h index 6c4f5cf9..8cc4992e 100644 --- a/Quotient/events/eventrelation.h +++ b/Quotient/events/eventrelation.h @@ -7,6 +7,7 @@ namespace Quotient { +constexpr inline auto RelatesToKey = "m.relates_to"_L1; constexpr inline auto RelTypeKey = "rel_type"_L1; constexpr inline auto IsFallingBackKey = "is_falling_back"_L1; diff --git a/Quotient/events/roomevent.h b/Quotient/events/roomevent.h index 4f013e54..2509fd51 100644 --- a/Quotient/events/roomevent.h +++ b/Quotient/events/roomevent.h @@ -13,7 +13,6 @@ constexpr inline auto EventIdKey = "event_id"_L1; constexpr inline auto RoomIdKey = "room_id"_L1; constexpr inline auto StateKeyKey = "state_key"_L1; constexpr inline auto RedactedCauseKey = "redacted_because"_L1; -constexpr inline auto RelatesToKey = "m.relates_to"_L1; class RedactionEvent; class EncryptedEvent; diff --git a/Quotient/events/roommessageevent.cpp b/Quotient/events/roommessageevent.cpp index e2ae7c34..580764b4 100644 --- a/Quotient/events/roommessageevent.cpp +++ b/Quotient/events/roommessageevent.cpp @@ -19,10 +19,7 @@ using namespace EventContent; using MsgType = RoomMessageEvent::MsgType; 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 TextTypeId = "m.text"_L1; constexpr auto EmoteTypeId = "m.emote"_L1; constexpr auto NoticeTypeId = "m.notice"_L1; @@ -31,7 +28,6 @@ constexpr auto ImageTypeId = "m.image"_L1; constexpr auto AudioTypeId = "m.audio"_L1; constexpr auto VideoTypeId = "m.video"_L1; constexpr auto LocationTypeId = "m.location"_L1; -constexpr auto HtmlContentTypeId = "org.matrix.custom.html"_L1; template std::unique_ptr make(const QJsonObject& json) @@ -387,63 +383,3 @@ QString RoomMessageEvent::rawMsgTypeForFile(const QFileInfo& fi) { return rawMsgTypeForMimeType(QMimeDatabase().mimeTypeForFile(fi)); } - -TextContent::TextContent(QString text, const QString& contentType) - : mimeType(QMimeDatabase().mimeTypeForName(contentType)), body(std::move(text)) -{ - if (contentType == HtmlContentTypeId) - mimeType = QMimeDatabase().mimeTypeForName("text/html"_L1); -} - -TextContent::TextContent(const QJsonObject& json) -{ - 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; - // Special-casing the custom matrix.org's (actually, Element's) way - // of sending HTML messages. - if (actualJson["format"_L1].toString() == HtmlContentTypeId) { - mimeType = HtmlMimeType; - body = actualJson[FormattedBodyKey].toString(); - } else { - // Falling back to plain text, as there's no standard way to describe - // rich text in messages. - mimeType = PlainTextMimeType; - body = actualJson[BodyKey].toString(); - } -} - -void TextContent::fillJson(QJsonObject &json) const -{ - if (mimeType.inherits("text/html"_L1)) { - json.insert(FormatKey, HtmlContentTypeId); - json.insert(FormattedBodyKey, body); - } -} - -LocationContent::LocationContent(const QString& geoUri, const Thumbnail& thumbnail) - : geoUri(geoUri), thumbnail(thumbnail) -{} - -LocationContent::LocationContent(const QJsonObject& json) - : Base(json) - , geoUri(json["geo_uri"_L1].toString()) - , thumbnail(json[InfoKey].toObject()) -{} - -QMimeType LocationContent::type() const -{ - return QMimeDatabase().mimeTypeForData(geoUri.toLatin1()); -} - -void LocationContent::fillJson(QJsonObject& o) const -{ - o.insert("geo_uri"_L1, geoUri); - o.insert(InfoKey, toInfoJson(thumbnail)); -}