From 41fe990530c546b4cac7e000b40481f87fb33305 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Mon, 19 Oct 2020 19:36:10 +0200 Subject: shared_ptr -> unique_ptr and naked pointers --- src/QuickMedia.cpp | 107 +++++++++++++++++++++-------------------------------- 1 file changed, 42 insertions(+), 65 deletions(-) (limited to 'src/QuickMedia.cpp') diff --git a/src/QuickMedia.cpp b/src/QuickMedia.cpp index 659e59c..a32febb 100644 --- a/src/QuickMedia.cpp +++ b/src/QuickMedia.cpp @@ -2961,21 +2961,10 @@ namespace QuickMedia { // This is needed to get initial data, with joined rooms etc. TODO: Remove this once its cached // and allow asynchronous update of rooms bool synced = false; - - struct RoomBodyData { - std::shared_ptr body_item; - bool last_message_read; - time_t last_read_message_timestamp; - }; - - std::unordered_map, RoomBodyData> body_items_by_room; - std::shared_ptr current_room; - RoomBodyData *current_room_body_data = nullptr; - + RoomData *current_room = nullptr; bool is_window_focused = window.hasFocus(); - // TODO: Always keep the mentioned rooms at the top, and then the ones with unread messages below? - auto process_new_room_messages = [this, &tabs, &body_items_by_room, ¤t_room, &is_window_focused](RoomSyncMessages &room_sync_messages, bool is_first_sync) mutable { + auto process_new_room_messages = [this, &tabs, ¤t_room, &is_window_focused](RoomSyncMessages &room_sync_messages, bool is_first_sync) mutable { size_t room_swap_index = 0; for(auto &[room, messages] : room_sync_messages) { if(messages.empty()) @@ -2985,6 +2974,7 @@ namespace QuickMedia { for(auto &message : messages) { if(message->mentions_me) { was_mentioned = true; + room->has_unread_mention = true; //message->mentions_me = false; // TODO: What if the message or username begins with "-"? also make the notification image be the avatar of the user if(!is_window_focused || room != current_room) @@ -2992,9 +2982,8 @@ namespace QuickMedia { } } - auto room_body_item_it = body_items_by_room.find(room); - if(room_body_item_it == body_items_by_room.end()) - continue; + BodyItem *room_body_item = static_cast(room->userdata); + assert(room_body_item); // TODO: this wont always work because we dont display all types of messages from server, such as "joined", "left", "kicked", "banned", "changed avatar", "changed display name", etc. bool unread_messages = false; @@ -3006,19 +2995,20 @@ namespace QuickMedia { std::string room_desc = "Unread: " + matrix->message_get_author_displayname(messages.back().get()) + ": " + extract_first_line(messages.back()->body, 150); if(was_mentioned) room_desc += "\n** You were mentioned **"; // TODO: Better notification? - room_body_item_it->second.body_item->set_description(std::move(room_desc)); - room_body_item_it->second.body_item->set_title_color(sf::Color(255, 100, 100)); - room_body_item_it->second.last_message_read = false; + room_body_item->set_description(std::move(room_desc)); + room_body_item->set_title_color(sf::Color(255, 100, 100)); + room->last_message_read = false; // Swap room with the top one // TODO: Optimize with hash map instead of linear search? or cache the index - int room_body_index = tabs[ROOMS_TAB_INDEX].body->get_index_by_body_item(room_body_item_it->second.body_item.get()); + int room_body_index = tabs[ROOMS_TAB_INDEX].body->get_index_by_body_item(room_body_item); if(room_body_index != -1) { std::swap(tabs[ROOMS_TAB_INDEX].body->items[room_body_index], tabs[ROOMS_TAB_INDEX].body->items[room_swap_index]); ++room_swap_index; } } else if(is_first_sync) { - room_body_item_it->second.body_item->set_description(matrix->message_get_author_displayname(messages.back().get()) + ": " + extract_first_line(messages.back()->body, 150)); + room_body_item->set_description(matrix->message_get_author_displayname(messages.back().get()) + ": " + extract_first_line(messages.back()->body, 150)); + room->has_unread_mention = false; } } }; @@ -3058,14 +3048,6 @@ namespace QuickMedia { bool redraw = true; - auto get_room_by_ptr = [&body_items_by_room](RoomData *room_ptr) -> std::shared_ptr { - for(auto &[room, body_data] : body_items_by_room) { - if(room.get() == room_ptr) - return room; - } - return nullptr; - }; - // TODO: Optimize with hash map? auto find_body_item_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) { @@ -3077,7 +3059,7 @@ namespace QuickMedia { }; // TODO: What if these never end up referencing events? clean up automatically after a while? - std::unordered_map, Messages> unreferenced_event_by_room; + std::unordered_map unreferenced_event_by_room; auto set_body_as_deleted = [](Message *message, BodyItem *body_item) { body_item->embedded_item = nullptr; @@ -3137,9 +3119,9 @@ namespace QuickMedia { }; room_search_bar.onTextSubmitCallback = - [this, &tabs, &selected_tab, ¤t_room, ¤t_room_body_data, &room_name_text, - &get_room_by_ptr, &body_items_by_room, &modify_related_messages_in_current_room, - &room_avatar_thumbnail_data, &read_marker_timeout_ms, &redraw] + [this, &tabs, &selected_tab, ¤t_room, &room_name_text, + &modify_related_messages_in_current_room, &room_avatar_thumbnail_data, + &read_marker_timeout_ms, &redraw] (const std::string&) { BodyItem *selected_item = tabs[ROOMS_TAB_INDEX].body->get_selected(); @@ -3148,7 +3130,7 @@ namespace QuickMedia { tabs[ROOMS_TAB_INDEX].body->clear_cache(); - current_room = get_room_by_ptr((RoomData*)selected_item->userdata); + current_room = (RoomData*)selected_item->userdata; assert(current_room); selected_tab = MESSAGES_TAB_INDEX; tabs[MESSAGES_TAB_INDEX].body->clear_items(); @@ -3163,12 +3145,8 @@ namespace QuickMedia { show_notification("QuickMedia", err_msg, Urgency::CRITICAL); } - auto room_body_item_it = body_items_by_room.find(current_room); - if(room_body_item_it != body_items_by_room.end()) { - current_room_body_data = &room_body_item_it->second; - room_name_text.setString(current_room_body_data->body_item->get_title()); - room_avatar_thumbnail_data = std::make_shared(); - } + room_name_text.setString(static_cast(current_room->userdata)->get_title()); + room_avatar_thumbnail_data = std::make_shared(); read_marker_timeout_ms = 0; redraw = true; @@ -3255,11 +3233,11 @@ namespace QuickMedia { std::future previous_messages_future; bool fetching_previous_messages_running = false; - std::shared_ptr previous_messages_future_room; + RoomData *previous_messages_future_room = nullptr; std::future> fetch_reply_message_future; bool fetching_reply_message_running = false; - std::shared_ptr fetch_reply_future_room; + RoomData *fetch_reply_future_room = nullptr; BodyItem *fetch_reply_body_item = nullptr; // TODO: How about instead fetching all messages we have, not only the visible ones? also fetch with multiple threads. @@ -3287,7 +3265,7 @@ namespace QuickMedia { body_item->embedded_item_status = EmbeddedItemStatus::LOADING; // TODO: Check if the message is already cached before calling async? is this needed? is async creation expensive? fetch_reply_message_future = std::async(std::launch::async, [this, &fetch_reply_future_room, message_event_id]() { - return matrix->get_message_by_id(fetch_reply_future_room.get(), message_event_id); + return matrix->get_message_by_id(fetch_reply_future_room, message_event_id); }); }; @@ -3318,7 +3296,7 @@ namespace QuickMedia { float tab_vertical_offset = 0.0f; - auto typing_async_func = [this](bool new_state, std::shared_ptr room) { + auto typing_async_func = [this](bool new_state, RoomData *room) { if(new_state) { matrix->on_start_typing(room); } else { @@ -3381,7 +3359,7 @@ namespace QuickMedia { } }; - auto add_new_rooms = [&tabs, &body_items_by_room, ¤t_room, ¤t_room_body_data, &room_name_text, &room_search_bar](Rooms &rooms) { + auto add_new_rooms = [&tabs, ¤t_room, &room_name_text, &room_search_bar](Rooms &rooms) { if(rooms.empty()) return; @@ -3395,23 +3373,19 @@ namespace QuickMedia { auto body_item = BodyItem::create(std::move(room_name)); body_item->thumbnail_url = room->avatar_url; - body_item->userdata = room.get(); // Note: this has to be valid as long as the room list is valid! + body_item->userdata = room; // Note: this has to be valid as long as the room list is valid! body_item->thumbnail_mask_type = ThumbnailMaskType::CIRCLE; body_item->thumbnail_size = sf::Vector2i(32, 32); tabs[ROOMS_TAB_INDEX].body->filter_search_fuzzy_item(search_filter_text, body_item.get()); tabs[ROOMS_TAB_INDEX].body->items.push_back(body_item); - body_items_by_room[room] = { body_item, true, 0 }; + room->userdata = body_item.get(); } if(current_room) return; current_room = rooms[0]; - auto room_body_item_it = body_items_by_room.find(current_room); - if(room_body_item_it != body_items_by_room.end()) { - current_room_body_data = &room_body_item_it->second; - room_name_text.setString(current_room_body_data->body_item->get_title()); - } + room_name_text.setString(static_cast(current_room->userdata)->get_title()); }; float tab_shade_height = 0.0f; @@ -3738,8 +3712,8 @@ namespace QuickMedia { ++it; } - if(current_room_body_data && room_avatar_thumbnail_data->loading_state == LoadingState::NOT_LOADED) - async_image_loader.load_thumbnail(current_room_body_data->body_item->thumbnail_url, false, sf::Vector2i(32, 32), use_tor, room_avatar_thumbnail_data); + if(current_room && current_room->userdata && room_avatar_thumbnail_data->loading_state == LoadingState::NOT_LOADED) + async_image_loader.load_thumbnail(static_cast(current_room->userdata)->thumbnail_url, false, sf::Vector2i(32, 32), use_tor, room_avatar_thumbnail_data); if(room_avatar_thumbnail_data->loading_state == LoadingState::FINISHED_LOADING && room_avatar_thumbnail_data->image->getSize().x > 0 && room_avatar_thumbnail_data->image->getSize().y > 0) { if(!room_avatar_thumbnail_data->texture.loadFromImage(*room_avatar_thumbnail_data->image)) @@ -3987,20 +3961,23 @@ namespace QuickMedia { tabs[MESSAGES_TAB_INDEX].body->draw_item(window, currently_operating_on_item.get(), body_item_pos, body_item_size); } - if(tabs[selected_tab].type == ChatTabType::MESSAGES && current_room_body_data) { + if(tabs[selected_tab].type == ChatTabType::MESSAGES && current_room && current_room->userdata) { if(tabs[selected_tab].body->is_last_item_fully_visible()) { - if(!current_room_body_data->last_message_read) { - std::string room_desc = current_room_body_data->body_item->get_description(); + if(!current_room->last_message_read) { + BodyItem *current_room_body_item = static_cast(current_room->userdata); + std::string room_desc = current_room_body_item->get_description(); if(strncmp(room_desc.c_str(), "Unread: ", 8) == 0) room_desc = room_desc.substr(8); if(room_desc.size() >= 25 && strncmp(room_desc.c_str() + room_desc.size() - 25, "\n** You were mentioned **", 25) == 0) room_desc = room_desc.substr(0, room_desc.size() - 25); - current_room_body_data->body_item->set_description(std::move(room_desc)); + current_room_body_item->set_description(std::move(room_desc)); // TODO: Show a line like nheko instead for unread messages, or something else - current_room_body_data->body_item->set_title_color(sf::Color::White); - current_room_body_data->last_message_read = true; + current_room_body_item->set_title_color(sf::Color::White); + current_room->last_message_read = true; + // TODO: Maybe set this instead when the mention is visible on the screen? + current_room->has_unread_mention = false; } - } else if(!current_room_body_data->last_message_read) { + } else if(!current_room->last_message_read) { window.draw(more_messages_below_rect); } } @@ -4014,15 +3991,15 @@ namespace QuickMedia { if(tabs[selected_tab].type == ChatTabType::MESSAGES && current_room) { BodyItem *last_visible_item = tabs[selected_tab].body->get_last_fully_visible_item(); - if(is_window_focused && chat_state != ChatState::URL_SELECTION && current_room_body_data && last_visible_item && !setting_read_marker && read_marker_timer.getElapsedTime().asMilliseconds() >= read_marker_timeout_ms) { + if(is_window_focused && chat_state != ChatState::URL_SELECTION && current_room && last_visible_item && !setting_read_marker && read_marker_timer.getElapsedTime().asMilliseconds() >= read_marker_timeout_ms) { Message *message = (Message*)last_visible_item->userdata; // TODO: What if two messages have the same timestamp? - if(message->timestamp > current_room_body_data->last_read_message_timestamp) { + if(message->timestamp > current_room->last_read_message_timestamp) { read_marker_timeout_ms = read_marker_timeout_ms_default; - current_room_body_data->last_read_message_timestamp = message->timestamp; + current_room->last_read_message_timestamp = message->timestamp; // TODO: What if the message is no longer valid? setting_read_marker = true; - std::shared_ptr room = current_room; + RoomData *room = current_room; set_read_marker_future = std::async(std::launch::async, [this, room, message]() mutable { if(matrix->set_read_marker(room, message) != PluginResult::OK) { fprintf(stderr, "Warning: failed to set read marker to %s\n", message->event_id.c_str()); -- cgit v1.2.3