Skip to content

Commit

Permalink
Move the EventRelation out of TextContent and into RoomMessageEvent a…
Browse files Browse the repository at this point in the history
…s any message can now be replied to.
  • Loading branch information
nvrWhere committed Sep 21, 2024
1 parent 4a6f0bd commit 4a8dc2a
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 59 deletions.
6 changes: 3 additions & 3 deletions Quotient/events/eventrelation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ void JsonObjectConverter<EventRelation>::dumpTo(QJsonObject& jo,
}

if (pod.type == EventRelation::ReplyType) {
jo.insert(EventRelation::ReplyType, {{EventIdKey, pod.eventId}});
jo.insert(EventRelation::ReplyType, {QJsonObject{{EventIdKey, pod.eventId}}});
return;
}

Expand All @@ -26,9 +26,9 @@ void JsonObjectConverter<EventRelation>::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<EventRelation>::fillFrom(const QJsonObject& jo,
Expand Down
84 changes: 35 additions & 49 deletions Quotient/events/roommessageevent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
#include "roommessageevent.h"

#include "../logging_categories_p.h"
#include <Quotient/converters.h>
#include "eventrelation.h"
#include <Quotient/events/event.h>

#include <QtCore/QFileInfo>
#include <QtCore/QMimeDatabase>
Expand Down Expand Up @@ -86,49 +88,47 @@ inline bool isReplacement(const std::optional<EventRelation>& rel)

QJsonObject RoomMessageEvent::assembleContentJson(const QString& plainBody,
const QString& jsonMsgType,
TypedBase* content)
TypedBase* content,
std::optional<EventRelation> 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<EventRelation>(relatesTo.value()));
// JsonObjectConverter<EventRelation>::dumpTo(json, relatesTo.value());
if (auto* textContent = static_cast<const TextContent*>(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<const TextContent*>(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<EventRelation> 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<EventRelation> relatesTo)
: RoomMessageEvent(plainBody, msgTypeToJson(msgType), content, relatesTo)
{}

RoomMessageEvent::RoomMessageEvent(const QJsonObject& obj)
Expand All @@ -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<std::optional<EventRelation>>(content[RelatesToKey]);
}
} else {
qCWarning(EVENTS) << "No body or msgtype in room message event";
Expand Down Expand Up @@ -198,7 +204,7 @@ bool RoomMessageEvent::hasThumbnail() const

std::optional<EventRelation> RoomMessageEvent::relatesTo() const
{
return content() && hasTextContent() ? static_cast<const TextContent*>(content())->relatesTo : std::nullopt;
return _relatesTo;
}

QString RoomMessageEvent::upstreamEventId() const
Expand All @@ -212,8 +218,7 @@ QString RoomMessageEvent::replacedEvent() const
if (!content() || !hasTextContent())
return {};

const auto& rel = static_cast<const TextContent*>(content())->relatesTo;
return isReplacement(rel) ? rel->eventId : QString();
return isReplacement(_relatesTo) ? _relatesTo->eventId : QString();
}

bool RoomMessageEvent::isReplaced() const
Expand Down Expand Up @@ -320,23 +325,22 @@ QString RoomMessageEvent::rawMsgTypeForFile(const QFileInfo& fi)
return rawMsgTypeForMimeType(QMimeDatabase().mimeTypeForFile(fi));
}

TextContent::TextContent(QString text, const QString& contentType,
std::optional<EventRelation> 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<std::optional<EventRelation>>(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<std::optional<EventRelation>>(json[RelatesToKey]);

const auto actualJson = isReplacement(relatesTo)
? json.value("m.new_content"_L1).toObject()
: json;
Expand All @@ -355,28 +359,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,
Expand Down
16 changes: 9 additions & 7 deletions Quotient/events/roommessageevent.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<EventRelation> relatesTo = std:: nullopt);
explicit RoomMessageEvent(const QString& plainBody,
MsgType msgType = MsgType::Text,
EventContent::TypedBase* content = nullptr);
EventContent::TypedBase* content = nullptr,
std::optional<EventRelation> relatesTo = std:: nullopt);

explicit RoomMessageEvent(const QJsonObject& obj);

Expand All @@ -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
Expand Down Expand Up @@ -141,11 +143,13 @@ class QUOTIENT_API RoomMessageEvent : public RoomEvent {

private:
std::unique_ptr<EventContent::TypedBase> _content;
std::optional<EventRelation> _relatesTo;

// FIXME: should it really be static?
static QJsonObject assembleContentJson(const QString& plainBody,
const QString& jsonMsgType,
EventContent::TypedBase* content);
EventContent::TypedBase* content,
std::optional<EventRelation> relatesTo);

Q_ENUM(MsgType)
};
Expand All @@ -164,15 +168,13 @@ namespace EventContent {
*/
class QUOTIENT_API TextContent : public TypedBase {
public:
TextContent(QString text, const QString& contentType,
std::optional<EventRelation> relatesTo = {});
TextContent(QString text, const QString& contentType);
explicit TextContent(const QJsonObject& json);

QMimeType type() const override { return mimeType; }

QMimeType mimeType;
QString body;
std::optional<EventRelation> relatesTo;

protected:
void fillJson(QJsonObject& json) const override;
Expand Down

0 comments on commit 4a8dc2a

Please sign in to comment.