Switch to new relations format
This commit is contained in:
parent
463cee7146
commit
2e77a1554f
@ -356,7 +356,7 @@ if(USE_BUNDLED_MTXCLIENT)
|
|||||||
FetchContent_Declare(
|
FetchContent_Declare(
|
||||||
MatrixClient
|
MatrixClient
|
||||||
GIT_REPOSITORY https://github.com/Nheko-Reborn/mtxclient.git
|
GIT_REPOSITORY https://github.com/Nheko-Reborn/mtxclient.git
|
||||||
GIT_TAG v0.4.1
|
GIT_TAG 70fa15de3ec84cf0c0ab6250f2e5e62f34a6d05b
|
||||||
)
|
)
|
||||||
set(BUILD_LIB_EXAMPLES OFF CACHE INTERNAL "")
|
set(BUILD_LIB_EXAMPLES OFF CACHE INTERNAL "")
|
||||||
set(BUILD_LIB_TESTS OFF CACHE INTERNAL "")
|
set(BUILD_LIB_TESTS OFF CACHE INTERNAL "")
|
||||||
|
@ -220,8 +220,7 @@
|
|||||||
"name": "mtxclient",
|
"name": "mtxclient",
|
||||||
"sources": [
|
"sources": [
|
||||||
{
|
{
|
||||||
"commit": "4951190c938740defa0988d98d5e861038622936",
|
"commit": "70fa15de3ec84cf0c0ab6250f2e5e62f34a6d05b",
|
||||||
"tag": "v0.4.1",
|
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/Nheko-Reborn/mtxclient.git"
|
"url": "https://github.com/Nheko-Reborn/mtxclient.git"
|
||||||
}
|
}
|
||||||
|
@ -2713,23 +2713,19 @@ Cache::saveTimelineMessages(lmdb::txn &txn,
|
|||||||
lmdb::dbi_put(txn, evToOrderDb, event_id, txn_order);
|
lmdb::dbi_put(txn, evToOrderDb, event_id, txn_order);
|
||||||
lmdb::dbi_del(txn, evToOrderDb, lmdb::val(txn_id));
|
lmdb::dbi_del(txn, evToOrderDb, lmdb::val(txn_id));
|
||||||
|
|
||||||
if (event.contains("content") &&
|
auto relations = mtx::accessors::relations(e);
|
||||||
event["content"].contains("m.relates_to")) {
|
if (!relations.relations.empty()) {
|
||||||
auto temp = event["content"]["m.relates_to"];
|
for (const auto &r : relations.relations) {
|
||||||
json relates_to_j = temp.contains("m.in_reply_to") &&
|
if (!r.event_id.empty()) {
|
||||||
temp["m.in_reply_to"].is_object()
|
lmdb::dbi_del(txn,
|
||||||
? temp["m.in_reply_to"]["event_id"]
|
relationsDb,
|
||||||
: temp["event_id"];
|
lmdb::val(r.event_id),
|
||||||
std::string relates_to =
|
lmdb::val(txn_id));
|
||||||
relates_to_j.is_string() ? relates_to_j.get<std::string>() : "";
|
lmdb::dbi_put(txn,
|
||||||
|
relationsDb,
|
||||||
if (!relates_to.empty()) {
|
lmdb::val(r.event_id),
|
||||||
lmdb::dbi_del(txn,
|
event_id);
|
||||||
relationsDb,
|
}
|
||||||
lmdb::val(relates_to),
|
|
||||||
lmdb::val(txn_id));
|
|
||||||
lmdb::dbi_put(
|
|
||||||
txn, relationsDb, lmdb::val(relates_to), event_id);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2808,19 +2804,16 @@ Cache::saveTimelineMessages(lmdb::txn &txn,
|
|||||||
lmdb::val(&msgIndex, sizeof(msgIndex)));
|
lmdb::val(&msgIndex, sizeof(msgIndex)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.contains("content") &&
|
auto relations = mtx::accessors::relations(e);
|
||||||
event["content"].contains("m.relates_to")) {
|
if (!relations.relations.empty()) {
|
||||||
auto temp = event["content"]["m.relates_to"];
|
for (const auto &r : relations.relations) {
|
||||||
json relates_to_j = temp.contains("m.in_reply_to") &&
|
if (!r.event_id.empty()) {
|
||||||
temp["m.in_reply_to"].is_object()
|
lmdb::dbi_put(txn,
|
||||||
? temp["m.in_reply_to"]["event_id"]
|
relationsDb,
|
||||||
: temp["event_id"];
|
lmdb::val(r.event_id),
|
||||||
std::string relates_to =
|
event_id);
|
||||||
relates_to_j.is_string() ? relates_to_j.get<std::string>() : "";
|
}
|
||||||
|
}
|
||||||
if (!relates_to.empty())
|
|
||||||
lmdb::dbi_put(
|
|
||||||
txn, relationsDb, lmdb::val(relates_to), event_id);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2901,17 +2894,14 @@ Cache::saveOldMessages(const std::string &room_id, const mtx::responses::Message
|
|||||||
txn, msg2orderDb, event_id, lmdb::val(&msgIndex, sizeof(msgIndex)));
|
txn, msg2orderDb, event_id, lmdb::val(&msgIndex, sizeof(msgIndex)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.contains("content") && event["content"].contains("m.relates_to")) {
|
auto relations = mtx::accessors::relations(e);
|
||||||
auto temp = event["content"]["m.relates_to"];
|
if (!relations.relations.empty()) {
|
||||||
json relates_to_j =
|
for (const auto &r : relations.relations) {
|
||||||
temp.contains("m.in_reply_to") && temp["m.in_reply_to"].is_object()
|
if (!r.event_id.empty()) {
|
||||||
? temp["m.in_reply_to"]["event_id"]
|
lmdb::dbi_put(
|
||||||
: temp["event_id"];
|
txn, relationsDb, lmdb::val(r.event_id), event_id);
|
||||||
std::string relates_to =
|
}
|
||||||
relates_to_j.is_string() ? relates_to_j.get<std::string>() : "";
|
}
|
||||||
|
|
||||||
if (!relates_to.empty())
|
|
||||||
lmdb::dbi_put(txn, relationsDb, lmdb::val(relates_to), event_id);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,8 +105,8 @@ DeviceVerificationFlow::DeviceVerificationFlow(QObject *,
|
|||||||
if (msg.transaction_id.has_value()) {
|
if (msg.transaction_id.has_value()) {
|
||||||
if (msg.transaction_id.value() != this->transaction_id)
|
if (msg.transaction_id.value() != this->transaction_id)
|
||||||
return;
|
return;
|
||||||
} else if (msg.relates_to.has_value()) {
|
} else if (msg.relations.references()) {
|
||||||
if (msg.relates_to.value().event_id != this->relation.event_id)
|
if (msg.relations.references() != this->relation.event_id)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ((msg.key_agreement_protocol == "curve25519-hkdf-sha256") &&
|
if ((msg.key_agreement_protocol == "curve25519-hkdf-sha256") &&
|
||||||
@ -136,8 +136,8 @@ DeviceVerificationFlow::DeviceVerificationFlow(QObject *,
|
|||||||
if (msg.transaction_id.has_value()) {
|
if (msg.transaction_id.has_value()) {
|
||||||
if (msg.transaction_id.value() != this->transaction_id)
|
if (msg.transaction_id.value() != this->transaction_id)
|
||||||
return;
|
return;
|
||||||
} else if (msg.relates_to.has_value()) {
|
} else if (msg.relations.references()) {
|
||||||
if (msg.relates_to.value().event_id != this->relation.event_id)
|
if (msg.relations.references() != this->relation.event_id)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
error_ = User;
|
error_ = User;
|
||||||
@ -152,8 +152,8 @@ DeviceVerificationFlow::DeviceVerificationFlow(QObject *,
|
|||||||
if (msg.transaction_id.has_value()) {
|
if (msg.transaction_id.has_value()) {
|
||||||
if (msg.transaction_id.value() != this->transaction_id)
|
if (msg.transaction_id.value() != this->transaction_id)
|
||||||
return;
|
return;
|
||||||
} else if (msg.relates_to.has_value()) {
|
} else if (msg.relations.references()) {
|
||||||
if (msg.relates_to.value().event_id != this->relation.event_id)
|
if (msg.relations.references() != this->relation.event_id)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -217,8 +217,8 @@ DeviceVerificationFlow::DeviceVerificationFlow(QObject *,
|
|||||||
if (msg.transaction_id.has_value()) {
|
if (msg.transaction_id.has_value()) {
|
||||||
if (msg.transaction_id.value() != this->transaction_id)
|
if (msg.transaction_id.value() != this->transaction_id)
|
||||||
return;
|
return;
|
||||||
} else if (msg.relates_to.has_value()) {
|
} else if (msg.relations.references()) {
|
||||||
if (msg.relates_to.value().event_id != this->relation.event_id)
|
if (msg.relations.references() != this->relation.event_id)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -385,8 +385,8 @@ DeviceVerificationFlow::DeviceVerificationFlow(QObject *,
|
|||||||
if (msg.transaction_id.has_value()) {
|
if (msg.transaction_id.has_value()) {
|
||||||
if (msg.transaction_id.value() != this->transaction_id)
|
if (msg.transaction_id.value() != this->transaction_id)
|
||||||
return;
|
return;
|
||||||
} else if ((msg.relates_to.has_value() && sender)) {
|
} else if (msg.relations.references()) {
|
||||||
if (msg.relates_to.value().event_id != this->relation.event_id)
|
if (msg.relations.references() != this->relation.event_id)
|
||||||
return;
|
return;
|
||||||
else {
|
else {
|
||||||
this->deviceId = QString::fromStdString(msg.from_device);
|
this->deviceId = QString::fromStdString(msg.from_device);
|
||||||
@ -402,8 +402,8 @@ DeviceVerificationFlow::DeviceVerificationFlow(QObject *,
|
|||||||
if (msg.transaction_id.has_value()) {
|
if (msg.transaction_id.has_value()) {
|
||||||
if (msg.transaction_id.value() != this->transaction_id)
|
if (msg.transaction_id.value() != this->transaction_id)
|
||||||
return;
|
return;
|
||||||
} else if (msg.relates_to.has_value()) {
|
} else if (msg.relations.references()) {
|
||||||
if (msg.relates_to.value().event_id != this->relation.event_id)
|
if (msg.relations.references() != this->relation.event_id)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
nhlog::ui()->info("Flow done on other side");
|
nhlog::ui()->info("Flow done on other side");
|
||||||
@ -526,8 +526,8 @@ DeviceVerificationFlow::handleStartMessage(const mtx::events::msg::KeyVerificati
|
|||||||
if (msg.transaction_id.has_value()) {
|
if (msg.transaction_id.has_value()) {
|
||||||
if (msg.transaction_id.value() != this->transaction_id)
|
if (msg.transaction_id.value() != this->transaction_id)
|
||||||
return;
|
return;
|
||||||
} else if (msg.relates_to.has_value()) {
|
} else if (msg.relations.references()) {
|
||||||
if (msg.relates_to.value().event_id != this->relation.event_id)
|
if (msg.relations.references() != this->relation.event_id)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ((std::find(msg.key_agreement_protocols.begin(),
|
if ((std::find(msg.key_agreement_protocols.begin(),
|
||||||
@ -625,8 +625,10 @@ DeviceVerificationFlow::startVerificationRequest()
|
|||||||
req.transaction_id = this->transaction_id;
|
req.transaction_id = this->transaction_id;
|
||||||
this->canonical_json = nlohmann::json(req);
|
this->canonical_json = nlohmann::json(req);
|
||||||
} else if (this->type == DeviceVerificationFlow::Type::RoomMsg && model_) {
|
} else if (this->type == DeviceVerificationFlow::Type::RoomMsg && model_) {
|
||||||
req.relates_to = this->relation;
|
req.relations.relations.push_back(this->relation);
|
||||||
this->canonical_json = nlohmann::json(req);
|
// Set synthesized to surpress the nheko relation extensions
|
||||||
|
req.relations.synthesized = true;
|
||||||
|
this->canonical_json = nlohmann::json(req);
|
||||||
}
|
}
|
||||||
send(req);
|
send(req);
|
||||||
setState(WaitingForOtherToAccept);
|
setState(WaitingForOtherToAccept);
|
||||||
|
@ -206,7 +206,7 @@ private:
|
|||||||
std::vector<int> sasList;
|
std::vector<int> sasList;
|
||||||
UserKeyCache their_keys;
|
UserKeyCache their_keys;
|
||||||
TimelineModel *model_;
|
TimelineModel *model_;
|
||||||
mtx::common::RelatesTo relation;
|
mtx::common::Relation relation;
|
||||||
|
|
||||||
State state_ = PromptStartVerification;
|
State state_ = PromptStartVerification;
|
||||||
Error error_ = UnknownMethod;
|
Error error_ = UnknownMethod;
|
||||||
@ -230,8 +230,12 @@ private:
|
|||||||
static_cast<int>(err->status_code));
|
static_cast<int>(err->status_code));
|
||||||
});
|
});
|
||||||
} else if (this->type == DeviceVerificationFlow::Type::RoomMsg && model_) {
|
} else if (this->type == DeviceVerificationFlow::Type::RoomMsg && model_) {
|
||||||
if constexpr (!std::is_same_v<T, mtx::events::msg::KeyVerificationRequest>)
|
if constexpr (!std::is_same_v<T,
|
||||||
msg.relates_to = this->relation;
|
mtx::events::msg::KeyVerificationRequest>) {
|
||||||
|
msg.relations.relations.push_back(this->relation);
|
||||||
|
// Set synthesized to surpress the nheko relation extensions
|
||||||
|
msg.relations.synthesized = true;
|
||||||
|
}
|
||||||
(model_)->sendMessageEvent(msg, mtx::events::to_device_content_to_type<T>);
|
(model_)->sendMessageEvent(msg, mtx::events::to_device_content_to_type<T>);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -250,31 +250,17 @@ struct EventFilesize
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct EventInReplyTo
|
struct EventRelations
|
||||||
{
|
{
|
||||||
template<class Content>
|
template<class Content>
|
||||||
using related_ev_id_t = decltype(Content::relates_to.in_reply_to.event_id);
|
using related_ev_id_t = decltype(Content::relations);
|
||||||
template<class T>
|
template<class T>
|
||||||
std::string operator()(const mtx::events::Event<T> &e)
|
mtx::common::Relations operator()(const mtx::events::Event<T> &e)
|
||||||
{
|
{
|
||||||
if constexpr (is_detected<related_ev_id_t, T>::value) {
|
if constexpr (is_detected<related_ev_id_t, T>::value) {
|
||||||
return e.content.relates_to.in_reply_to.event_id;
|
return e.content.relations;
|
||||||
}
|
}
|
||||||
return "";
|
return {};
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct EventRelatesTo
|
|
||||||
{
|
|
||||||
template<class Content>
|
|
||||||
using related_ev_id_t = decltype(Content::relates_to.event_id);
|
|
||||||
template<class T>
|
|
||||||
std::string operator()(const mtx::events::Event<T> &e)
|
|
||||||
{
|
|
||||||
if constexpr (is_detected<related_ev_id_t, T>::value) {
|
|
||||||
return e.content.relates_to.event_id;
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -434,15 +420,10 @@ mtx::accessors::mimetype(const mtx::events::collections::TimelineEvents &event)
|
|||||||
{
|
{
|
||||||
return std::visit(EventMimeType{}, event);
|
return std::visit(EventMimeType{}, event);
|
||||||
}
|
}
|
||||||
std::string
|
mtx::common::Relations
|
||||||
mtx::accessors::in_reply_to_event(const mtx::events::collections::TimelineEvents &event)
|
mtx::accessors::relations(const mtx::events::collections::TimelineEvents &event)
|
||||||
{
|
{
|
||||||
return std::visit(EventInReplyTo{}, event);
|
return std::visit(EventRelations{}, event);
|
||||||
}
|
|
||||||
std::string
|
|
||||||
mtx::accessors::relates_to_event_id(const mtx::events::collections::TimelineEvents &event)
|
|
||||||
{
|
|
||||||
return std::visit(EventRelatesTo{}, event);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string
|
std::string
|
||||||
|
@ -53,10 +53,8 @@ std::string
|
|||||||
blurhash(const mtx::events::collections::TimelineEvents &event);
|
blurhash(const mtx::events::collections::TimelineEvents &event);
|
||||||
std::string
|
std::string
|
||||||
mimetype(const mtx::events::collections::TimelineEvents &event);
|
mimetype(const mtx::events::collections::TimelineEvents &event);
|
||||||
std::string
|
mtx::common::Relations
|
||||||
in_reply_to_event(const mtx::events::collections::TimelineEvents &event);
|
relations(const mtx::events::collections::TimelineEvents &event);
|
||||||
std::string
|
|
||||||
relates_to_event_id(const mtx::events::collections::TimelineEvents &event);
|
|
||||||
std::string
|
std::string
|
||||||
transaction_id(const mtx::events::collections::TimelineEvents &event);
|
transaction_id(const mtx::events::collections::TimelineEvents &event);
|
||||||
|
|
||||||
|
27
src/Olm.cpp
27
src/Olm.cpp
@ -575,29 +575,19 @@ encrypt_group_message(const std::string &room_id, const std::string &device_id,
|
|||||||
if (!sendSessionTo.empty())
|
if (!sendSessionTo.empty())
|
||||||
olm::send_encrypted_to_device_messages(sendSessionTo, megolm_payload);
|
olm::send_encrypted_to_device_messages(sendSessionTo, megolm_payload);
|
||||||
|
|
||||||
mtx::common::ReplyRelatesTo relation;
|
|
||||||
mtx::common::RelatesTo r_relation;
|
|
||||||
|
|
||||||
// relations shouldn't be encrypted...
|
// relations shouldn't be encrypted...
|
||||||
if (body["content"].contains("m.relates_to")) {
|
mtx::common::Relations relations = mtx::common::parse_relations(body["content"]);
|
||||||
if (body["content"]["m.relates_to"].contains("m.in_reply_to")) {
|
|
||||||
relation = body["content"]["m.relates_to"];
|
|
||||||
} else if (body["content"]["m.relates_to"].contains("event_id")) {
|
|
||||||
r_relation = body["content"]["m.relates_to"];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto payload = olm::client()->encrypt_group_message(session.get(), body.dump());
|
auto payload = olm::client()->encrypt_group_message(session.get(), body.dump());
|
||||||
|
|
||||||
// Prepare the m.room.encrypted event.
|
// Prepare the m.room.encrypted event.
|
||||||
msg::Encrypted data;
|
msg::Encrypted data;
|
||||||
data.ciphertext = std::string((char *)payload.data(), payload.size());
|
data.ciphertext = std::string((char *)payload.data(), payload.size());
|
||||||
data.sender_key = olm::client()->identity_keys().curve25519;
|
data.sender_key = olm::client()->identity_keys().curve25519;
|
||||||
data.session_id = mtx::crypto::session_id(session.get());
|
data.session_id = mtx::crypto::session_id(session.get());
|
||||||
data.device_id = device_id;
|
data.device_id = device_id;
|
||||||
data.algorithm = MEGOLM_ALGO;
|
data.algorithm = MEGOLM_ALGO;
|
||||||
data.relates_to = relation;
|
data.relations = relations;
|
||||||
data.r_relates_to = r_relation;
|
|
||||||
|
|
||||||
group_session_data.message_index = olm_outbound_group_session_message_index(session.get());
|
group_session_data.message_index = olm_outbound_group_session_message_index(session.get());
|
||||||
nhlog::crypto()->debug("next message_index {}", group_session_data.message_index);
|
nhlog::crypto()->debug("next message_index {}", group_session_data.message_index);
|
||||||
@ -910,8 +900,7 @@ decryptEvent(const MegolmSessionIndex &index,
|
|||||||
body["unsigned"] = event.unsigned_data;
|
body["unsigned"] = event.unsigned_data;
|
||||||
|
|
||||||
// relations are unencrypted in content...
|
// relations are unencrypted in content...
|
||||||
if (json old_ev = event; old_ev["content"].count("m.relates_to") != 0)
|
mtx::common::add_relations(body["content"], event.content.relations);
|
||||||
body["content"]["m.relates_to"] = old_ev["content"]["m.relates_to"];
|
|
||||||
|
|
||||||
mtx::events::collections::TimelineEvent te;
|
mtx::events::collections::TimelineEvent te;
|
||||||
try {
|
try {
|
||||||
|
@ -293,16 +293,16 @@ EventStore::handleSync(const mtx::responses::Timeline &events)
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (const auto &event : events.events) {
|
for (const auto &event : events.events) {
|
||||||
std::string relates_to;
|
std::set<std::string> relates_to;
|
||||||
if (auto redaction =
|
if (auto redaction =
|
||||||
std::get_if<mtx::events::RedactionEvent<mtx::events::msg::Redaction>>(
|
std::get_if<mtx::events::RedactionEvent<mtx::events::msg::Redaction>>(
|
||||||
&event)) {
|
&event)) {
|
||||||
// fixup reactions
|
// fixup reactions
|
||||||
auto redacted = events_by_id_.object({room_id_, redaction->redacts});
|
auto redacted = events_by_id_.object({room_id_, redaction->redacts});
|
||||||
if (redacted) {
|
if (redacted) {
|
||||||
auto id = mtx::accessors::relates_to_event_id(*redacted);
|
auto id = mtx::accessors::relations(*redacted);
|
||||||
if (!id.empty()) {
|
if (id.annotates()) {
|
||||||
auto idx = idToIndex(id);
|
auto idx = idToIndex(id.annotates()->event_id);
|
||||||
if (idx) {
|
if (idx) {
|
||||||
events_by_id_.remove(
|
events_by_id_.remove(
|
||||||
{room_id_, redaction->redacts});
|
{room_id_, redaction->redacts});
|
||||||
@ -312,20 +312,17 @@ EventStore::handleSync(const mtx::responses::Timeline &events)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
relates_to = redaction->redacts;
|
relates_to.insert(redaction->redacts);
|
||||||
} else if (auto reaction =
|
|
||||||
std::get_if<mtx::events::RoomEvent<mtx::events::msg::Reaction>>(
|
|
||||||
&event)) {
|
|
||||||
relates_to = reaction->content.relates_to.event_id;
|
|
||||||
} else {
|
} else {
|
||||||
relates_to = mtx::accessors::in_reply_to_event(event);
|
for (const auto &r : mtx::accessors::relations(event).relations)
|
||||||
|
relates_to.insert(r.event_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!relates_to.empty()) {
|
for (const auto &relates_to_id : relates_to) {
|
||||||
auto idx = cache::client()->getTimelineIndex(room_id_, relates_to);
|
auto idx = cache::client()->getTimelineIndex(room_id_, relates_to_id);
|
||||||
if (idx) {
|
if (idx) {
|
||||||
events_by_id_.remove({room_id_, relates_to});
|
events_by_id_.remove({room_id_, relates_to_id});
|
||||||
decryptedEvents_.remove({room_id_, relates_to});
|
decryptedEvents_.remove({room_id_, relates_to_id});
|
||||||
events_.remove({room_id_, *idx});
|
events_.remove({room_id_, *idx});
|
||||||
emit dataChanged(toExternalIdx(*idx), toExternalIdx(*idx));
|
emit dataChanged(toExternalIdx(*idx), toExternalIdx(*idx));
|
||||||
}
|
}
|
||||||
@ -430,13 +427,14 @@ EventStore::reactions(const std::string &event_id)
|
|||||||
|
|
||||||
if (auto reaction = std::get_if<mtx::events::RoomEvent<mtx::events::msg::Reaction>>(
|
if (auto reaction = std::get_if<mtx::events::RoomEvent<mtx::events::msg::Reaction>>(
|
||||||
related_event);
|
related_event);
|
||||||
reaction && reaction->content.relates_to.key) {
|
reaction && reaction->content.relations.annotates() &&
|
||||||
auto &agg = aggregation[reaction->content.relates_to.key.value()];
|
reaction->content.relations.annotates()->key) {
|
||||||
|
auto key = reaction->content.relations.annotates()->key.value();
|
||||||
|
auto &agg = aggregation[key];
|
||||||
|
|
||||||
if (agg.count == 0) {
|
if (agg.count == 0) {
|
||||||
Reaction temp{};
|
Reaction temp{};
|
||||||
temp.key_ =
|
temp.key_ = QString::fromStdString(key);
|
||||||
QString::fromStdString(reaction->content.relates_to.key.value());
|
|
||||||
reactions.push_back(temp);
|
reactions.push_back(temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -691,8 +689,7 @@ EventStore::decryptEvent(const IdIndex &idx,
|
|||||||
body["unsigned"] = e.unsigned_data;
|
body["unsigned"] = e.unsigned_data;
|
||||||
|
|
||||||
// relations are unencrypted in content...
|
// relations are unencrypted in content...
|
||||||
if (json old_ev = e; old_ev["content"].count("m.relates_to") != 0)
|
mtx::common::add_relations(body["content"], e.content.relations);
|
||||||
body["content"]["m.relates_to"] = old_ev["content"]["m.relates_to"];
|
|
||||||
|
|
||||||
json event_array = json::array();
|
json event_array = json::array();
|
||||||
event_array.push_back(body);
|
event_array.push_back(body);
|
||||||
|
@ -294,7 +294,8 @@ InputBar::message(QString msg, MarkdownOverride useMarkdown)
|
|||||||
text.formatted_body =
|
text.formatted_body =
|
||||||
utils::getFormattedQuoteBody(related, msg.toHtmlEscaped()).toStdString();
|
utils::getFormattedQuoteBody(related, msg.toHtmlEscaped()).toStdString();
|
||||||
|
|
||||||
text.relates_to.in_reply_to.event_id = related.related_event;
|
text.relations.relations.push_back(
|
||||||
|
{mtx::common::RelationType::InReplyTo, related.related_event});
|
||||||
room->resetReply();
|
room->resetReply();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -316,7 +317,8 @@ InputBar::emote(QString msg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!room->reply().isEmpty()) {
|
if (!room->reply().isEmpty()) {
|
||||||
emote.relates_to.in_reply_to.event_id = room->reply().toStdString();
|
emote.relations.relations.push_back(
|
||||||
|
{mtx::common::RelationType::InReplyTo, room->reply().toStdString()});
|
||||||
room->resetReply();
|
room->resetReply();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -346,7 +348,8 @@ InputBar::image(const QString &filename,
|
|||||||
image.url = url.toStdString();
|
image.url = url.toStdString();
|
||||||
|
|
||||||
if (!room->reply().isEmpty()) {
|
if (!room->reply().isEmpty()) {
|
||||||
image.relates_to.in_reply_to.event_id = room->reply().toStdString();
|
image.relations.relations.push_back(
|
||||||
|
{mtx::common::RelationType::InReplyTo, room->reply().toStdString()});
|
||||||
room->resetReply();
|
room->resetReply();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -371,7 +374,8 @@ InputBar::file(const QString &filename,
|
|||||||
file.url = url.toStdString();
|
file.url = url.toStdString();
|
||||||
|
|
||||||
if (!room->reply().isEmpty()) {
|
if (!room->reply().isEmpty()) {
|
||||||
file.relates_to.in_reply_to.event_id = room->reply().toStdString();
|
file.relations.relations.push_back(
|
||||||
|
{mtx::common::RelationType::InReplyTo, room->reply().toStdString()});
|
||||||
room->resetReply();
|
room->resetReply();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -397,7 +401,8 @@ InputBar::audio(const QString &filename,
|
|||||||
audio.url = url.toStdString();
|
audio.url = url.toStdString();
|
||||||
|
|
||||||
if (!room->reply().isEmpty()) {
|
if (!room->reply().isEmpty()) {
|
||||||
audio.relates_to.in_reply_to.event_id = room->reply().toStdString();
|
audio.relations.relations.push_back(
|
||||||
|
{mtx::common::RelationType::InReplyTo, room->reply().toStdString()});
|
||||||
room->resetReply();
|
room->resetReply();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -422,7 +427,8 @@ InputBar::video(const QString &filename,
|
|||||||
video.url = url.toStdString();
|
video.url = url.toStdString();
|
||||||
|
|
||||||
if (!room->reply().isEmpty()) {
|
if (!room->reply().isEmpty()) {
|
||||||
video.relates_to.in_reply_to.event_id = room->reply().toStdString();
|
video.relations.relations.push_back(
|
||||||
|
{mtx::common::RelationType::InReplyTo, room->reply().toStdString()});
|
||||||
room->resetReply();
|
room->resetReply();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -360,7 +360,7 @@ TimelineModel::data(const mtx::events::collections::TimelineEvents &event, int r
|
|||||||
const static QRegularExpression replyFallback(
|
const static QRegularExpression replyFallback(
|
||||||
"<mx-reply>.*</mx-reply>", QRegularExpression::DotMatchesEverythingOption);
|
"<mx-reply>.*</mx-reply>", QRegularExpression::DotMatchesEverythingOption);
|
||||||
|
|
||||||
bool isReply = !in_reply_to_event(event).empty();
|
bool isReply = relations(event).reply_to().has_value();
|
||||||
|
|
||||||
auto formattedBody_ = QString::fromStdString(formatted_body(event));
|
auto formattedBody_ = QString::fromStdString(formatted_body(event));
|
||||||
if (formattedBody_.isEmpty()) {
|
if (formattedBody_.isEmpty()) {
|
||||||
@ -442,7 +442,7 @@ TimelineModel::data(const mtx::events::collections::TimelineEvents &event, int r
|
|||||||
return cache::isRoomEncrypted(room_id_.toStdString());
|
return cache::isRoomEncrypted(room_id_.toStdString());
|
||||||
}
|
}
|
||||||
case ReplyTo:
|
case ReplyTo:
|
||||||
return QVariant(QString::fromStdString(in_reply_to_event(event)));
|
return QVariant(QString::fromStdString(relations(event).reply_to().value_or("")));
|
||||||
case Reactions: {
|
case Reactions: {
|
||||||
auto id = event_id(event);
|
auto id = event_id(event);
|
||||||
return QVariant::fromValue(events.reactions(id));
|
return QVariant::fromValue(events.reactions(id));
|
||||||
|
@ -503,9 +503,11 @@ TimelineViewManager::queueReactionMessage(const QString &reactedEvent, const QSt
|
|||||||
// If selfReactedEvent is empty, that means we haven't previously reacted
|
// If selfReactedEvent is empty, that means we haven't previously reacted
|
||||||
if (selfReactedEvent.isEmpty()) {
|
if (selfReactedEvent.isEmpty()) {
|
||||||
mtx::events::msg::Reaction reaction;
|
mtx::events::msg::Reaction reaction;
|
||||||
reaction.relates_to.rel_type = mtx::common::RelationType::Annotation;
|
mtx::common::Relation rel;
|
||||||
reaction.relates_to.event_id = reactedEvent.toStdString();
|
rel.rel_type = mtx::common::RelationType::Annotation;
|
||||||
reaction.relates_to.key = reactionKey.toStdString();
|
rel.event_id = reactedEvent.toStdString();
|
||||||
|
rel.key = reactionKey.toStdString();
|
||||||
|
reaction.relations.relations.push_back(rel);
|
||||||
|
|
||||||
timeline_->sendMessageEvent(reaction, mtx::events::EventType::Reaction);
|
timeline_->sendMessageEvent(reaction, mtx::events::EventType::Reaction);
|
||||||
// Otherwise, we have previously reacted and the reaction should be redacted
|
// Otherwise, we have previously reacted and the reaction should be redacted
|
||||||
|
Loading…
Reference in New Issue
Block a user