aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2021-03-27 23:53:14 +0100
committerdec05eba <dec05eba@protonmail.com>2021-03-27 23:53:14 +0100
commitc428eb6118a2c7e7dcf9ebdee05e80eb5cd3dc1b (patch)
treeda0d9548436f6d12dfcb5f1fb4dcaa901eca4bba
parent725c36eee8291b7d4d0eca1b4c49ee8830270fc1 (diff)
Fix some body flickering when loading embedded items that are in cache
-rw-r--r--src/QuickMedia.cpp124
1 files changed, 70 insertions, 54 deletions
diff --git a/src/QuickMedia.cpp b/src/QuickMedia.cpp
index a26f52f..e94ba34 100644
--- a/src/QuickMedia.cpp
+++ b/src/QuickMedia.cpp
@@ -3217,6 +3217,46 @@ namespace QuickMedia {
static const sf::Vector2i CHAT_MESSAGE_THUMBNAIL_MAX_SIZE(600, 337);
+ static std::shared_ptr<BodyItem> find_body_item_by_event_id(const std::shared_ptr<BodyItem> *body_items, size_t num_body_items, const std::string &event_id, size_t *index_result = nullptr) {
+ if(event_id.empty())
+ return nullptr;
+
+ for(size_t i = 0; i < num_body_items; ++i) {
+ auto &body_item = body_items[i];
+ if(body_item->userdata && static_cast<Message*>(body_item->userdata)->event_id == event_id) {
+ if(index_result)
+ *index_result = i;
+ return body_item;
+ }
+ }
+
+ return nullptr;
+ }
+
+ // Returns true if cached and loaded
+ static bool load_cached_related_embedded_item(BodyItem *body_item, Message *message, UserInfo *me, const std::string &my_display_name, const std::string &my_user_id, const BodyItems &message_body_items) {
+ // Check if we already have the referenced message as a body item, so we dont create a new one.
+ // TODO: Optimize from linear search to hash map
+ auto related_body_item = find_body_item_by_event_id(message_body_items.data(), message_body_items.size(), message->related_event_id);
+ if(!related_body_item)
+ return false;
+
+ body_item->embedded_item = std::make_shared<BodyItem>("");
+ *body_item->embedded_item = *related_body_item;
+ body_item->embedded_item->embedded_item = nullptr;
+ body_item->embedded_item->reactions.clear();
+ if((related_body_item->userdata && static_cast<Message*>(related_body_item->userdata)->user.get() == me) || message_contains_user_mention(message->body, my_display_name) || message_contains_user_mention(message->body, my_user_id))
+ body_item->set_description_color(sf::Color(255, 100, 100));
+ else
+ body_item->set_description_color(sf::Color::White);
+ body_item->embedded_item_status = FetchStatus::FINISHED_LOADING;
+ return true;
+ }
+
+ static bool load_cached_related_embedded_item(BodyItem *body_item, Message *message, const std::shared_ptr<UserInfo> &me, RoomData *current_room, const BodyItems &message_body_items) {
+ return load_cached_related_embedded_item(body_item, message, me.get(), current_room->get_user_display_name(me), me->user_id, message_body_items);
+ }
+
static std::shared_ptr<BodyItem> message_to_body_item(RoomData *room, Message *message, const std::string &my_display_name, const std::string &my_user_id) {
auto body_item = BodyItem::create("");
body_item->set_author(room->get_user_display_name(message->user));
@@ -3253,6 +3293,15 @@ namespace QuickMedia {
return result_items;
}
+ static void messages_load_cached_related_embedded_item(BodyItems &new_body_items, const BodyItems &all_body_items, const std::shared_ptr<UserInfo> &me, RoomData *current_room) {
+ std::string my_display_name = current_room->get_user_display_name(me);
+ for(auto &body_item : new_body_items) {
+ Message *message = static_cast<Message*>(body_item->userdata);
+ if(message)
+ load_cached_related_embedded_item(body_item.get(), message, me.get(), my_display_name, me->user_id, all_body_items);
+ }
+ }
+
static bool is_state_message_type(const Message *message) {
if(!message)
return true;
@@ -3383,23 +3432,6 @@ namespace QuickMedia {
bool redraw = true;
bool draw_room_list = show_room_side_panel;
- // TODO: Optimize with hash map?
- auto find_body_item_by_event_id = [](std::shared_ptr<BodyItem> *body_items, size_t num_body_items, const std::string &event_id, size_t *index_result = nullptr) -> std::shared_ptr<BodyItem> {
- if(event_id.empty())
- return nullptr;
-
- for(size_t i = 0; i < num_body_items; ++i) {
- auto &body_item = body_items[i];
- if(body_item->userdata && static_cast<Message*>(body_item->userdata)->event_id == event_id) {
- if(index_result)
- *index_result = i;
- return body_item;
- }
- }
-
- return nullptr;
- };
-
// TODO: What if these never end up referencing events? clean up automatically after a while?
Messages unreferenced_events;
@@ -3421,7 +3453,7 @@ namespace QuickMedia {
};
// TODO: Optimize with hash map?
- auto resolve_unreferenced_events_with_body_items = [this, &current_room, &set_body_as_deleted, &unreferenced_events, &find_body_item_by_event_id](std::shared_ptr<BodyItem> *body_items, size_t num_body_items) {
+ auto resolve_unreferenced_events_with_body_items = [this, &current_room, &set_body_as_deleted, &unreferenced_events](std::shared_ptr<BodyItem> *body_items, size_t num_body_items) {
if(num_body_items == 0)
return;
@@ -3457,7 +3489,7 @@ namespace QuickMedia {
};
// TODO: Optimize find_body_item_by_event_id hash map?
- auto modify_related_messages_in_current_room = [this, &current_room, &set_body_as_deleted, &unreferenced_events, &find_body_item_by_event_id, &tabs](Messages &messages) {
+ auto modify_related_messages_in_current_room = [this, &current_room, &set_body_as_deleted, &unreferenced_events, &tabs](Messages &messages) {
if(messages.empty())
return;
@@ -3491,7 +3523,7 @@ namespace QuickMedia {
std::vector<std::shared_ptr<Message>> unresolved_reactions;
// TODO: Optimize find_body_item_by_event_id hash map?
- auto process_reactions = [&tabs, &find_body_item_by_event_id, &unresolved_reactions, &current_room](Messages &messages) {
+ auto process_reactions = [&tabs, &unresolved_reactions, &current_room](Messages &messages) {
if(messages.empty())
return;
@@ -3600,7 +3632,9 @@ namespace QuickMedia {
fetched_messages_set.insert(message->event_id);
}
auto me = matrix->get_me(current_room);
- tabs[MESSAGES_TAB_INDEX].body->insert_items_by_timestamps(messages_to_body_items(current_room, all_messages, current_room->get_user_display_name(me), me->user_id));
+ auto new_body_items = messages_to_body_items(current_room, all_messages, current_room->get_user_display_name(me), me->user_id);
+ messages_load_cached_related_embedded_item(new_body_items, tabs[MESSAGES_TAB_INDEX].body->items, me, current_room);
+ tabs[MESSAGES_TAB_INDEX].body->insert_items_by_timestamps(std::move(new_body_items));
modify_related_messages_in_current_room(all_messages);
process_reactions(all_messages);
tabs[MESSAGES_TAB_INDEX].body->select_last_item();
@@ -3646,7 +3680,7 @@ namespace QuickMedia {
};
std::thread post_thread(post_thread_handler);
- auto message_set_replaced_by = [&find_body_item_by_event_id, &tabs, &pending_sent_replies](std::shared_ptr<Message> message) {
+ auto message_set_replaced_by = [&tabs, &pending_sent_replies](std::shared_ptr<Message> message) {
if(message->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(), message->related_event_id);
if(body_item) {
@@ -3697,7 +3731,7 @@ namespace QuickMedia {
bool frame_skip_text_entry = false;
- chat_input.on_submit_callback = [this, &frame_skip_text_entry, &tabs, &me, &chat_input, &selected_tab, &current_room, &new_page, &chat_state, &pending_sent_replies, &currently_operating_on_item, &post_task_queue, &process_reactions, &find_body_item_by_event_id](std::string text) mutable {
+ chat_input.on_submit_callback = [this, &frame_skip_text_entry, &tabs, &me, &chat_input, &selected_tab, &current_room, &new_page, &chat_state, &pending_sent_replies, &currently_operating_on_item, &post_task_queue, &process_reactions](std::string text) mutable {
if(!current_room)
return false;
@@ -3765,6 +3799,7 @@ namespace QuickMedia {
message->related_event_type = RelatedEventType::REACTION;
message->related_event_id = static_cast<Message*>(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);
+ load_cached_related_embedded_item(body_item.get(), message.get(), me, current_room, tabs[MESSAGES_TAB_INDEX].body->items);
tabs[MESSAGES_TAB_INDEX].body->insert_items_by_timestamps({body_item});
Messages messages;
messages.push_back(message);
@@ -3780,6 +3815,7 @@ namespace QuickMedia {
} else {
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);
+ load_cached_related_embedded_item(body_item.get(), message.get(), me, current_room, tabs[MESSAGES_TAB_INDEX].body->items);
tabs[MESSAGES_TAB_INDEX].body->insert_items_by_timestamps({body_item});
post_task_queue.push([this, &current_room, text, msgtype, body_item, message]() {
ProvisionalMessage provisional_message;
@@ -3804,6 +3840,7 @@ namespace QuickMedia {
message->related_event_id = static_cast<Message*>(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);
+ load_cached_related_embedded_item(body_item.get(), message.get(), me, current_room, tabs[MESSAGES_TAB_INDEX].body->items);
tabs[MESSAGES_TAB_INDEX].body->insert_items_by_timestamps({body_item});
post_task_queue.push([this, &current_room, text, related_to_message, body_item, message, transaction_id]() {
ProvisionalMessage provisional_message;
@@ -3832,6 +3869,7 @@ namespace QuickMedia {
auto edit_body_item = message_to_body_item(current_room, message.get(), current_room->get_user_avatar_url(me), me->user_id);
edit_body_item->visible = false;
+ load_cached_related_embedded_item(body_item.get(), message.get(), me, current_room, tabs[MESSAGES_TAB_INDEX].body->items);
tabs[MESSAGES_TAB_INDEX].body->insert_items_by_timestamps({edit_body_item});
//unreferenced_events.push_back(message);
@@ -3877,7 +3915,7 @@ namespace QuickMedia {
int fetch_message_tab = -1;
// TODO: How about instead fetching all messages we have, not only the visible ones? also fetch with multiple threads.
- tabs[PINNED_TAB_INDEX].body->body_item_render_callback = [this, &current_room, &me, &fetch_message_future, &tabs, &fetch_message, &find_body_item_by_event_id, &fetch_body_item, &fetch_message_tab](BodyItem *body_item) {
+ tabs[PINNED_TAB_INDEX].body->body_item_render_callback = [this, &current_room, &me, &fetch_message_future, &tabs, &fetch_body_item, &fetch_message_tab](BodyItem *body_item) {
if(fetch_message_future.valid())
return;
@@ -3900,25 +3938,13 @@ namespace QuickMedia {
}
#endif
+ // Fetch replied to message
if(event_data->status == FetchStatus::FINISHED_LOADING && event_data->message) {
if(event_data->message->related_event_id.empty() || (body_item->embedded_item_status != FetchStatus::NONE && body_item->embedded_item_status != FetchStatus::QUEUED_LOADING))
return;
- // Check if we already have the referenced message as a body item, so we dont create a new one.
- // TODO: Optimize from linear search to hash map
- auto related_body_item = find_body_item_by_event_id(tabs[MESSAGES_TAB_INDEX].body->items.data(), tabs[MESSAGES_TAB_INDEX].body->items.size(), event_data->message->related_event_id);
- if(related_body_item) {
- body_item->embedded_item = std::make_shared<BodyItem>("");
- *body_item->embedded_item = *related_body_item;
- body_item->embedded_item->embedded_item = nullptr;
- body_item->embedded_item->reactions.clear();
- if(related_body_item->userdata && static_cast<Message*>(related_body_item->userdata)->user == me)
- body_item->set_description_color(sf::Color(255, 100, 100));
- else
- body_item->set_description_color(sf::Color::White);
- body_item->embedded_item_status = FetchStatus::FINISHED_LOADING;
+ if(load_cached_related_embedded_item(body_item, event_data->message, me, current_room, tabs[MESSAGES_TAB_INDEX].body->items))
return;
- }
std::string message_event_id = event_data->message->related_event_id;
fetch_body_item = body_item;
@@ -3934,6 +3960,7 @@ namespace QuickMedia {
if(event_data->status != FetchStatus::NONE)
return;
+ // Fetch embed message
// Check if we already have the referenced message as a body item in the messages list, so we dont create a new one.
// TODO: Optimize from linear search to hash map
auto related_body_item = find_body_item_by_event_id(tabs[MESSAGES_TAB_INDEX].body->items.data(), tabs[MESSAGES_TAB_INDEX].body->items.size(), event_data->event_id);
@@ -3961,7 +3988,7 @@ namespace QuickMedia {
};
// TODO: How about instead fetching all messages we have, not only the visible ones? also fetch with multiple threads.
- tabs[MESSAGES_TAB_INDEX].body->body_item_render_callback = [this, &current_room, &me, &fetch_message_future, &tabs, &is_window_focused, &chat_state, &setting_read_marker, &read_marker_timer, &read_marker_timeout_ms, &set_read_marker_future, &find_body_item_by_event_id, &fetch_body_item, &fetch_message_tab](BodyItem *body_item) {
+ tabs[MESSAGES_TAB_INDEX].body->body_item_render_callback = [this, &current_room, &me, &fetch_message_future, &tabs, &is_window_focused, &chat_state, &setting_read_marker, &read_marker_timer, &read_marker_timeout_ms, &set_read_marker_future, &fetch_body_item, &fetch_message_tab](BodyItem *body_item) {
Message *message = static_cast<Message*>(body_item->userdata);
if(!message)
return;
@@ -4010,21 +4037,8 @@ namespace QuickMedia {
return;
}
- // Check if we already have the referenced message as a body item, so we dont create a new one.
- // TODO: Optimize from linear search to hash map
- auto related_body_item = find_body_item_by_event_id(tabs[MESSAGES_TAB_INDEX].body->items.data(), tabs[MESSAGES_TAB_INDEX].body->items.size(), message->related_event_id);
- if(related_body_item) {
- body_item->embedded_item = std::make_shared<BodyItem>("");
- *body_item->embedded_item = *related_body_item;
- body_item->embedded_item->embedded_item = nullptr;
- body_item->embedded_item->reactions.clear();
- if((related_body_item->userdata && static_cast<Message*>(related_body_item->userdata)->user == me) || message_contains_user_mention(message->body, current_room->get_user_display_name(me)) || message_contains_user_mention(message->body, me->user_id))
- body_item->set_description_color(sf::Color(255, 100, 100));
- else
- body_item->set_description_color(sf::Color::White);
- body_item->embedded_item_status = FetchStatus::FINISHED_LOADING;
+ if(load_cached_related_embedded_item(body_item, message, me, current_room, tabs[MESSAGES_TAB_INDEX].body->items))
return;
- }
std::string message_event_id = message->related_event_id;
fetch_body_item = body_item;
@@ -4189,7 +4203,9 @@ namespace QuickMedia {
}
BodyItem *selected_item = tabs[MESSAGES_TAB_INDEX].body->get_selected();
- tabs[MESSAGES_TAB_INDEX].body->insert_items_by_timestamps(messages_to_body_items(current_room, messages, current_room->get_user_display_name(me), me->user_id));
+ auto new_body_items = messages_to_body_items(current_room, messages, current_room->get_user_display_name(me), me->user_id);
+ messages_load_cached_related_embedded_item(new_body_items, tabs[MESSAGES_TAB_INDEX].body->items, me, current_room);
+ tabs[MESSAGES_TAB_INDEX].body->insert_items_by_timestamps(std::move(new_body_items));
if(selected_item && !scroll_to_end) {
int selected_item_index = tabs[MESSAGES_TAB_INDEX].body->get_index_by_body_item(selected_item);
if(selected_item_index != -1)