diff options
author | dec05eba <dec05eba@protonmail.com> | 2022-11-12 15:07:16 +0100 |
---|---|---|
committer | dec05eba <dec05eba@protonmail.com> | 2022-11-12 15:07:16 +0100 |
commit | 224a5f3b2ed2141a94940fe73fc8ccb4b2f8d962 (patch) | |
tree | 4a51b48205042279d7cdfa065ae55120a09cc9d9 /src | |
parent | 4197fd3d7aaa84197eb17e700fb27093293f228b (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.cpp | 52 | ||||
-rw-r--r-- | src/plugins/Matrix.cpp | 60 |
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; |