aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2022-11-12 15:07:16 +0100
committerdec05eba <dec05eba@protonmail.com>2022-11-12 15:07:16 +0100
commit224a5f3b2ed2141a94940fe73fc8ccb4b2f8d962 (patch)
tree4a51b48205042279d7cdfa065ae55120a09cc9d9 /src
parent4197fd3d7aaa84197eb17e700fb27093293f228b (diff)
Matrix: fix editing reply breaking body and formatted text, edits should always show latest edit, set read marker to proper latest message
Diffstat (limited to 'src')
-rw-r--r--src/QuickMedia.cpp52
-rw-r--r--src/plugins/Matrix.cpp60
2 files changed, 67 insertions, 45 deletions
diff --git a/src/QuickMedia.cpp b/src/QuickMedia.cpp
index 57f54a4..e8c76d7 100644
--- a/src/QuickMedia.cpp
+++ b/src/QuickMedia.cpp
@@ -5630,16 +5630,18 @@ namespace QuickMedia {
} else {
// TODO: Properly check reply message objects for mention of user instead of message data, but only when synapse fixes that notifications
// are not triggered by reply to a message with our display name/user id.
- Message *edited_message_ref = static_cast<Message*>(body_item->userdata);
- std::string qm_formatted_text = message_to_qm_text(matrix, message.get());
-
- body_item->set_description(std::move(qm_formatted_text));
- if(message->user != me && message_contains_user_mention(matrix, message.get(), my_display_name, me->user_id))
- body_item->set_description_color(get_theme().attention_alert_text_color, true);
- else
- body_item->set_description_color(get_theme().text_color);
- message->replaces = edited_message_ref;
- edited_message_ref->replaced_by = message;
+ Message *edited_message_ref = get_latest_message_in_edit_chain(static_cast<Message*>(body_item->userdata));
+ if(message->timestamp > edited_message_ref->timestamp) {
+ std::string qm_formatted_text = message_to_qm_text(matrix, message.get());
+
+ body_item->set_description(std::move(qm_formatted_text));
+ if(message->user != me && message_contains_user_mention(matrix, message.get(), my_display_name, me->user_id))
+ body_item->set_description_color(get_theme().attention_alert_text_color, true);
+ else
+ body_item->set_description_color(get_theme().text_color);
+ message->replaces = edited_message_ref;
+ edited_message_ref->replaced_by = message;
+ }
}
it = unreferenced_events.erase(it);
} else {
@@ -5671,16 +5673,18 @@ namespace QuickMedia {
} else {
// TODO: Properly check reply message objects for mention of user instead of message data, but only when synapse fixes that notifications
// are not triggered by reply to a message with our display name/user id.
- Message *edited_message_ref = static_cast<Message*>(body_item->userdata);
- std::string qm_formatted_text = formatted_text_to_qm_text(matrix, message->body.c_str(), message->body.size(), true);
-
- body_item->set_description(std::move(qm_formatted_text));
- if(message->user != me && message_contains_user_mention(matrix, message.get(), my_display_name, me->user_id))
- body_item->set_description_color(get_theme().attention_alert_text_color, true);
- else
- body_item->set_description_color(get_theme().text_color);
- message->replaces = edited_message_ref;
- edited_message_ref->replaced_by = message;
+ Message *edited_message_ref = get_latest_message_in_edit_chain(static_cast<Message*>(body_item->userdata));
+ if(message->timestamp > edited_message_ref->timestamp) {
+ std::string qm_formatted_text = formatted_text_to_qm_text(matrix, message->body.c_str(), message->body.size(), true);
+
+ body_item->set_description(std::move(qm_formatted_text));
+ if(message->user != me && message_contains_user_mention(matrix, message.get(), my_display_name, me->user_id))
+ body_item->set_description_color(get_theme().attention_alert_text_color, true);
+ else
+ body_item->set_description_color(get_theme().text_color);
+ message->replaces = edited_message_ref;
+ edited_message_ref->replaced_by = message;
+ }
}
} else {
unreferenced_events.push_back(message);
@@ -7588,8 +7592,8 @@ namespace QuickMedia {
// TODO: Only set read marker once every second if the message is not the last message in the room
auto body_items = tabs[selected_tab].body->get_items();
int last_timeline_message = (int)body_items.size() - 1;
- for(int i = last_timeline_message - 1; i >= 0; --i) {
- BodyItem *item = body_items[i].get();
+ for(; last_timeline_message >= 0; --last_timeline_message) {
+ BodyItem *item = body_items[last_timeline_message].get();
Message *message = static_cast<Message*>(item->userdata);
if(item->visible && message && message_is_timeline(message))
break;
@@ -7604,9 +7608,7 @@ namespace QuickMedia {
// TODO: Maybe set this instead when the mention is visible on the screen?
current_room->unread_notification_count = 0;
- Message *read_message = static_cast<Message*>(body_items[last_timeline_message]->userdata);
- if(read_message->replaced_by)
- read_message = read_message->replaced_by.get();
+ Message *read_message = get_latest_message_in_edit_chain(static_cast<Message*>(body_items[last_timeline_message]->userdata));
// TODO: What if two messages have the same timestamp?
if(!read_message->event_id.empty() && read_message->timestamp > current_room->last_read_message_timestamp) {
matrix_chat_page->set_room_as_read(current_room);
diff --git a/src/plugins/Matrix.cpp b/src/plugins/Matrix.cpp
index 515ef7a..a821158 100644
--- a/src/plugins/Matrix.cpp
+++ b/src/plugins/Matrix.cpp
@@ -885,7 +885,6 @@ namespace QuickMedia {
auto tag_body_item = BodyItem::create(std::move(tag_name));
tag_body_item->url = tag;
tag_body_items_by_name.insert(std::make_pair(tag, TagData{tag_body_item, {}}));
- // TODO: Sort by tag priority
body->append_item(tag_body_item);
tag_data = &tag_body_items_by_name[tag];
tag_data->tag_item = tag_body_item;
@@ -4051,7 +4050,7 @@ namespace QuickMedia {
"</mx-reply>" + std::move(formatted_body);
}
- static Message* get_latest_message_in_edit_chain(Message *message) {
+ Message* get_latest_message_in_edit_chain(Message *message) {
while(message) {
Message *replaced_by = message->replaced_by.get();
if(!replaced_by)
@@ -4152,40 +4151,61 @@ namespace QuickMedia {
return PluginResult::OK;
}
+ static Message* get_replied_to_message_recursive(Matrix *matrix, RoomData *room, Message *message) {
+ while(message) {
+ if(message->related_event_type == RelatedEventType::REPLY && !message->related_event_id.empty())
+ return get_latest_message_in_edit_chain(matrix->get_message_by_id(room, message->related_event_id).get());
+ else if(message->related_event_type == RelatedEventType::EDIT && !message->related_event_id.empty())
+ message = matrix->get_message_by_id(room, message->related_event_id).get();
+ else
+ return nullptr;
+ }
+ return nullptr;
+ }
+
+ static std::string create_body_for_message_edit(Matrix *matrix, const Message *replied_to_message, const std::string &body) {
+ if(replied_to_message)
+ return create_body_for_message_reply(matrix, replied_to_message, " * " + body);
+ else
+ return " * " + body;
+ }
+
+ std::string Matrix::create_formatted_body_for_message_edit(RoomData *room, const Message *replied_to_message, const std::string &body) {
+ if(replied_to_message)
+ return create_formatted_body_for_message_reply(room, replied_to_message, " * " + body);
+ else
+ return body_to_formatted_body(room, " * " + body);
+ }
+
PluginResult Matrix::post_edit(RoomData *room, const std::string &body, void *relates_to, std::string &event_id_response) {
Message *relates_to_message_raw = (Message*)relates_to;
+ Message *replied_to_message = get_replied_to_message_recursive(this, room, relates_to_message_raw);
std::string transaction_id = create_transaction_id();
if(transaction_id.empty())
return PluginResult::ERR;
my_events_transaction_ids.insert(transaction_id);
- std::string formatted_body = body_to_formatted_body(room, body);
+ rapidjson::Document request_data(rapidjson::kObjectType);
+ const std::string message_edit_body = create_body_for_message_edit(this, replied_to_message, body);
+ const std::string formatted_message_edit_body = create_formatted_body_for_message_edit(room, replied_to_message, body);
+ request_data.AddMember("msgtype", "m.text", request_data.GetAllocator());
+ request_data.AddMember("body", rapidjson::StringRef(message_edit_body.c_str()), request_data.GetAllocator());
+ request_data.AddMember("format", "org.matrix.custom.html", request_data.GetAllocator());
+ request_data.AddMember("formatted_body", rapidjson::StringRef(formatted_message_edit_body.c_str()), request_data.GetAllocator());
+
+ const std::string formatted_body = body_to_formatted_body(room, body);
rapidjson::Document new_content_json(rapidjson::kObjectType);
new_content_json.AddMember("msgtype", "m.text", new_content_json.GetAllocator());
new_content_json.AddMember("body", rapidjson::StringRef(body.c_str()), new_content_json.GetAllocator());
- if(!formatted_body.empty()) {
- new_content_json.AddMember("format", "org.matrix.custom.html", new_content_json.GetAllocator());
- new_content_json.AddMember("formatted_body", rapidjson::StringRef(formatted_body.c_str()), new_content_json.GetAllocator());
- }
+ new_content_json.AddMember("format", "org.matrix.custom.html", new_content_json.GetAllocator());
+ new_content_json.AddMember("formatted_body", rapidjson::StringRef(formatted_body.c_str()), new_content_json.GetAllocator());
+ request_data.AddMember("m.new_content", std::move(new_content_json), request_data.GetAllocator());
rapidjson::Document relates_to_json(rapidjson::kObjectType);
relates_to_json.AddMember("event_id", rapidjson::StringRef(relates_to_message_raw->event_id.c_str()), relates_to_json.GetAllocator());
relates_to_json.AddMember("rel_type", "m.replace", relates_to_json.GetAllocator());
-
- std::string body_edit_str = " * " + body;
- std::string formatted_body_edit_str;
-
- rapidjson::Document request_data(rapidjson::kObjectType);
- request_data.AddMember("msgtype", "m.text", request_data.GetAllocator());
- request_data.AddMember("body", rapidjson::StringRef(body_edit_str.c_str()), request_data.GetAllocator());
- if(!formatted_body.empty()) {
- formatted_body_edit_str = " * " + formatted_body;
- request_data.AddMember("format", "org.matrix.custom.html", request_data.GetAllocator());
- request_data.AddMember("formatted_body", rapidjson::StringRef(formatted_body_edit_str.c_str()), request_data.GetAllocator());
- }
- request_data.AddMember("m.new_content", std::move(new_content_json), request_data.GetAllocator());
request_data.AddMember("m.relates_to", std::move(relates_to_json), request_data.GetAllocator());
rapidjson::StringBuffer buffer;