From fd9178b9d500a0b5f30f388f8d419ac386ce87cb Mon Sep 17 00:00:00 2001 From: dec05eba Date: Sat, 17 Oct 2020 00:35:20 +0200 Subject: Matrix: edit/redact the referenced message instead of appending a new message --- src/QuickMedia.cpp | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 58 insertions(+), 4 deletions(-) (limited to 'src/QuickMedia.cpp') diff --git a/src/QuickMedia.cpp b/src/QuickMedia.cpp index 249f38f..80567f2 100644 --- a/src/QuickMedia.cpp +++ b/src/QuickMedia.cpp @@ -2891,6 +2891,8 @@ namespace QuickMedia { body_item->author_color = message->user->display_name_color; body_item->userdata = (void*)message.get(); // Note: message has to be valid as long as body_item is used! result_items[i] = std::move(body_item); + if(message->related_event_type == RelatedEventType::REDACTION || message->related_event_type == RelatedEventType::EDIT) + result_items[i]->visible = false; } return result_items; } @@ -3267,6 +3269,53 @@ namespace QuickMedia { return nullptr; }; + // TODO: Optimize with hash map? + auto find_body_items_by_event_id = [](std::shared_ptr *body_items, size_t num_body_items, const std::string &event_id) -> std::shared_ptr { + for(size_t i = 0; i < num_body_items; ++i) { + auto &body_item = body_items[i]; + if(static_cast(body_item->userdata)->event_id == event_id) + return body_item; + } + return nullptr; + }; + + // TODO: What if these never end up referencing events? clean up automatically after a while? + std::unordered_map, Messages> unreferenced_event_by_room; + + auto resolve_unreferenced_events_with_body_items = [&unreferenced_event_by_room, ¤t_room, &find_body_items_by_event_id](std::shared_ptr *body_items, size_t num_body_items) { + auto &unreferenced_events = unreferenced_event_by_room[current_room]; + for(auto it = unreferenced_events.begin(); it != unreferenced_events.end(); ) { + auto &message = *it; + // TODO: Make redacted/edited events as (redacted)/(edited) in the body + if(message->related_event_type == RelatedEventType::REDACTION || message->related_event_type == RelatedEventType::EDIT) { + auto body_item = find_body_items_by_event_id(body_items, num_body_items, message->related_event_id); + if(body_item) { + body_item->set_description(message->body); + it = unreferenced_events.erase(it); + } else { + ++it; + } + } else { + ++it; + } + } + }; + + auto modify_related_messages_in_current_room = [&unreferenced_event_by_room, ¤t_room, &find_body_items_by_event_id, &tabs](Messages &messages) { + auto &unreferenced_events = unreferenced_event_by_room[current_room]; + for(auto &message : messages) { + // TODO: Make redacted/edited events as (redacted)/(edited) in the body + if(message->related_event_type == RelatedEventType::REDACTION || message->related_event_type == RelatedEventType::EDIT) { + auto &body_items = tabs[MESSAGES_TAB_INDEX].body->items; + auto body_item = find_body_items_by_event_id(body_items.data(), body_items.size(), message->related_event_id); + if(body_item) + body_item->set_description(message->body); + else + unreferenced_events.push_back(message); + } + } + }; + while (current_page == PageType::CHAT) { sf::Int32 frame_time_ms = frame_timer.restart().asMilliseconds(); while (window.pollEvent(event)) { @@ -3518,6 +3567,7 @@ namespace QuickMedia { if(matrix->get_all_synced_room_messages(current_room, new_messages) == PluginResult::OK) { tabs[MESSAGES_TAB_INDEX].body->insert_items_by_timestamps(messages_to_body_items(new_messages)); tabs[MESSAGES_TAB_INDEX].body->select_last_item(); + modify_related_messages_in_current_room(new_messages); } else { std::string err_msg = "Failed to get messages in room: " + current_room->id; show_notification("QuickMedia", err_msg, Urgency::CRITICAL); @@ -3699,10 +3749,10 @@ namespace QuickMedia { add_new_rooms(sync_result.rooms); auto room_messages_it = sync_result.room_sync_messages.find(current_room); - if(room_messages_it != sync_result.room_sync_messages.end()) + if(room_messages_it != sync_result.room_sync_messages.end()) { add_new_messages_to_current_room(room_messages_it->second); - - //modify_related_messages() + modify_related_messages_in_current_room(room_messages_it->second); + } process_new_room_messages(sync_result.room_sync_messages, !synced); sync_running = false; @@ -3722,12 +3772,16 @@ namespace QuickMedia { size_t num_new_messages = new_messages.size(); if(previous_messages_future_room == current_room && num_new_messages > 0) { BodyItem *selected_item = tabs[MESSAGES_TAB_INDEX].body->get_selected(); - tabs[MESSAGES_TAB_INDEX].body->insert_items_by_timestamps(messages_to_body_items(new_messages)); + BodyItems new_body_items = messages_to_body_items(new_messages); + size_t num_new_body_items = new_body_items.size(); + tabs[MESSAGES_TAB_INDEX].body->insert_items_by_timestamps(std::move(new_body_items)); if(selected_item) { int selected_item_index = tabs[MESSAGES_TAB_INDEX].body->get_index_by_body_item(selected_item); if(selected_item_index != -1) tabs[MESSAGES_TAB_INDEX].body->set_selected_item(selected_item_index); } + modify_related_messages_in_current_room(new_messages); + resolve_unreferenced_events_with_body_items(tabs[MESSAGES_TAB_INDEX].body->items.data(), num_new_body_items); } fetching_previous_messages_running = false; } -- cgit v1.2.3