Skip to content

Commit

Permalink
Merge #805(nvrWhere): Reply to All RoomMessageEvents
Browse files Browse the repository at this point in the history
  • Loading branch information
KitsuneRal authored Oct 2, 2024
2 parents 9827025 + fee5b8e commit 28ce82e
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 58 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
79 changes: 31 additions & 48 deletions Quotient/events/roommessageevent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,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;
Expand Down Expand Up @@ -86,49 +87,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(relatesTo.value()));
if (relatesTo->type == EventRelation::ReplacementType) {
QJsonObject newContentJson;
if (auto* textContent = static_cast<const TextContent*>(content);
textContent && textContent->mimeType.inherits("text/html"_L1)) {
newContentJson.insert(FormatKey, 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,17 +139,21 @@ 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;
}

fromJson(content[RelatesToKey], _relatesTo);
} else {
qCWarning(EVENTS) << "No body or msgtype in room message event";
qCWarning(EVENTS) << formatJson << obj;
Expand Down Expand Up @@ -198,7 +201,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 +215,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 @@ -319,23 +321,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 @@ -354,28 +355,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(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 28ce82e

Please sign in to comment.