diff options
Diffstat (limited to 'src/QuickMedia.cpp')
-rw-r--r-- | src/QuickMedia.cpp | 76 |
1 files changed, 56 insertions, 20 deletions
diff --git a/src/QuickMedia.cpp b/src/QuickMedia.cpp index 90abfcc..0021f96 100644 --- a/src/QuickMedia.cpp +++ b/src/QuickMedia.cpp @@ -2967,22 +2967,44 @@ namespace QuickMedia { RoomData *current_room = nullptr; bool is_window_focused = window.hasFocus(); - auto process_new_room_messages = [this, &selected_tab, ¤t_room, &is_window_focused](RoomSyncMessages &room_sync_messages, bool is_first_sync) mutable { - for(auto &[room, messages] : room_sync_messages) { - if(messages.empty()) - continue; + // Returns -1 if no rooms or no unread rooms + auto find_top_body_position_for_unread_room = [&tabs](BodyItem *item_to_swap, int start_index) { + for(int i = start_index; i < (int)tabs[ROOMS_TAB_INDEX].body->items.size(); ++i) { + const auto &body_item = tabs[ROOMS_TAB_INDEX].body->items[i]; + if(static_cast<RoomData*>(body_item->userdata)->last_message_read || body_item.get() == item_to_swap) + return i; + } + return -1; + }; - bool was_mentioned = false; + // Returns -1 if no rooms or all rooms have unread mentions + auto find_top_body_position_for_mentioned_room = [&tabs](BodyItem *item_to_swap, int start_index) { + for(int i = start_index; i < (int)tabs[ROOMS_TAB_INDEX].body->items.size(); ++i) { + const auto &body_item = tabs[ROOMS_TAB_INDEX].body->items[i]; + if(!static_cast<RoomData*>(body_item->userdata)->has_unread_mention || body_item.get() == item_to_swap) + return i; + } + return -1; + }; + + auto process_new_room_messages = + [this, &selected_tab, ¤t_room, &is_window_focused, &tabs, &find_top_body_position_for_unread_room, &find_top_body_position_for_mentioned_room] + (RoomSyncMessages &room_sync_messages, bool is_first_sync) mutable + { + for(auto &[room, messages] : room_sync_messages) { 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 || is_first_sync || selected_tab == ROOMS_TAB_INDEX) show_notification("QuickMedia matrix - " + matrix->message_get_author_displayname(message.get()) + " (" + room->name + ")", message->body); } } + } + + for(auto &[room, messages] : room_sync_messages) { + if(messages.empty()) + continue; BodyItem *room_body_item = static_cast<BodyItem*>(room->userdata); assert(room_body_item); @@ -2990,27 +3012,41 @@ namespace QuickMedia { // 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; std::shared_ptr<UserInfo> me = matrix->get_me(room); - if(me && room->get_user_read_marker(me) != messages.back()->event_id) + if(room->has_unread_mention || (me && room->get_user_read_marker(me) != messages.back()->event_id)) unread_messages = true; if(unread_messages) { std::string room_desc = "Unread: " + matrix->message_get_author_displayname(messages.back().get()) + ": " + extract_first_line(messages.back()->body, 150); - if(was_mentioned) + if(room->has_unread_mention) room_desc += "\n** You were mentioned **"; // TODO: Better notification? 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 + // Swap order of rooms in body list to put rooms with mentions at the top and then unread messages and then all the other rooms // 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); - // 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; - // } + int room_body_index = tabs[ROOMS_TAB_INDEX].body->get_index_by_body_item(room_body_item); + if(room_body_index != -1) { + int body_swap_index = 0; + while(true) { + BodyItem *body_item = tabs[ROOMS_TAB_INDEX].body->items[room_body_index].get(); + RoomData *room = static_cast<RoomData*>(body_item->userdata); + if(room->has_unread_mention) + body_swap_index = find_top_body_position_for_mentioned_room(body_item, body_swap_index); + else if(!room->last_message_read) + body_swap_index = find_top_body_position_for_unread_room(body_item, body_swap_index); + else + break; + + if(body_swap_index == -1) + break; + + std::swap(tabs[ROOMS_TAB_INDEX].body->items[room_body_index], tabs[ROOMS_TAB_INDEX].body->items[body_swap_index]); + ++body_swap_index; + } + } } else if(is_first_sync) { 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; } } }; @@ -3184,8 +3220,6 @@ namespace QuickMedia { } } - tabs[selected_tab].body->select_last_item(); - if(chat_state == ChatState::TYPING_MESSAGE) { // TODO: Make asynchronous if(matrix->post_message(current_room, text, std::nullopt, std::nullopt) == PluginResult::OK) { @@ -3346,9 +3380,11 @@ namespace QuickMedia { } }; - auto add_new_messages_to_current_room = [this, &tabs, ¤t_room](Messages &messages) { + auto add_new_messages_to_current_room = [this, &tabs, &selected_tab, ¤t_room, &is_window_focused](Messages &messages) { int num_items = tabs[MESSAGES_TAB_INDEX].body->items.size(); - bool scroll_to_end = (num_items == 0 || tabs[MESSAGES_TAB_INDEX].body->is_selected_item_last_visible_item()); + bool scroll_to_end = num_items == 0; + if(tabs[MESSAGES_TAB_INDEX].body->is_selected_item_last_visible_item() && selected_tab == MESSAGES_TAB_INDEX && is_window_focused) + scroll_to_end = true; BodyItem *selected_item = tabs[MESSAGES_TAB_INDEX].body->get_selected(); tabs[MESSAGES_TAB_INDEX].body->insert_items_by_timestamps(messages_to_body_items(messages, matrix->get_me(current_room).get())); |