From ba0f42d30f87ca80ac933137cba5995f4f2c39bf Mon Sep 17 00:00:00 2001 From: dec05eba Date: Thu, 11 Feb 2021 22:23:58 +0100 Subject: Matrix: mark local edit/reply as read --- plugins/Matrix.hpp | 6 ++++-- src/QuickMedia.cpp | 56 ++++++++++++++++++++++++++++---------------------- src/plugins/Matrix.cpp | 24 +++++++++++++--------- 3 files changed, 49 insertions(+), 37 deletions(-) diff --git a/plugins/Matrix.hpp b/plugins/Matrix.hpp index 9fb35fe..7028e4d 100644 --- a/plugins/Matrix.hpp +++ b/plugins/Matrix.hpp @@ -76,7 +76,7 @@ namespace QuickMedia { RelatedEventType related_event_type = RelatedEventType::NONE; bool notification_mentions_me = false; bool cache = false; - bool provisional = false; + std::string transaction_id; time_t timestamp = 0; // In milliseconds MessageType type; std::shared_ptr replaced_by = nullptr; @@ -204,6 +204,7 @@ namespace QuickMedia { bool message_contains_user_mention(const std::string &msg, const std::string &username); bool message_is_timeline(Message *message); void body_set_selected_item(Body *body, BodyItem *selected_item); + std::string create_transaction_id(); enum class MatrixPageType { ROOM_LIST, @@ -459,7 +460,8 @@ namespace QuickMedia { // TODO: Make api better. PluginResult post_message(RoomData *room, const std::string &body, std::string &event_id_response, const std::optional &file_info, const std::optional &thumbnail_info, const std::string &msgtype = ""); // |relates_to| is from |BodyItem.userdata| and is of type |Message*| - PluginResult post_reply(RoomData *room, const std::string &body, void *relates_to, std::string &event_id_response); + // If |custom_transaction_id| is empty, then a new transaction id is generated + PluginResult post_reply(RoomData *room, const std::string &body, void *relates_to, std::string &event_id_response, const std::string &custom_transaction_id = ""); // |relates_to| is from |BodyItem.userdata| and is of type |Message*| PluginResult post_edit(RoomData *room, const std::string &body, void *relates_to, std::string &event_id_response); // |relates_to| is from |BodyItem.userdata| and is of type |Message*| diff --git a/src/QuickMedia.cpp b/src/QuickMedia.cpp index 205b201..e3653e5 100644 --- a/src/QuickMedia.cpp +++ b/src/QuickMedia.cpp @@ -3443,8 +3443,9 @@ namespace QuickMedia { std::string event_id; }; + std::unordered_map> pending_sent_replies; + // This is needed to keep the message shared ptr alive. TODO: Remove this shit, maybe even use raw pointers. - std::unordered_map sent_messages; // |event_id| is always empty in this. Use |message->event_id| instead std::optional provisional_message; MessageQueue provisional_message_queue; MessageQueue> post_task_queue; @@ -3458,15 +3459,6 @@ namespace QuickMedia { }; std::thread post_thread(post_thread_handler); - auto filter_sent_messages = [&sent_messages](Messages &messages) { - for(auto it = messages.begin(); it != messages.end();) { - if(sent_messages.find((*it)->event_id) != sent_messages.end()) - it = messages.erase(it); - else - ++it; - } - }; - auto upload_file = [this, &tabs, ¤t_room](const std::string &filepath) { TaskResult post_file_result = run_task_with_loading_screen([this, ¤t_room, filepath]() { std::string event_id_response; @@ -3485,7 +3477,7 @@ namespace QuickMedia { } }; - chat_input.on_submit_callback = [this, &tabs, &me, &chat_input, &selected_tab, ¤t_room, &new_page, &chat_state, ¤tly_operating_on_item, &post_task_queue, &process_reactions, &find_body_item_by_event_id](std::string text) mutable { + chat_input.on_submit_callback = [this, &tabs, &me, &chat_input, &selected_tab, ¤t_room, &new_page, &chat_state, &pending_sent_replies, ¤tly_operating_on_item, &post_task_queue, &process_reactions, &find_body_item_by_event_id](std::string text) mutable { if(!current_room) return false; @@ -3582,17 +3574,20 @@ namespace QuickMedia { tabs[MESSAGES_TAB_INDEX].body->select_last_item(); return true; } else if(chat_state == ChatState::REPLYING) { + std::string transaction_id = create_transaction_id(); + pending_sent_replies[transaction_id] = message; + void *related_to_message = currently_operating_on_item->userdata; message->related_event_type = RelatedEventType::REPLY; message->related_event_id = static_cast(related_to_message)->event_id; auto body_item = message_to_body_item(current_room, message.get(), current_room->get_user_avatar_url(me), me->user_id); body_item->set_description_color(provisional_message_color); tabs[MESSAGES_TAB_INDEX].body->insert_items_by_timestamps({body_item}); - post_task_queue.push([this, ¤t_room, text, related_to_message, body_item, message]() { + post_task_queue.push([this, ¤t_room, text, related_to_message, body_item, message, transaction_id]() { ProvisionalMessage provisional_message; provisional_message.body_item = body_item; provisional_message.message = message; - if(matrix->post_reply(current_room, text, related_to_message, provisional_message.event_id) != PluginResult::OK) + if(matrix->post_reply(current_room, text, related_to_message, provisional_message.event_id, transaction_id) != PluginResult::OK) fprintf(stderr, "Failed to post matrix reply\n"); return provisional_message; }); @@ -3923,12 +3918,26 @@ namespace QuickMedia { } }; - auto filter_provisional_messages = [](Messages &messages) { + auto filter_provisional_messages = [&find_body_item_by_event_id, &tabs, &pending_sent_replies](Messages &messages) { for(auto it = messages.begin(); it != messages.end();) { - if((*it)->provisional) + if(!(*it)->transaction_id.empty()) { + if((*it)->related_event_type == RelatedEventType::EDIT) { + auto body_item = find_body_item_by_event_id(tabs[MESSAGES_TAB_INDEX].body->items.data(), tabs[MESSAGES_TAB_INDEX].body->items.size(), (*it)->related_event_id); + if(body_item) { + Message *orig_message = static_cast(body_item->userdata); + orig_message->replaced_by = (*it); + } + } else if((*it)->related_event_type == RelatedEventType::REPLY) { + auto pending_sent_reply_it = pending_sent_replies.find((*it)->transaction_id); + if(pending_sent_reply_it != pending_sent_replies.end()) { + pending_sent_reply_it->second->replaced_by = (*it); + pending_sent_replies.erase(pending_sent_reply_it); + } + } it = messages.erase(it); - else + } else { ++it; + } } }; @@ -4088,7 +4097,7 @@ namespace QuickMedia { } }; - auto cleanup_tasks = [&set_read_marker_future, &fetch_message_future, &fetch_users_future, &typing_state_queue, &typing_state_thread, &post_task_queue, &provisional_message_queue, &fetched_messages_set, &sent_messages, &post_thread, &tabs]() { + auto cleanup_tasks = [&set_read_marker_future, &fetch_message_future, &fetch_users_future, &typing_state_queue, &typing_state_thread, &post_task_queue, &provisional_message_queue, &fetched_messages_set, &pending_sent_replies, &post_thread, &tabs]() { set_read_marker_future.cancel(); fetch_message_future.cancel(); fetch_users_future.cancel(); @@ -4104,7 +4113,7 @@ namespace QuickMedia { } provisional_message_queue.clear(); fetched_messages_set.clear(); - sent_messages.clear(); + pending_sent_replies.clear(); //unreferenced_event_by_room.clear(); @@ -4545,8 +4554,8 @@ namespace QuickMedia { chat_input.set_max_width(window_size.x - (logo_padding_x + logo_size.x + chat_input_padding_x + logo_padding_x + body_pos.x - body_padding_horizontal)); chat_input.set_position(sf::Vector2f(std::floor(body_pos.x - body_padding_horizontal + logo_padding_x + logo_size.x + chat_input_padding_x), window_size.y - chat_height - chat_input_padding_y)); - more_messages_below_rect.setSize(sf::Vector2f(window_size.x, gradient_height)); - more_messages_below_rect.setPosition(0.0f, std::floor(window_size.y - chat_input_height_full - gradient_height)); + more_messages_below_rect.setSize(sf::Vector2f(chat_input_shade.getSize().x, gradient_height)); + more_messages_below_rect.setPosition(chat_input_shade.getPosition().x, std::floor(window_size.y - chat_input_height_full - gradient_height)); logo_sprite.setPosition(body_pos.x - body_padding_horizontal + logo_padding_x, std::floor(window_size.y - chat_input_height_full * 0.5f - logo_size.y * 0.5f)); } @@ -4558,7 +4567,6 @@ namespace QuickMedia { if(!provisional_message->event_id.empty()) { provisional_message->message->event_id = std::move(provisional_message->event_id); provisional_message->body_item->set_description_color(sf::Color::White); - sent_messages[provisional_message->message->event_id] = std::move(provisional_message.value()); } else if(provisional_message->body_item) { provisional_message->body_item->set_description("Failed to send: " + provisional_message->body_item->get_description()); provisional_message->body_item->set_description_color(sf::Color::Red); @@ -4590,7 +4598,6 @@ namespace QuickMedia { all_messages.insert(all_messages.end(), new_messages.begin(), new_messages.end()); if(new_messages.empty()) fetched_enough_messages = true; - filter_sent_messages(new_messages); filter_existing_messages(new_messages); fprintf(stderr, "Finished fetching older messages, num new messages: %zu\n", new_messages.size()); size_t num_new_messages = new_messages.size(); @@ -4702,7 +4709,7 @@ namespace QuickMedia { gradient_inc += (frame_time_ms * 0.5); sf::Color top_color = interpolate_colors(back_color, sf::Color(175, 180, 188), progress); - gradient_points[0].position.x = 0.0f; + gradient_points[0].position.x = chat_input_shade.getPosition().x; gradient_points[0].position.y = tab_shade_height; gradient_points[1].position.x = window_size.x; @@ -4711,7 +4718,7 @@ namespace QuickMedia { gradient_points[2].position.x = window_size.x; gradient_points[2].position.y = tab_shade_height + gradient_height; - gradient_points[3].position.x = 0.0f; + gradient_points[3].position.x = chat_input_shade.getPosition().x; gradient_points[3].position.y = tab_shade_height + gradient_height; gradient_points[0].color = top_color; @@ -4818,7 +4825,6 @@ namespace QuickMedia { } all_messages.insert(all_messages.end(), all_messages_new.begin(), all_messages_new.end()); //me = matrix->get_me(current_room); - filter_sent_messages(all_messages_new); add_new_messages_to_current_room(all_messages_new); modify_related_messages_in_current_room(all_messages_new); unresolved_reactions.clear(); diff --git a/src/plugins/Matrix.cpp b/src/plugins/Matrix.cpp index a47b588..2b72f03 100644 --- a/src/plugins/Matrix.cpp +++ b/src/plugins/Matrix.cpp @@ -1857,12 +1857,12 @@ namespace QuickMedia { if(origin_server_ts.IsInt64()) timestamp = origin_server_ts.GetInt64(); - bool provisional = false; + std::string transaction_id; const rapidjson::Value &unsigned_json = GetMember(event_item_json, "unsigned"); if(unsigned_json.IsObject()) { const rapidjson::Value &transaction_id_json = GetMember(unsigned_json, "transaction_id"); if(transaction_id_json.IsString() && my_events_transaction_ids.find(transaction_id_json.GetString()) != my_events_transaction_ids.end()) - provisional = true; + transaction_id = std::string(transaction_id_json.GetString(), transaction_id_json.GetStringLength()); } RelatedEventType related_event_type = RelatedEventType::NONE; @@ -1892,7 +1892,7 @@ namespace QuickMedia { message->related_event_id = relates_to_event_id_json.GetString(); message->related_event_type = RelatedEventType::REACTION; message->timestamp = timestamp; - message->provisional = provisional; + message->transaction_id = std::move(transaction_id); return message; } } @@ -1911,7 +1911,7 @@ namespace QuickMedia { message->body = "Message deleted"; message->timestamp = timestamp; message->related_event_type = RelatedEventType::REDACTION; - message->provisional = provisional; + message->transaction_id = std::move(transaction_id); const rapidjson::Value &reason_json = GetMember(*content_json, "reason"); if(reason_json.IsString()) { @@ -2033,7 +2033,7 @@ namespace QuickMedia { message->related_event_id = std::move(related_event_id); message->related_event_type = related_event_type; message->timestamp = timestamp; - message->provisional = provisional; + message->transaction_id = std::move(transaction_id); return message; } else { auto message = std::make_shared(); @@ -2044,7 +2044,7 @@ namespace QuickMedia { message->related_event_id = std::move(related_event_id); message->related_event_type = related_event_type; message->timestamp = timestamp; - message->provisional = provisional; + message->transaction_id = std::move(transaction_id); return message; } @@ -2118,7 +2118,7 @@ namespace QuickMedia { message->related_event_id = std::move(related_event_id); message->related_event_type = related_event_type; message->timestamp = timestamp; - message->provisional = provisional; + message->transaction_id = std::move(transaction_id); return message; } @@ -2541,7 +2541,7 @@ namespace QuickMedia { return result.str(); } - static std::string create_transaction_id() { + std::string create_transaction_id() { char random_characters[18]; if(!generate_random_characters(random_characters, sizeof(random_characters))) return ""; @@ -2751,13 +2751,17 @@ namespace QuickMedia { } // TODO: Support greentext - PluginResult Matrix::post_reply(RoomData *room, const std::string &body, void *relates_to, std::string &event_id_response) { + PluginResult Matrix::post_reply(RoomData *room, const std::string &body, void *relates_to, std::string &event_id_response, const std::string &custom_transaction_id) { // TODO: Store shared_ptr instead of raw pointer... Message *relates_to_message_raw = (Message*)relates_to; - std::string transaction_id = create_transaction_id(); + std::string transaction_id = custom_transaction_id; + if(transaction_id.empty()) + transaction_id = create_transaction_id(); + if(transaction_id.empty()) return PluginResult::ERR; + my_events_transaction_ids.insert(transaction_id); rapidjson::Document in_reply_to_json(rapidjson::kObjectType); -- cgit v1.2.3