aboutsummaryrefslogtreecommitdiff
path: root/src/plugins
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2021-05-19 23:45:27 +0200
committerdec05eba <dec05eba@protonmail.com>2021-05-20 01:16:46 +0200
commit8e79b2e10827f42d76ec61621f2c484f9cdc2551 (patch)
tree2f55f23bdebace14d4c56d15f72a40cbafd0ca3e /src/plugins
parent6beaa000d590db342bc0198590686cbbd6304eb4 (diff)
Start on notifications
run matrix delegate on main (ui) thread instead of mutex hell
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/Matrix.cpp486
1 files changed, 148 insertions, 338 deletions
diff --git a/src/plugins/Matrix.cpp b/src/plugins/Matrix.cpp
index 4328888..8a0f486 100644
--- a/src/plugins/Matrix.cpp
+++ b/src/plugins/Matrix.cpp
@@ -349,14 +349,16 @@ namespace QuickMedia {
}
MatrixQuickMedia::MatrixQuickMedia(Program *program, Matrix *matrix, MatrixRoomsPage *rooms_page, MatrixRoomTagsPage *room_tags_page, MatrixInvitesPage *invites_page) :
- program(program), matrix(matrix), rooms_page(rooms_page), room_tags_page(room_tags_page), invites_page(invites_page)
+ program(program), matrix(matrix), chat_page(nullptr), rooms_page(rooms_page), room_tags_page(room_tags_page), invites_page(invites_page)
{
rooms_page->matrix_delegate = this;
room_tags_page->matrix_delegate = this;
}
void MatrixQuickMedia::join_room(RoomData *room) {
- std::lock_guard<std::mutex> lock(room_body_items_mutex);
+ if(room_body_item_by_room.find(room) != room_body_item_by_room.end())
+ return;
+
std::string room_name = room->get_name();
if(room_name.empty())
room_name = room->id;
@@ -368,12 +370,11 @@ namespace QuickMedia {
body_item->thumbnail_mask_type = ThumbnailMaskType::CIRCLE;
body_item->thumbnail_size = sf::Vector2i(32, 32);
room->body_item = body_item;
- rooms_page->add_body_item(body_item);
room_body_item_by_room[room] = body_item;
+ rooms_page->add_body_item(body_item);
}
void MatrixQuickMedia::leave_room(RoomData *room, LeaveType leave_type, const std::string &reason) {
- std::lock_guard<std::mutex> lock(room_body_items_mutex);
room_body_item_by_room.erase(room);
rooms_page->remove_body_item_by_room_id(room->id);
room_tags_page->remove_body_item_by_room_id(room->id);
@@ -382,22 +383,35 @@ namespace QuickMedia {
}
void MatrixQuickMedia::room_add_tag(RoomData *room, const std::string &tag) {
- std::lock_guard<std::mutex> lock(room_body_items_mutex);
- room_tags_page->add_room_body_item_to_tag(room_body_item_by_room[room], tag);
+ auto it = room_body_item_by_room.find(room);
+ if(it == room_body_item_by_room.end())
+ return;
+ room_tags_page->add_room_body_item_to_tag(it->second, tag);
}
void MatrixQuickMedia::room_remove_tag(RoomData *room, const std::string &tag) {
- std::lock_guard<std::mutex> lock(room_body_items_mutex);
- room_tags_page->remove_room_body_item_from_tag(room_body_item_by_room[room], tag);
+ auto it = room_body_item_by_room.find(room);
+ if(it == room_body_item_by_room.end())
+ return;
+ room_tags_page->remove_room_body_item_from_tag(it->second, tag);
}
void MatrixQuickMedia::room_add_new_messages(RoomData *room, const Messages &messages, bool is_initial_sync, bool sync_is_cache, MessageDirection message_dir) {
- std::lock_guard<std::mutex> lock(pending_room_messages_mutex);
- auto &room_messages_data = pending_room_messages[room];
- room_messages_data.messages.insert(room_messages_data.messages.end(), messages.begin(), messages.end());
- room_messages_data.is_initial_sync = is_initial_sync;
- room_messages_data.sync_is_cache = sync_is_cache;
- room_messages_data.message_dir = message_dir;
+ bool is_window_focused = program->is_window_focused();
+ RoomData *current_room = program->get_current_chat_room();
+
+ if(!sync_is_cache && message_dir == MessageDirection::AFTER && !is_initial_sync) {
+ for(auto &message : messages) {
+ if(message->notification_mentions_me) {
+ // 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) && message->related_event_type != RelatedEventType::EDIT && message->related_event_type != RelatedEventType::REDACTION) {
+ show_notification("QuickMedia matrix - " + extract_first_line_remove_newline_elipses(matrix->message_get_author_displayname(message.get()), AUTHOR_MAX_LENGTH) + " (" + room->get_name() + ")", message->body);
+ }
+ }
+ }
+ }
+
+ update_room_description(room, messages, is_initial_sync, sync_is_cache);
}
void MatrixQuickMedia::add_invite(const std::string &room_id, const Invite &invite) {
@@ -419,34 +433,11 @@ namespace QuickMedia {
invites_page->remove_body_item_by_room_id(room_id);
}
- void MatrixQuickMedia::add_unread_notification(RoomData *room, std::string event_id, std::string sender, std::string body) {
- std::lock_guard<std::mutex> lock(room_body_items_mutex);
- Notification notification;
- notification.event_id = std::move(event_id);
- notification.sender = std::move(sender);
- notification.body = std::move(body);
- unread_notifications[room].push_back(std::move(notification));
+ void MatrixQuickMedia::add_unread_notification(RoomData *room, std::string, std::string sender, std::string body) {
+ show_notification("QuickMedia matrix - " + sender + " (" + room->get_name() + ")", body);
}
static void sort_room_body_items(std::vector<std::shared_ptr<BodyItem>> &room_body_items) {
- #if 0
- std::sort(room_body_items.begin(), room_body_items.end(), [](const std::shared_ptr<BodyItem> &body_item1, const std::shared_ptr<BodyItem> &body_item2) {
- return strcasecmp(body_item1->get_title().c_str(), body_item2->get_title().c_str()) < 0;
- });
- #if 1
- std::sort(room_body_items.begin(), room_body_items.end(), [](const std::shared_ptr<BodyItem> &body_item1, const std::shared_ptr<BodyItem> &body_item2) {
- RoomData *room1 = static_cast<RoomData*>(body_item1->userdata);
- RoomData *room2 = static_cast<RoomData*>(body_item2->userdata);
- int room1_focus_sum = (int)(room1->unread_notification_count > 0) + (int)!room1->last_message_read;
- int room2_focus_sum = (int)(room2->unread_notification_count > 0) + (int)!room2->last_message_read;
- return room1_focus_sum > room2_focus_sum;
- });
- #else
- std::sort(room_body_items.begin(), room_body_items.end(), [](const std::shared_ptr<BodyItem> &body_item1, const std::shared_ptr<BodyItem> &body_item2) {
- return strcasecmp(body_item1->get_title().c_str(), body_item2->get_title().c_str()) < 0;
- });
- #endif
- #endif
std::sort(room_body_items.begin(), room_body_items.end(), [](const std::shared_ptr<BodyItem> &body_item1, const std::shared_ptr<BodyItem> &body_item2) {
RoomData *room1 = static_cast<RoomData*>(body_item1->userdata);
RoomData *room2 = static_cast<RoomData*>(body_item2->userdata);
@@ -456,6 +447,18 @@ namespace QuickMedia {
});
}
+ static void insert_room_body_item_by_timestamp(BodyItems &body_items, std::shared_ptr<BodyItem> new_body_item) {
+ RoomData *new_room = static_cast<RoomData*>(new_body_item->userdata);
+ for(auto it = body_items.begin(), end = body_items.end(); it != end; ++it) {
+ RoomData *room = static_cast<RoomData*>((*it)->userdata);
+ if(new_room->last_message_timestamp >= room->last_message_timestamp) {
+ body_items.insert(it, std::move(new_body_item));
+ return;
+ }
+ }
+ body_items.push_back(std::move(new_body_item));
+ }
+
void body_set_selected_item(Body *body, BodyItem *selected_item) {
for(size_t i = 0; i < body->items.size(); ++i) {
if(body->items[i]->url == selected_item->url) {
@@ -466,24 +469,7 @@ namespace QuickMedia {
}
}
- void MatrixQuickMedia::update(MatrixPageType page_type, Body *chat_body, bool messages_tab_visible) {
- update_pending_room_messages(page_type, chat_body, messages_tab_visible);
- std::lock_guard<std::mutex> room_body_lock(room_body_items_mutex);
- for(auto &it : unread_notifications) {
- for(auto &unread_notification : it.second) {
- show_notification("QuickMedia matrix - " + unread_notification.sender + " (" + it.first->get_name() + ")", unread_notification.body);
- }
- }
- //if(!unread_notifications.empty()) {
- // rooms_page->sort_rooms();
- // room_tags_page->sort_rooms();
- //}
- unread_notifications.clear();
- }
-
void MatrixQuickMedia::clear_data() {
- std::lock_guard<std::mutex> lock(pending_room_messages_mutex);
- std::lock_guard<std::mutex> room_body_lock(room_body_items_mutex);
//room_body_item_by_room.clear();
//pending_room_messages.clear();
//rooms_page->clear_data();
@@ -493,22 +479,19 @@ namespace QuickMedia {
}
static std::shared_ptr<Message> get_last_message_by_timestamp(const Messages &messages) {
- #if 0
- return *std::max_element(messages.begin(), messages.end(), [](const std::shared_ptr<Message> &message1, const std::shared_ptr<Message> &message2) {
- return message1->timestamp < message2->timestamp;
- });
- #else
if(messages.empty())
return nullptr;
+
size_t last_message_index = 0;
for(size_t i = 1; i < messages.size(); ++i) {
if(message_is_timeline(messages[i].get()) && messages[i]->timestamp >= messages[last_message_index]->timestamp)
last_message_index = i;
}
+
if(message_is_timeline(messages[last_message_index].get()))
return messages[last_message_index];
+
return nullptr;
- #endif
}
static std::string message_to_room_description_text(Message *message) {
@@ -523,7 +506,7 @@ namespace QuickMedia {
return extract_first_line_remove_newline_elipses(body, 150);
}
- void MatrixQuickMedia::update_room_description(RoomData *room, Messages &new_messages, bool is_initial_sync, bool sync_is_cache, Body *chat_body, bool messages_tab_visible) {
+ void MatrixQuickMedia::update_room_description(RoomData *room, const Messages &new_messages, bool is_initial_sync, bool sync_is_cache) {
time_t read_marker_message_timestamp = 0;
std::shared_ptr<UserInfo> me = matrix->get_me(room);
std::string my_user_read_marker;
@@ -570,7 +553,8 @@ namespace QuickMedia {
if(last_unread_message && !sync_is_cache) {
bool is_window_focused = program->is_window_focused();
RoomData *current_room = program->get_current_chat_room();
- bool set_room_as_unread = !is_window_focused || room != current_room || (!chat_body || !chat_body->is_last_item_fully_visible()) || !messages_tab_visible;
+ Body *chat_body = chat_page ? chat_page->chat_body : nullptr;
+ bool set_room_as_unread = !is_window_focused || room != current_room || (!chat_body || !chat_body->is_last_item_fully_visible()) || (chat_page && !chat_page->messages_tab_visible);
std::string room_desc;
if(set_room_as_unread)
@@ -597,35 +581,7 @@ namespace QuickMedia {
}
}
- void MatrixQuickMedia::update_pending_room_messages(MatrixPageType page_type, Body *chat_body, bool messages_tab_visible) {
- std::lock_guard<std::mutex> lock(pending_room_messages_mutex);
- bool is_window_focused = program->is_window_focused();
- RoomData *current_room = program->get_current_chat_room();
- for(auto &it : pending_room_messages) {
- RoomData *room = it.first;
- auto &messages = it.second.messages;
- bool is_initial_sync = it.second.is_initial_sync;
- //auto &room_body_item = room_body_item_by_room[room];
- //std::string room_desc = extract_first_line_remove_newline_elipses(matrix->message_get_author_displayname(it.second.back().get()), AUTHOR_MAX_LENGTH) + ": " + extract_first_line_remove_newline_elipses(it.second.back()->body, 150);
- //room_body_item->set_description(std::move(room_desc));
-
- if(!it.second.sync_is_cache && it.second.message_dir == MessageDirection::AFTER && !is_initial_sync) {
- for(auto &message : messages) {
- if(message->notification_mentions_me) {
- // 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) && message->related_event_type != RelatedEventType::EDIT && message->related_event_type != RelatedEventType::REDACTION) {
- show_notification("QuickMedia matrix - " + extract_first_line_remove_newline_elipses(matrix->message_get_author_displayname(message.get()), AUTHOR_MAX_LENGTH) + " (" + room->get_name() + ")", message->body);
- }
- }
- }
- }
-
- update_room_description(room, messages, is_initial_sync, it.second.sync_is_cache, chat_body, messages_tab_visible);
- }
- pending_room_messages.clear();
- }
-
- MatrixRoomsPage::MatrixRoomsPage(Program *program, Body *body, std::string title, MatrixRoomTagsPage *room_tags_page, SearchBar *search_bar) : Page(program), body(body), title(std::move(title)), room_tags_page(room_tags_page), search_bar(search_bar) {
+ MatrixRoomsPage::MatrixRoomsPage(Program *program, Body *body, std::string title, MatrixRoomTagsPage *room_tags_page) : Page(program), body(body), title(std::move(title)), room_tags_page(room_tags_page) {
if(room_tags_page)
room_tags_page->set_current_rooms_page(this);
}
@@ -635,90 +591,19 @@ namespace QuickMedia {
room_tags_page->set_current_rooms_page(nullptr);
}
- PluginResult MatrixRoomsPage::submit(const std::string &title, const std::string &url, std::vector<Tab> &result_tabs) {
- (void)title;
+ PluginResult MatrixRoomsPage::submit(const std::string&, const std::string &url, std::vector<Tab> &result_tabs) {
auto chat_page = std::make_unique<MatrixChatPage>(program, url, this);
result_tabs.push_back(Tab{nullptr, std::move(chat_page), nullptr});
return PluginResult::OK;
}
- void MatrixRoomsPage::on_navigate_to_page(Body *body) {
- if(search_bar)
- body->filter_search_fuzzy(search_bar->get_text());
- //sort_room_body_items(body->items);
- }
-
- void MatrixRoomsPage::update() {
- {
- std::lock_guard<std::mutex> lock(mutex);
- int prev_selected_item = body->get_selected_item();
- if(clear_data_on_update) {
- clear_data_on_update = false;
- body->clear_items();
- }
-
- if(!pending_remove_body_items.empty() || !room_body_items.empty()) {
- sort_on_update = true;
- filter_on_update = true;
- }
-
- for(const std::string &room_id : pending_remove_body_items) {
- remove_body_item_by_url(body->items, room_id);
- // TODO: There can be a race condition where current_chat_page is set after entering a room and then we will enter a room we left
- if(current_chat_page && current_chat_page->room_id == room_id) {
- program->set_go_to_previous_page();
- body->select_first_item();
- current_chat_page = nullptr;
- }
- }
-
- pending_remove_body_items.clear();
- body->set_selected_item(prev_selected_item, false);
- body->clamp_selection();
- body->append_items(std::move(room_body_items));
- }
- if(sort_on_update) {
- sort_on_update = false;
- //BodyItem *selected_item = body->get_selected();
- sort_room_body_items(body->items);
- //body_set_selected_item(body, selected_item);
- }
- matrix_delegate->update(MatrixPageType::ROOM_LIST, nullptr, false);
- if(filter_on_update) {
- filter_on_update = false;
- if(search_bar)
- body->filter_search_fuzzy(search_bar->get_text());
- //sort_room_body_items(body->items);
- }
- }
-
void MatrixRoomsPage::add_body_item(std::shared_ptr<BodyItem> body_item) {
- std::lock_guard<std::mutex> lock(mutex);
- room_body_items.push_back(body_item);
+ insert_room_body_item_by_timestamp(body->items, body_item);
}
void MatrixRoomsPage::move_room_to_top(RoomData *room) {
// 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
- std::lock_guard<std::mutex> lock(mutex);
-#if 0
- int room_body_index = body->get_index_by_body_item(room->body_item.get());
- if(room_body_index != -1) {
- std::shared_ptr<BodyItem> body_item = body->items[room_body_index];
- int body_swap_index = -1;
- if(room->unread_notification_count > 0)
- body_swap_index = find_top_body_position_for_mentioned_room(body->items, body_item.get());
- else if(!room->last_message_read)
- body_swap_index = find_top_body_position_for_unread_room(body->items, body_item.get());
- if(body_swap_index != -1 && body_swap_index != room_body_index) {
- body->items.erase(body->items.begin() + room_body_index);
- if(body_swap_index <= room_body_index)
- body->items.insert(body->items.begin() + body_swap_index, std::move(body_item));
- else
- body->items.insert(body->items.begin() + (body_swap_index - 1), std::move(body_item));
- }
- }
-#else
+ // TODO: Optimize with binary search of linear search? or cache the index
int room_body_index = body->get_index_by_body_item(room->body_item.get());
if(room_body_index == -1)
return;
@@ -732,6 +617,7 @@ namespace QuickMedia {
RoomData *room_i = static_cast<RoomData*>(body->items[i]->userdata);
if((int)i == room_body_index)
return;
+
if((int)i != selected_item && room_i && room->last_message_timestamp >= room_i->last_message_timestamp) {
auto body_item_to_insert = body->items[room_body_index];
body->items.erase(body->items.begin() + room_body_index);
@@ -746,35 +632,28 @@ namespace QuickMedia {
return;
}
}
-#endif
}
void MatrixRoomsPage::remove_body_item_by_room_id(const std::string &room_id) {
- std::lock_guard<std::mutex> lock(mutex);
- pending_remove_body_items.push_back(room_id);
+ remove_body_item_by_url(body->items, room_id);
+ if(current_chat_page && current_chat_page->room_id == room_id) {
+ program->set_go_to_previous_page();
+ body->select_first_item();
+ current_chat_page = nullptr;
+ }
}
void MatrixRoomsPage::set_current_chat_page(MatrixChatPage *chat_page) {
- std::lock_guard<std::mutex> lock(mutex);
current_chat_page = chat_page;
}
void MatrixRoomsPage::clear_data() {
- std::lock_guard<std::mutex> lock(mutex);
- room_body_items.clear();
- pending_remove_body_items.clear();
- clear_data_on_update = true;
+ body->clear_items();
if(current_chat_page)
current_chat_page->should_clear_data = true;
}
- void MatrixRoomsPage::sort_rooms() {
- sort_on_update = true;
- }
-
- PluginResult MatrixRoomTagsPage::submit(const std::string &title, const std::string &url, std::vector<Tab> &result_tabs) {
- (void)title;
- std::lock_guard<std::recursive_mutex> lock(mutex);
+ PluginResult MatrixRoomTagsPage::submit(const std::string&, const std::string &url, std::vector<Tab> &result_tabs) {
auto body = create_body();
Body *body_ptr = body.get();
TagData &tag_data = tag_body_items_by_name[url];
@@ -782,105 +661,68 @@ namespace QuickMedia {
//BodyItem *selected_item = body->get_selected();
sort_room_body_items(body->items);
//body_set_selected_item(body.get(), selected_item);
- auto search_bar = create_search_bar("Search...", SEARCH_DELAY_FILTER);
- auto rooms_page = std::make_unique<MatrixRoomsPage>(program, body_ptr, tag_data.tag_item->get_title(), this, search_bar.get());
+ auto rooms_page = std::make_unique<MatrixRoomsPage>(program, body_ptr, tag_data.tag_item->get_title(), this);
rooms_page->matrix_delegate = matrix_delegate;
- result_tabs.push_back(Tab{std::move(body), std::move(rooms_page), std::move(search_bar)});
+ result_tabs.push_back(Tab{std::move(body), std::move(rooms_page), create_search_bar("Search...", SEARCH_DELAY_FILTER)});
return PluginResult::OK;
}
- // TODO: Also add/remove body items to above body (in submit)
- void MatrixRoomTagsPage::update() {
- {
- std::lock_guard<std::recursive_mutex> lock(mutex);
- int prev_selected_item = body->get_selected_item();
- if(clear_data_on_update) {
- clear_data_on_update = false;
- body->clear_items();
- }
-
- for(auto &it : remove_room_body_items_by_tags) {
- auto tag_body_it = tag_body_items_by_name.find(it.first);
- if(tag_body_it == tag_body_items_by_name.end())
- continue;
-
- for(auto &room_to_remove : it.second) {
- auto room_body_item_it = std::find(tag_body_it->second.room_body_items.begin(), tag_body_it->second.room_body_items.end(), room_to_remove);
- if(room_body_item_it != tag_body_it->second.room_body_items.end())
- tag_body_it->second.room_body_items.erase(room_body_item_it);
- }
-
- if(tag_body_it->second.room_body_items.empty()) {
- auto room_body_item_it = std::find(body->items.begin(), body->items.end(), tag_body_it->second.tag_item);
- if(room_body_item_it != body->items.end()) {
- body->items.erase(room_body_item_it);
- filter_on_update = true;
- }
- tag_body_items_by_name.erase(tag_body_it);
- }
+ void MatrixRoomTagsPage::add_room_body_item_to_tag(std::shared_ptr<BodyItem> body_item, const std::string &tag) {
+ TagData *tag_data;
+ auto tag_body_it = tag_body_items_by_name.find(tag);
+ if(tag_body_it == tag_body_items_by_name.end()) {
+ std::string tag_name = tag_get_name(tag);
+ if(tag_name.empty()) {
+ return;
+ } else {
+ auto tag_body_item = BodyItem::create(std::move(tag_name));
+ tag_body_item->url = tag;
+ tag_body_items_by_name.insert(std::make_pair(tag, TagData{tag_body_item, {}}));
+ // TODO: Sort by tag priority
+ body->items.push_back(tag_body_item);
+ body->items_set_dirty();
+ tag_data = &tag_body_items_by_name[tag];
+ tag_data->tag_item = tag_body_item;
}
- remove_room_body_items_by_tags.clear();
-
- for(auto &it : add_room_body_items_by_tags) {
- TagData *tag_data;
- auto tag_body_it = tag_body_items_by_name.find(it.first);
- if(tag_body_it == tag_body_items_by_name.end()) {
- std::string tag_name = tag_get_name(it.first);
- if(!tag_name.empty()) {
- auto tag_body_item = BodyItem::create(std::move(tag_name));
- tag_body_item->url = it.first;
- tag_body_items_by_name.insert(std::make_pair(it.first, TagData{tag_body_item, {}}));
- // TODO: Sort by tag priority
- body->items.push_back(tag_body_item);
- tag_data = &tag_body_items_by_name[it.first];
- tag_data->tag_item = tag_body_item;
- filter_on_update = true;
- }
- } else {
- tag_data = &tag_body_it->second;
- }
+ } else {
+ tag_data = &tag_body_it->second;
+ }
- for(auto &room_body_item : it.second) {
- bool already_exists = false;
- for(auto &body_it : tag_data->room_body_items) {
- if(body_it->userdata == room_body_item->userdata) {
- already_exists = true;
- break;
- }
- }
- if(!already_exists)
- tag_data->room_body_items.push_back(room_body_item);
- }
+ bool already_exists = false;
+ for(auto &body_it : tag_data->room_body_items) {
+ if(body_it->userdata == body_item->userdata) {
+ already_exists = true;
+ break;
}
- add_room_body_items_by_tags.clear();
- body->set_selected_item(prev_selected_item, false);
}
- matrix_delegate->update(MatrixPageType::ROOM_LIST, nullptr, false);
- if(filter_on_update) {
- filter_on_update = false;
- if(search_bar)
- body->filter_search_fuzzy(search_bar->get_text());
- }
- }
- void MatrixRoomTagsPage::add_room_body_item_to_tag(std::shared_ptr<BodyItem> body_item, const std::string &tag) {
- std::lock_guard<std::recursive_mutex> lock(mutex);
- add_room_body_items_by_tags[tag].push_back(body_item);
+ if(!already_exists)
+ tag_data->room_body_items.push_back(body_item);
}
void MatrixRoomTagsPage::remove_room_body_item_from_tag(std::shared_ptr<BodyItem> body_item, const std::string &tag) {
- std::lock_guard<std::recursive_mutex> lock(mutex);
- remove_room_body_items_by_tags[tag].push_back(body_item);
+ auto tag_body_it = tag_body_items_by_name.find(tag);
+ if(tag_body_it == tag_body_items_by_name.end())
+ return;
+
+ auto room_body_item_it = std::find(tag_body_it->second.room_body_items.begin(), tag_body_it->second.room_body_items.end(), body_item);
+ if(room_body_item_it != tag_body_it->second.room_body_items.end())
+ tag_body_it->second.room_body_items.erase(room_body_item_it);
+
+ if(tag_body_it->second.room_body_items.empty()) {
+ auto room_body_item_it = std::find(body->items.begin(), body->items.end(), tag_body_it->second.tag_item);
+ if(room_body_item_it != body->items.end())
+ body->items.erase(room_body_item_it);
+ tag_body_items_by_name.erase(tag_body_it);
+ }
}
void MatrixRoomTagsPage::move_room_to_top(RoomData *room) {
- std::lock_guard<std::recursive_mutex> lock(mutex);
if(current_rooms_page)
current_rooms_page->move_room_to_top(room);
}
void MatrixRoomTagsPage::remove_body_item_by_room_id(const std::string &room_id) {
- std::lock_guard<std::recursive_mutex> lock(mutex);
for(auto it = tag_body_items_by_name.begin(); it != tag_body_items_by_name.end();) {
remove_body_item_by_url(it->second.room_body_items, room_id);
if(it->second.room_body_items.empty())
@@ -888,32 +730,23 @@ namespace QuickMedia {
else
++it;
}
+
if(current_rooms_page)
current_rooms_page->remove_body_item_by_room_id(room_id);
}
void MatrixRoomTagsPage::set_current_rooms_page(MatrixRoomsPage *rooms_page) {
- std::lock_guard<std::recursive_mutex> lock(mutex);
current_rooms_page = rooms_page;
}
void MatrixRoomTagsPage::clear_data() {
- std::lock_guard<std::recursive_mutex> lock(mutex);
tag_body_items_by_name.clear();
- add_room_body_items_by_tags.clear();
- remove_room_body_items_by_tags.clear();
- clear_data_on_update = true;
+ body->clear_items();
if(current_rooms_page)
current_rooms_page->clear_data();
}
- void MatrixRoomTagsPage::sort_rooms() {
- std::lock_guard<std::recursive_mutex> lock(mutex);
- if(current_rooms_page)
- current_rooms_page->sort_rooms();
- }
-
- MatrixInvitesPage::MatrixInvitesPage(Program *program, Matrix *matrix, Body *body, SearchBar *search_bar) : Page(program), matrix(matrix), body(body), search_bar(search_bar) {
+ MatrixInvitesPage::MatrixInvitesPage(Program *program, Matrix *matrix, Body *body) : Page(program), matrix(matrix), body(body) {
}
@@ -948,71 +781,35 @@ namespace QuickMedia {
return PluginResult::OK;
}
- void MatrixInvitesPage::update() {
- std::lock_guard<std::mutex> lock(mutex);
-
- int prev_selected_item = body->get_selected_item();
- if(clear_data_on_update) {
- clear_data_on_update = false;
- body->clear_items();
- }
-
- if(!pending_remove_body_items.empty() || !body_items.empty())
- filter_on_update = true;
-
- for(const std::string &room_id : pending_remove_body_items) {
- remove_body_item_by_url(body->items, room_id);
- }
- pending_remove_body_items.clear();
- body->set_selected_item(prev_selected_item, false);
- body->clamp_selection();
-
+ void MatrixInvitesPage::add_body_item(std::shared_ptr<BodyItem> body_item) {
// TODO: Insert in reverse order (to show the latest invite at the top?)
- body->insert_items_by_timestamps(std::move(body_items));
+ body->insert_item_by_timestamp(std::move(body_item));
+ body->items_set_dirty();
if(body->items.size() != prev_invite_count) {
prev_invite_count = body->items.size();
title = "Invites (" + std::to_string(body->items.size()) + ")";
}
-
- if(filter_on_update) {
- filter_on_update = false;
- if(search_bar)
- body->filter_search_fuzzy(search_bar->get_text());
- }
- }
-
- void MatrixInvitesPage::add_body_item(std::shared_ptr<BodyItem> body_item) {
- std::lock_guard<std::mutex> lock(mutex);
- body_items.push_back(std::move(body_item));
}
void MatrixInvitesPage::remove_body_item_by_room_id(const std::string &room_id) {
- std::lock_guard<std::mutex> lock(mutex);
- pending_remove_body_items.push_back(room_id);
+ remove_body_item_by_url(body->items, room_id);
}
void MatrixInvitesPage::clear_data() {
- std::lock_guard<std::mutex> lock(mutex);
- body_items.clear();
- pending_remove_body_items.clear();
- title = "Invites (0)";
+ body->clear_items();
prev_invite_count = 0;
- clear_data_on_update = true;
+ title = "Invites (0)";
}
MatrixChatPage::MatrixChatPage(Program *program, std::string room_id, MatrixRoomsPage *rooms_page) : Page(program), room_id(std::move(room_id)), rooms_page(rooms_page) {
assert(rooms_page);
rooms_page->set_current_chat_page(this);
+ rooms_page->matrix_delegate->chat_page = this;
}
MatrixChatPage::~MatrixChatPage() {
rooms_page->set_current_chat_page(nullptr);
- }
-
- void MatrixChatPage::update() {
- rooms_page->matrix_delegate->update(MatrixPageType::CHAT, chat_body, messages_tab_visible);
- if(rooms_page)
- rooms_page->update();
+ rooms_page->matrix_delegate->chat_page = nullptr;
}
PluginResult MatrixRoomDirectoryPage::submit(const std::string &title, const std::string&, std::vector<Tab> &result_tabs) {
@@ -1466,7 +1263,9 @@ namespace QuickMedia {
std::string event_id(event_id_json.GetString(), event_id_json.GetStringLength());
std::string sender(sender_json.GetString(), sender_json.GetStringLength());
std::string body(body_json.GetString(), body_json.GetStringLength());
- delegate->add_unread_notification(room, std::move(event_id), std::move(sender), std::move(body));
+ ui_thread_tasks.push([this, room, event_id{std::move(event_id)}, sender{std::move(sender)}, body{std::move(body)}] {
+ delegate->add_unread_notification(room, std::move(event_id), std::move(sender), std::move(body));
+ });
}
return PluginResult::OK;
}
@@ -1586,7 +1385,7 @@ namespace QuickMedia {
}
if(is_new_room)
- delegate->join_room(room);
+ ui_thread_tasks.push([this, room]{ delegate->join_room(room); });
events_add_messages(events_json, room, MessageDirection::AFTER, has_unread_notifications);
if(!is_additional_messages_sync)
@@ -1600,12 +1399,12 @@ namespace QuickMedia {
}
if(is_new_room)
- delegate->join_room(room);
+ ui_thread_tasks.push([this, room]{ delegate->join_room(room); });
}
if(remove_invite(room_id_str)) {
// TODO: Show leave type and reason and who caused the invite to be removed
- delegate->remove_invite(room_id_str);
+ ui_thread_tasks.push([this, room_id_str{std::move(room_id_str)}]{ delegate->remove_invite(room_id_str); });
}
if(account_data_json.IsObject()) {
@@ -1618,7 +1417,7 @@ namespace QuickMedia {
std::set<std::string> &room_tags = room->get_tags_unsafe();
if(room_tags.empty()) {
room_tags.insert(OTHERS_ROOM_TAG);
- delegate->room_add_tag(room, OTHERS_ROOM_TAG);
+ ui_thread_tasks.push([this, room]{ delegate->room_add_tag(room, OTHERS_ROOM_TAG); });
}
room->release_room_lock();
}
@@ -1637,7 +1436,8 @@ namespace QuickMedia {
std::lock_guard<std::recursive_mutex> lock(room_data_mutex);
for(auto &room : rooms) {
if(existing_rooms.find(room.get()) == existing_rooms.end()) {
- delegate->leave_room(room.get(), LeaveType::LEAVE, "");
+ RoomData *room_p = room.get();
+ ui_thread_tasks.push([this, room_p]{ delegate->leave_room(room_p, LeaveType::LEAVE, ""); });
remove_room(room->id);
}
}
@@ -1925,8 +1725,13 @@ namespace QuickMedia {
}
}
- if(delegate)
- delegate->room_add_new_messages(room_data, new_messages, next_batch.empty(), sync_is_cache, message_dir);
+ if(delegate) {
+ bool cache_sync = sync_is_cache;
+ bool is_initial_sync = next_batch.empty();
+ ui_thread_tasks.push([this, room_data, cache_sync, new_messages{std::move(new_messages)}, is_initial_sync, message_dir]{
+ delegate->room_add_new_messages(room_data, new_messages, is_initial_sync, cache_sync, message_dir);
+ });
+ }
return num_new_messages;
}
@@ -2472,18 +2277,18 @@ namespace QuickMedia {
for(const std::string &room_tag : room_tags) {
auto it = new_tags.find(room_tag);
if(it == new_tags.end())
- delegate->room_remove_tag(room_data, room_tag);
+ ui_thread_tasks.push([this, room_data, room_tag]{ delegate->room_remove_tag(room_data, room_tag); });
}
for(const std::string &new_tag : new_tags) {
auto it = room_tags.find(new_tag);
if(it == room_tags.end())
- delegate->room_add_tag(room_data, new_tag);
+ ui_thread_tasks.push([this, room_data, new_tag]{ delegate->room_add_tag(room_data, new_tag); });
}
if(new_tags.empty()) {
new_tags.insert(OTHERS_ROOM_TAG);
- delegate->room_add_tag(room_data, OTHERS_ROOM_TAG);
+ ui_thread_tasks.push([this, room_data]{ delegate->room_add_tag(room_data, OTHERS_ROOM_TAG); });
}
room_tags = std::move(new_tags);
@@ -2556,7 +2361,7 @@ namespace QuickMedia {
std::string room_id_str(room_id.GetString(), room_id.GetStringLength());
if(set_invite(room_id_str, invite))
- delegate->add_invite(room_id_str, std::move(invite));
+ ui_thread_tasks.push([this, room_id_str{std::move(room_id_str)}, invite{std::move(invite)}]{ delegate->add_invite(room_id_str, std::move(invite)); });
break;
}
@@ -2579,7 +2384,7 @@ namespace QuickMedia {
std::string room_id_str(room_id.GetString(), room_id.GetStringLength());
if(remove_invite(room_id_str)) {
// TODO: Show leave type and reason and who caused the invite to be removed
- delegate->remove_invite(room_id_str);
+ ui_thread_tasks.push([this, room_id_str{std::move(room_id_str)}]{ delegate->remove_invite(room_id_str); });
}
const rapidjson::Value &timeline_json = GetMember(it.value, "timeline");
@@ -2638,7 +2443,7 @@ namespace QuickMedia {
if(!reason_str.empty())
desc += ", reason: " + reason_str;
- delegate->leave_room(room, leave_type, desc);
+ ui_thread_tasks.push([this, room, leave_type, desc{std::move(desc)}]{ delegate->leave_room(room, leave_type, desc); });
remove_room(room_id_str);
break;
}
@@ -3047,9 +2852,7 @@ namespace QuickMedia {
"</mx-reply>" + std::move(formatted_body);
}
- // TODO: Support greentext
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<Message> instead of raw pointer...
Message *relates_to_message_raw = (Message*)relates_to;
std::string transaction_id = custom_transaction_id;
@@ -3133,7 +2936,7 @@ namespace QuickMedia {
std::string formatted_body_edit_str;
rapidjson::Document request_data(rapidjson::kObjectType);
- request_data.AddMember("msgtype", "m.text", request_data.GetAllocator()); // TODO: Allow other types of edits
+ request_data.AddMember("msgtype", "m.text", request_data.GetAllocator());
request_data.AddMember("body", rapidjson::StringRef(body_edit_str.c_str()), request_data.GetAllocator());
if(!formatted_body.empty()) {
formatted_body_edit_str = " * " + formatted_body;
@@ -3772,12 +3575,12 @@ namespace QuickMedia {
room = new_room.get();
add_room(std::move(new_room));
- delegate->join_room(room);
+ ui_thread_tasks.push([this, room]{ delegate->join_room(room); });
room->acquire_room_lock();
std::set<std::string> &room_tags = room->get_tags_unsafe();
if(room_tags.empty()) {
room_tags.insert(OTHERS_ROOM_TAG);
- delegate->room_add_tag(room, OTHERS_ROOM_TAG);
+ ui_thread_tasks.push([this, room]{ delegate->room_add_tag(room, OTHERS_ROOM_TAG); });
}
room->release_room_lock();
}
@@ -3799,7 +3602,7 @@ namespace QuickMedia {
if(download_result == DownloadResult::OK) {
RoomData *room = get_room_by_id(room_id);
if(room) {
- delegate->leave_room(room, LeaveType::LEAVE, "");
+ ui_thread_tasks.push([this, room]{ delegate->leave_room(room, LeaveType::LEAVE, ""); });
remove_room(room_id);
}
}
@@ -4019,7 +3822,7 @@ namespace QuickMedia {
// We intentionally dont clear |rooms| here because we want the objects inside it to still be valid. TODO: Clear |rooms| here
//room_data_by_id.clear();
invites.clear();
- delegate->clear_data();
+ ui_thread_tasks.push([this]{ delegate->clear_data(); });
}
std::shared_ptr<UserInfo> Matrix::get_user_by_id(RoomData *room, const std::string &user_id, bool *is_new_user, bool create_if_not_found) {
@@ -4184,6 +3987,13 @@ namespace QuickMedia {
event_queue.clear();
}
+ void Matrix::update() {
+ std::optional<std::function<void()>> task;
+ while((task = ui_thread_tasks.pop_if_available()) != std::nullopt) {
+ task.value()();
+ }
+ }
+
std::unique_ptr<MatrixEvent> Matrix::pop_event() {
std::lock_guard<std::mutex> lock(event_queue_mutex);
if(!current_event_queue_room || event_queue.empty())