aboutsummaryrefslogtreecommitdiff
path: root/src/QuickMedia.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/QuickMedia.cpp')
-rw-r--r--src/QuickMedia.cpp107
1 files changed, 42 insertions, 65 deletions
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<BodyItem> body_item;
- bool last_message_read;
- time_t last_read_message_timestamp;
- };
-
- std::unordered_map<std::shared_ptr<RoomData>, RoomBodyData> body_items_by_room;
- std::shared_ptr<RoomData> 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, &current_room, &is_window_focused](RoomSyncMessages &room_sync_messages, bool is_first_sync) mutable {
+ auto process_new_room_messages = [this, &tabs, &current_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<BodyItem*>(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<RoomData> {
- 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<BodyItem> *body_items, size_t num_body_items, const std::string &event_id) -> std::shared_ptr<BodyItem> {
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<std::shared_ptr<RoomData>, Messages> unreferenced_event_by_room;
+ std::unordered_map<RoomData*, Messages> 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, &current_room, &current_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, &current_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<ThumbnailData>();
- }
+ room_name_text.setString(static_cast<BodyItem*>(current_room->userdata)->get_title());
+ room_avatar_thumbnail_data = std::make_shared<ThumbnailData>();
read_marker_timeout_ms = 0;
redraw = true;
@@ -3255,11 +3233,11 @@ namespace QuickMedia {
std::future<Messages> previous_messages_future;
bool fetching_previous_messages_running = false;
- std::shared_ptr<RoomData> previous_messages_future_room;
+ RoomData *previous_messages_future_room = nullptr;
std::future<std::shared_ptr<Message>> fetch_reply_message_future;
bool fetching_reply_message_running = false;
- std::shared_ptr<RoomData> 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<RoomData> 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, &current_room, &current_room_body_data, &room_name_text, &room_search_bar](Rooms &rooms) {
+ auto add_new_rooms = [&tabs, &current_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<BodyItem*>(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<BodyItem*>(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<BodyItem*>(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<RoomData> 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());