aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexey Rusakov <Kitsune-Ral@users.sf.net>2022-01-21 02:04:10 +0100
committerAlexey Rusakov <Kitsune-Ral@users.sf.net>2022-01-21 02:04:34 +0100
commitfdff209744ac4c422f63fe2549aa0132df7e6292 (patch)
tree55ebfcd92da71aa7809f311cc1d2550ff9e51db0
parent142fc5a21f541e2a7592119df075a543527195b9 (diff)
downloadlibquotient-fdff209744ac4c422f63fe2549aa0132df7e6292.tar.gz
libquotient-fdff209744ac4c422f63fe2549aa0132df7e6292.zip
Redo EventRelation; deprecate RelatesTo
RelatesTo and EventRelation have been two means to the same end in two different contexts. (Modernised) EventRelation is the one used now both for ReactionEvent and EventContent::TextContent. The modernisation mostly boils down to using inline variables instead of functions to return relation types and switching to QLatin1String from const char* (because we know exactly that those constants are Latin-1 and QLatin1String is more efficient than const char* to compare/convert to QString).
-rw-r--r--CMakeLists.txt3
-rw-r--r--lib/events/eventrelation.cpp38
-rw-r--r--lib/events/eventrelation.h52
-rw-r--r--lib/events/reactionevent.cpp29
-rw-r--r--lib/events/reactionevent.h32
-rw-r--r--lib/events/roommessageevent.cpp38
-rw-r--r--lib/events/roommessageevent.h27
-rw-r--r--lib/room.cpp11
-rw-r--r--lib/room.h5
-rw-r--r--quotest/quotest.cpp2
10 files changed, 128 insertions, 109 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index fd5f1dca..df193b94 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -153,6 +153,7 @@ list(APPEND lib_SRCS
lib/events/stateevent.h lib/events/stateevent.cpp
lib/events/simplestateevents.h
lib/events/eventcontent.h lib/events/eventcontent.cpp
+ lib/events/eventrelation.h lib/events/eventrelation.cpp
lib/events/roomcreateevent.h lib/events/roomcreateevent.cpp
lib/events/roomtombstoneevent.h lib/events/roomtombstoneevent.cpp
lib/events/roommessageevent.h lib/events/roommessageevent.cpp
@@ -162,7 +163,7 @@ list(APPEND lib_SRCS
lib/events/typingevent.h lib/events/typingevent.cpp
lib/events/accountdataevents.h
lib/events/receiptevent.h lib/events/receiptevent.cpp
- lib/events/reactionevent.h lib/events/reactionevent.cpp
+ lib/events/reactionevent.h
lib/events/callinviteevent.h lib/events/callinviteevent.cpp
lib/events/callcandidatesevent.h
lib/events/callanswerevent.h lib/events/callanswerevent.cpp
diff --git a/lib/events/eventrelation.cpp b/lib/events/eventrelation.cpp
new file mode 100644
index 00000000..04972f45
--- /dev/null
+++ b/lib/events/eventrelation.cpp
@@ -0,0 +1,38 @@
+// SPDX-FileCopyrightText: 2022 Kitsune Ral <kitsune-ral@users.sf.net>
+// SPDX-License-Identifier: LGPL-2.1-or-later
+
+#include "eventrelation.h"
+
+#include "../logging.h"
+#include "event.h"
+
+using namespace Quotient;
+
+void JsonObjectConverter<EventRelation>::dumpTo(QJsonObject& jo,
+ const EventRelation& pod)
+{
+ if (pod.type.isEmpty()) {
+ qCWarning(MAIN) << "Empty relation type; won't dump to JSON";
+ return;
+ }
+ jo.insert(RelTypeKey, pod.type);
+ jo.insert(EventIdKey, pod.eventId);
+ if (pod.type == EventRelation::AnnotationType)
+ jo.insert(QStringLiteral("key"), pod.key);
+}
+
+void JsonObjectConverter<EventRelation>::fillFrom(const QJsonObject& jo,
+ EventRelation& pod)
+{
+ if (const auto replyJson = jo.value(EventRelation::ReplyType).toObject();
+ !replyJson.isEmpty()) {
+ pod.type = EventRelation::ReplyType;
+ fromJson(replyJson[EventIdKeyL], pod.eventId);
+ } else {
+ // The experimental logic for generic relationships (MSC1849)
+ fromJson(jo[RelTypeKey], pod.type);
+ fromJson(jo[EventIdKeyL], pod.eventId);
+ if (pod.type == EventRelation::AnnotationType)
+ fromJson(jo["key"_ls], pod.key);
+ }
+}
diff --git a/lib/events/eventrelation.h b/lib/events/eventrelation.h
new file mode 100644
index 00000000..e445ee42
--- /dev/null
+++ b/lib/events/eventrelation.h
@@ -0,0 +1,52 @@
+// SPDX-FileCopyrightText: 2022 Kitsune Ral <kitsune-ral@users.sf.net>
+// SPDX-License-Identifier: LGPL-2.1-or-later
+
+#pragma once
+
+#include "converters.h"
+
+namespace Quotient {
+
+[[maybe_unused]] constexpr auto RelatesToKey = "m.relates_to"_ls;
+constexpr auto RelTypeKey = "rel_type"_ls;
+
+struct QUOTIENT_API EventRelation {
+ using reltypeid_t = QLatin1String;
+
+ QString type;
+ QString eventId;
+ QString key = {}; // Only used for m.annotation for now
+
+ static constexpr auto ReplyType = "m.in_reply_to"_ls;
+ static constexpr auto AnnotationType = "m.annotation"_ls;
+ static constexpr auto ReplacementType = "m.replace"_ls;
+
+ static EventRelation replyTo(QString eventId)
+ {
+ return { ReplyType, std::move(eventId) };
+ }
+ static EventRelation annotate(QString eventId, QString key)
+ {
+ return { AnnotationType, std::move(eventId), std::move(key) };
+ }
+ static EventRelation replace(QString eventId)
+ {
+ return { ReplacementType, std::move(eventId) };
+ }
+
+ [[deprecated("Use ReplyRelation variable instead")]]
+ static constexpr auto Reply() { return ReplyType; }
+ [[deprecated("Use AnnotationRelation variable instead")]] //
+ static constexpr auto Annotation() { return AnnotationType; }
+ [[deprecated("Use ReplacementRelation variable instead")]] //
+ static constexpr auto Replacement() { return ReplacementType; }
+};
+
+template <>
+struct QUOTIENT_API JsonObjectConverter<EventRelation> {
+ static void dumpTo(QJsonObject& jo, const EventRelation& pod);
+ static void fillFrom(const QJsonObject& jo, EventRelation& pod);
+};
+
+}
+
diff --git a/lib/events/reactionevent.cpp b/lib/events/reactionevent.cpp
deleted file mode 100644
index b53fffd6..00000000
--- a/lib/events/reactionevent.cpp
+++ /dev/null
@@ -1,29 +0,0 @@
-// SPDX-FileCopyrightText: 2019 Kitsune Ral <kitsune-ral@users.sf.net>
-// SPDX-License-Identifier: LGPL-2.1-or-later
-
-#include "reactionevent.h"
-
-using namespace Quotient;
-
-void JsonObjectConverter<EventRelation>::dumpTo(
- QJsonObject& jo, const EventRelation& pod)
-{
- if (pod.type.isEmpty()) {
- qCWarning(MAIN) << "Empty relation type; won't dump to JSON";
- return;
- }
- jo.insert(QStringLiteral("rel_type"), pod.type);
- jo.insert(EventIdKey, pod.eventId);
- if (pod.type == EventRelation::Annotation())
- jo.insert(QStringLiteral("key"), pod.key);
-}
-
-void JsonObjectConverter<EventRelation>::fillFrom(
- const QJsonObject& jo, EventRelation& pod)
-{
- // The experimental logic for generic relationships (MSC1849)
- fromJson(jo["rel_type"_ls], pod.type);
- fromJson(jo[EventIdKeyL], pod.eventId);
- if (pod.type == EventRelation::Annotation())
- fromJson(jo["key"_ls], pod.key);
-}
diff --git a/lib/events/reactionevent.h b/lib/events/reactionevent.h
index ce11eaed..b3cb3ca7 100644
--- a/lib/events/reactionevent.h
+++ b/lib/events/reactionevent.h
@@ -4,38 +4,10 @@
#pragma once
#include "roomevent.h"
+#include "eventrelation.h"
namespace Quotient {
-struct QUOTIENT_API EventRelation {
- using reltypeid_t = const char*;
- static constexpr reltypeid_t Reply() { return "m.in_reply_to"; }
- static constexpr reltypeid_t Annotation() { return "m.annotation"; }
- static constexpr reltypeid_t Replacement() { return "m.replace"; }
-
- QString type;
- QString eventId;
- QString key = {}; // Only used for m.annotation for now
-
- static EventRelation replyTo(QString eventId)
- {
- return { Reply(), std::move(eventId) };
- }
- static EventRelation annotate(QString eventId, QString key)
- {
- return { Annotation(), std::move(eventId), std::move(key) };
- }
- static EventRelation replace(QString eventId)
- {
- return { Replacement(), std::move(eventId) };
- }
-};
-template <>
-struct QUOTIENT_API JsonObjectConverter<EventRelation> {
- static void dumpTo(QJsonObject& jo, const EventRelation& pod);
- static void fillFrom(const QJsonObject& jo, EventRelation& pod);
-};
-
class QUOTIENT_API ReactionEvent : public RoomEvent {
public:
DEFINE_EVENT_TYPEID("m.reaction", ReactionEvent)
@@ -47,7 +19,7 @@ public:
explicit ReactionEvent(const QJsonObject& obj) : RoomEvent(typeId(), obj) {}
EventRelation relation() const
{
- return contentPart<EventRelation>("m.relates_to"_ls);
+ return contentPart<EventRelation>(RelatesToKey);
}
};
REGISTER_EVENT_TYPE(ReactionEvent)
diff --git a/lib/events/roommessageevent.cpp b/lib/events/roommessageevent.cpp
index 5ab0f845..c07a4f3c 100644
--- a/lib/events/roommessageevent.cpp
+++ b/lib/events/roommessageevent.cpp
@@ -6,6 +6,7 @@
#include "roommessageevent.h"
#include "logging.h"
+#include "events/eventrelation.h"
#include <QtCore/QFileInfo>
#include <QtCore/QMimeDatabase>
@@ -20,7 +21,6 @@ using namespace EventContent;
using MsgType = RoomMessageEvent::MsgType;
namespace { // Supporting internal definitions
-
constexpr auto RelatesToKey = "m.relates_to"_ls;
constexpr auto MsgTypeKey = "msgtype"_ls;
constexpr auto FormattedBodyKey = "formatted_body"_ls;
@@ -84,9 +84,9 @@ MsgType jsonToMsgType(const QString& matrixType)
return MsgType::Unknown;
}
-inline bool isReplacement(const Omittable<RelatesTo>& rel)
+inline bool isReplacement(const Omittable<EventRelation>& rel)
{
- return rel && rel->type == RelatesTo::ReplacementTypeId();
+ return rel && rel->type == EventRelation::ReplacementType;
}
} // anonymous namespace
@@ -105,10 +105,10 @@ QJsonObject RoomMessageEvent::assembleContentJson(const QString& plainBody,
<< "messages; the relation has been stripped off";
} else {
// After the above, we know for sure that the content is TextContent
- // and that its RelatesTo structure is not omitted
+ // and that its EventRelation structure is not omitted
auto* textContent = static_cast<const TextContent*>(content);
Q_ASSERT(textContent && textContent->relatesTo.has_value());
- if (textContent->relatesTo->type == RelatesTo::ReplacementTypeId()) {
+ if (textContent->relatesTo->type == EventRelation::ReplacementType) {
auto newContentJson = json.take("m.new_content"_ls).toObject();
newContentJson.insert(BodyKey, plainBody);
newContentJson.insert(MsgTypeKey, jsonMsgType);
@@ -269,7 +269,7 @@ QString RoomMessageEvent::rawMsgTypeForFile(const QFileInfo& fi)
}
TextContent::TextContent(QString text, const QString& contentType,
- Omittable<RelatesTo> relatesTo)
+ Omittable<EventRelation> relatesTo)
: mimeType(QMimeDatabase().mimeTypeForName(contentType))
, body(std::move(text))
, relatesTo(std::move(relatesTo))
@@ -278,26 +278,8 @@ TextContent::TextContent(QString text, const QString& contentType,
mimeType = QMimeDatabase().mimeTypeForName("text/html");
}
-namespace Quotient {
-// Overload the default fromJson<> logic that defined in converters.h
-// as we want
-template <>
-Omittable<RelatesTo> fromJson(const QJsonValue& jv)
-{
- const auto jo = jv.toObject();
- if (jo.isEmpty())
- return none;
- const auto replyJson = jo.value(RelatesTo::ReplyTypeId()).toObject();
- if (!replyJson.isEmpty())
- return replyTo(fromJson<QString>(replyJson[EventIdKeyL]));
-
- return RelatesTo { jo.value("rel_type"_ls).toString(),
- jo.value(EventIdKeyL).toString() };
-}
-} // namespace Quotient
-
TextContent::TextContent(const QJsonObject& json)
- : relatesTo(fromJson<Omittable<RelatesTo>>(json[RelatesToKey]))
+ : relatesTo(fromJson<Omittable<EventRelation>>(json[RelatesToKey]))
{
QMimeDatabase db;
static const auto PlainTextMimeType = db.mimeTypeForName("text/plain");
@@ -331,13 +313,13 @@ void TextContent::fillJson(QJsonObject* json) const
if (relatesTo) {
json->insert(
QStringLiteral("m.relates_to"),
- relatesTo->type == RelatesTo::ReplyTypeId()
+ relatesTo->type == EventRelation::ReplyType
? QJsonObject { { relatesTo->type,
QJsonObject {
{ EventIdKey, relatesTo->eventId } } } }
- : QJsonObject { { "rel_type", relatesTo->type },
+ : QJsonObject { { RelTypeKey, relatesTo->type },
{ EventIdKey, relatesTo->eventId } });
- if (relatesTo->type == RelatesTo::ReplacementTypeId()) {
+ if (relatesTo->type == EventRelation::ReplacementType) {
QJsonObject newContentJson;
if (mimeType.inherits("text/html")) {
newContentJson.insert(FormatKey, HtmlContentTypeId);
diff --git a/lib/events/roommessageevent.h b/lib/events/roommessageevent.h
index 0c901b7a..44ef05fb 100644
--- a/lib/events/roommessageevent.h
+++ b/lib/events/roommessageevent.h
@@ -6,6 +6,7 @@
#pragma once
#include "eventcontent.h"
+#include "eventrelation.h"
#include "roomevent.h"
class QFileInfo;
@@ -97,23 +98,25 @@ REGISTER_EVENT_TYPE(RoomMessageEvent)
using MessageEventType = RoomMessageEvent::MsgType;
namespace EventContent {
- // Additional event content types
- struct RelatesTo {
- static constexpr const char* ReplyTypeId() { return "m.in_reply_to"; }
- static constexpr const char* ReplacementTypeId() { return "m.replace"; }
- QString type; // The only supported relation so far
- QString eventId;
+ struct [[deprecated("Use Quotient::EventRelation instead")]] RelatesTo
+ : EventRelation {
+ static constexpr auto ReplyTypeId() { return Reply(); }
+ static constexpr auto ReplacementTypeId() { return Replacement(); }
};
- inline RelatesTo replyTo(QString eventId)
+ [[deprecated("Use EventRelation::replyTo() instead")]]
+ inline auto replyTo(QString eventId)
{
- return { RelatesTo::ReplyTypeId(), std::move(eventId) };
+ return EventRelation::replyTo(std::move(eventId));
}
- inline RelatesTo replacementOf(QString eventId)
+ [[deprecated("Use EventRelation::replace() instead")]]
+ inline auto replacementOf(QString eventId)
{
- return { RelatesTo::ReplacementTypeId(), std::move(eventId) };
+ return EventRelation::replace(std::move(eventId));
}
+ // Additional event content types
+
/**
* Rich text content for m.text, m.emote, m.notice
*
@@ -123,14 +126,14 @@ namespace EventContent {
class QUOTIENT_API TextContent : public TypedBase {
public:
TextContent(QString text, const QString& contentType,
- Omittable<RelatesTo> relatesTo = none);
+ Omittable<EventRelation> relatesTo = none);
explicit TextContent(const QJsonObject& json);
QMimeType type() const override { return mimeType; }
QMimeType mimeType;
QString body;
- Omittable<RelatesTo> relatesTo;
+ Omittable<EventRelation> relatesTo;
protected:
void fillJson(QJsonObject* json) const override;
diff --git a/lib/room.cpp b/lib/room.cpp
index 55efb5b9..ba63f50d 100644
--- a/lib/room.cpp
+++ b/lib/room.cpp
@@ -996,14 +996,14 @@ Room::findPendingEvent(const QString& txnId) const
});
}
-const Room::RelatedEvents Room::relatedEvents(const QString& evtId,
- const char* relType) const
+const Room::RelatedEvents Room::relatedEvents(
+ const QString& evtId, EventRelation::reltypeid_t relType) const
{
return d->relations.value({ evtId, relType });
}
-const Room::RelatedEvents Room::relatedEvents(const RoomEvent& evt,
- const char* relType) const
+const Room::RelatedEvents Room::relatedEvents(
+ const RoomEvent& evt, EventRelation::reltypeid_t relType) const
{
return relatedEvents(evt.id(), relType);
}
@@ -2506,8 +2506,7 @@ bool Room::Private::processRedaction(const RedactionEvent& redaction)
}
if (const auto* reaction = eventCast<ReactionEvent>(oldEvent)) {
const auto& targetEvtId = reaction->relation().eventId;
- const auto lookupKey =
- qMakePair(targetEvtId, EventRelation::Annotation());
+ const QPair lookupKey { targetEvtId, EventRelation::AnnotationType };
if (relations.contains(lookupKey)) {
relations[lookupKey].removeOne(reaction);
emit q->updatedEvent(targetEvtId);
diff --git a/lib/room.h b/lib/room.h
index 61f475e8..15bc7648 100644
--- a/lib/room.h
+++ b/lib/room.h
@@ -21,6 +21,7 @@
#include "events/roommessageevent.h"
#include "events/roomcreateevent.h"
#include "events/roomtombstoneevent.h"
+#include "events/eventrelation.h"
#include <QtCore/QJsonObject>
#include <QtGui/QImage>
@@ -394,9 +395,9 @@ public:
PendingEvents::const_iterator findPendingEvent(const QString& txnId) const;
const RelatedEvents relatedEvents(const QString& evtId,
- const char* relType) const;
+ EventRelation::reltypeid_t relType) const;
const RelatedEvents relatedEvents(const RoomEvent& evt,
- const char* relType) const;
+ EventRelation::reltypeid_t relType) const;
const RoomCreateEvent* creation() const
{
diff --git a/quotest/quotest.cpp b/quotest/quotest.cpp
index 5a5642fe..40bc456b 100644
--- a/quotest/quotest.cpp
+++ b/quotest/quotest.cpp
@@ -381,7 +381,7 @@ TEST_IMPL(sendReaction)
if (actualTargetEvtId != targetEvtId)
return false;
const auto reactions = targetRoom->relatedEvents(
- targetEvtId, EventRelation::Annotation());
+ targetEvtId, EventRelation::AnnotationType);
// It's a test room, assuming no interference there should
// be exactly one reaction
if (reactions.size() != 1)