aboutsummaryrefslogtreecommitdiff
path: root/src/plugins
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2021-05-20 05:20:49 +0200
committerdec05eba <dec05eba@protonmail.com>2021-05-20 05:34:59 +0200
commit3609429b3d8fccd99994dde015b6516376e6835b (patch)
tree2155b1f3f60897a21ca29dbdf150b8ba6bb95376 /src/plugins
parent8e79b2e10827f42d76ec61621f2c484f9cdc2551 (diff)
Move chat page room list logic to matrix delegate
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/Matrix.cpp231
1 files changed, 186 insertions, 45 deletions
diff --git a/src/plugins/Matrix.cpp b/src/plugins/Matrix.cpp
index 8a0f486..afa8738 100644
--- a/src/plugins/Matrix.cpp
+++ b/src/plugins/Matrix.cpp
@@ -437,6 +437,50 @@ namespace QuickMedia {
show_notification("QuickMedia matrix - " + sender + " (" + room->get_name() + ")", body);
}
+ static UsersByRoom::iterator find_user_data_by_id(UsersByRoom &users_by_room, const MatrixEventUserInfo &user_info) {
+ RoomData *room = user_info.room;
+ auto range = users_by_room.equal_range(room);
+ for(auto &it = range.first; it != range.second; ++it) {
+ if(it->second.user_id == user_info.user_id)
+ return it;
+ }
+ return users_by_room.end();
+ }
+
+ void MatrixQuickMedia::add_user(MatrixEventUserInfo user_info) {
+ auto it = find_user_data_by_id(users_by_room, user_info);
+ if(it == users_by_room.end()) {
+ users_by_room.insert(std::make_pair(user_info.room, user_info));
+ if(chat_page)
+ chat_page->add_user(std::move(user_info));
+ }
+ }
+
+ void MatrixQuickMedia::remove_user(MatrixEventUserInfo user_info) {
+ auto it = find_user_data_by_id(users_by_room, user_info);
+ if(it != users_by_room.end()) {
+ users_by_room.erase(it);
+ if(chat_page)
+ chat_page->remove_user(std::move(user_info));
+ }
+ }
+
+ void MatrixQuickMedia::set_user_info(MatrixEventUserInfo user_info) {
+ auto it = find_user_data_by_id(users_by_room, user_info);
+ if(it != users_by_room.end()) {
+ it->second = user_info;
+ if(chat_page)
+ chat_page->set_user_info(std::move(user_info));
+ }
+ }
+
+ void MatrixQuickMedia::for_each_user_in_room(RoomData *room, std::function<void(const MatrixEventUserInfo&)> callback) {
+ auto range = users_by_room.equal_range(room);
+ for(auto &it = range.first; it != range.second; ++it) {
+ callback(it->second);
+ }
+ }
+
static void sort_room_body_items(std::vector<std::shared_ptr<BodyItem>> &room_body_items) {
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);
@@ -597,6 +641,10 @@ namespace QuickMedia {
return PluginResult::OK;
}
+ void MatrixRoomsPage::on_navigate_to_page(Body *body) {
+ body->items_set_dirty(true);
+ }
+
void MatrixRoomsPage::add_body_item(std::shared_ptr<BodyItem> body_item) {
insert_room_body_item_by_timestamp(body->items, body_item);
}
@@ -667,6 +715,10 @@ namespace QuickMedia {
return PluginResult::OK;
}
+ void MatrixRoomTagsPage::on_navigate_to_page(Body *body) {
+ body->items_set_dirty(true);
+ }
+
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);
@@ -679,8 +731,8 @@ namespace QuickMedia {
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->apply_search_filter_for_item(tag_body_item.get());
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;
}
@@ -783,8 +835,8 @@ namespace QuickMedia {
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->apply_search_filter_for_item(body_item.get());
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()) + ")";
@@ -812,6 +864,108 @@ namespace QuickMedia {
rooms_page->matrix_delegate->chat_page = nullptr;
}
+ // Returns |default_value| if the input items is empty
+ static size_t get_body_item_sorted_insert_position_by_author(BodyItems &body_items, const std::string &display_name, size_t default_value) {
+ for(size_t i = 0; i < body_items.size(); ++i) {
+ auto &body_item = body_items[i];
+ if(strcasecmp(display_name.c_str(), body_item->get_author().c_str()) <= 0)
+ return i;
+ }
+ return default_value;
+ }
+
+ static void add_user_to_body_by_user_info(Body *users_body, const MatrixEventUserInfo &user_info) {
+ std::string display_name = user_info.display_name.value_or(user_info.user_id);
+ size_t insert_index = get_body_item_sorted_insert_position_by_author(users_body->items, display_name, 0);
+
+ auto body_item = BodyItem::create("");
+ body_item->url = user_info.user_id;
+ body_item->set_author(std::move(display_name));
+ body_item->set_author_color(user_id_to_color(user_info.user_id));
+ body_item->set_description(user_info.user_id);
+ body_item->set_description_color(sf::Color(179, 179, 179));
+ if(user_info.avatar_url)
+ body_item->thumbnail_url = user_info.avatar_url.value();
+ body_item->thumbnail_mask_type = ThumbnailMaskType::CIRCLE;
+ body_item->thumbnail_size = sf::Vector2i(32, 32);
+
+ users_body->apply_search_filter_for_item(body_item.get());
+ users_body->items.insert(users_body->items.begin() + insert_index, std::move(body_item));
+ }
+
+ void MatrixChatPage::add_user(MatrixEventUserInfo user_info) {
+ if(!current_room || !users_body || user_info.room != current_room)
+ return;
+
+ // Ignore if the user already exists in the room
+ for(auto &body_item : users_body->items) {
+ if(body_item->url == user_info.user_id)
+ return;
+ }
+
+ add_user_to_body_by_user_info(users_body, user_info);
+ }
+
+ void MatrixChatPage::remove_user(MatrixEventUserInfo user_info) {
+ if(!current_room || !users_body || user_info.room != current_room)
+ return;
+
+ for(auto it = users_body->items.begin(), end = users_body->items.end(); it != end; ++it) {
+ if((*it)->url == user_info.user_id) {
+ users_body->items.erase(it);
+ return;
+ }
+ }
+ }
+
+ void MatrixChatPage::set_user_info(MatrixEventUserInfo user_info) {
+ if(!current_room || !users_body || user_info.room != current_room)
+ return;
+
+ for(auto it = users_body->items.begin(), end = users_body->items.end(); it != end; ++it) {
+ if((*it)->url == user_info.user_id) {
+ if(user_info.avatar_url)
+ (*it)->thumbnail_url = user_info.avatar_url.value();
+
+ if(user_info.display_name) {
+ std::string display_name;
+ if(user_info.display_name.value().empty())
+ display_name = user_info.user_id;
+ else
+ display_name = user_info.display_name.value();
+
+ (*it)->set_author(std::move(display_name));
+
+ auto user_body_item = *it;
+ users_body->items.erase(it);
+
+ // TODO: extract_first_line_remove_newline_elipses(room->get_user_display_name(message->user), AUTHOR_MAX_LENGTH),
+ // But that should be done in Text because we need author to be 100% the same as in the input to reorder users
+ users_body->apply_search_filter_for_item(user_body_item.get());
+ size_t insert_index = get_body_item_sorted_insert_position_by_author(users_body->items, user_body_item->get_author(), 0);
+ users_body->items.insert(users_body->items.begin() + insert_index, std::move(user_body_item));
+ }
+
+ return;
+ }
+ }
+ }
+
+ void MatrixChatPage::set_current_room(RoomData *room, Body *users_body) {
+ this->current_room = room;
+ this->users_body = users_body;
+ if(!room || !users_body)
+ return;
+
+ rooms_page->matrix_delegate->for_each_user_in_room(room, [users_body](const MatrixEventUserInfo &user_info) {
+ add_user_to_body_by_user_info(users_body, user_info);
+ });
+ }
+
+ size_t MatrixChatPage::get_num_users_in_current_room() const {
+ return users_body ? users_body->items.size() : 0;
+ }
+
PluginResult MatrixRoomDirectoryPage::submit(const std::string &title, const std::string&, std::vector<Tab> &result_tabs) {
std::string server_name = title;
@@ -1516,11 +1670,9 @@ namespace QuickMedia {
event_user_info.avatar_url = avatar_url;
if(is_new_user) {
- auto event = std::make_unique<MatrixAddUserEvent>(std::move(event_user_info));
- trigger_event(room_data, std::move(event));
+ trigger_event(room_data, MatrixEventType::ADD_USER, std::move(event_user_info));
} else {
- auto event = std::make_unique<MatrixUserInfoEvent>(std::move(event_user_info));
- trigger_event(room_data, std::move(event));
+ trigger_event(room_data, MatrixEventType::USER_INFO, std::move(event_user_info));
}
return user_info;
@@ -1779,8 +1931,7 @@ namespace QuickMedia {
if(is_new_user) {
MatrixEventUserInfo user_info;
user_info.user_id = user->user_id;
- auto event = std::make_unique<MatrixAddUserEvent>(std::move(user_info));
- trigger_event(room_data, std::move(event));
+ trigger_event(room_data, MatrixEventType::ADD_USER, std::move(user_info));
}
auto user_sender = user;
@@ -1791,8 +1942,7 @@ namespace QuickMedia {
if(is_new_user) {
MatrixEventUserInfo user_info;
user_info.user_id = user_sender->user_id;
- auto event = std::make_unique<MatrixAddUserEvent>(std::move(user_info));
- trigger_event(room_data, std::move(event));
+ trigger_event(room_data, MatrixEventType::ADD_USER, std::move(user_info));
}
}
@@ -1934,8 +2084,7 @@ namespace QuickMedia {
user_info.display_name = std::move(new_display_name);
user_info.avatar_url = std::move(new_avatar_url);
- auto event = std::make_unique<MatrixUserInfoEvent>(std::move(user_info));
- trigger_event(room_data, std::move(event));
+ trigger_event(room_data, MatrixEventType::USER_INFO, std::move(user_info));
}
} else {
body = user_display_name + " joined the room";
@@ -3781,7 +3930,7 @@ namespace QuickMedia {
if(room_it == room_data_by_id.end())
return;
- // We want to clear data instead of removing the object iself becasue we want to instance to still be valid,
+ // We want to clear data instead of removing the object iself because we want to instance to still be valid,
// also in the future we can have a "history" tag for rooms we have just left
rooms[room_it->second]->clear_data();
room_data_by_id.erase(room_it);
@@ -3898,11 +4047,9 @@ namespace QuickMedia {
user_info.avatar_url = avatar_url;
if(is_new_user) {
- auto event = std::make_unique<MatrixAddUserEvent>(std::move(user_info));
- trigger_event(room, std::move(event));
+ trigger_event(room, MatrixEventType::ADD_USER, std::move(user_info));
} else {
- auto event = std::make_unique<MatrixUserInfoEvent>(std::move(user_info));
- trigger_event(room, std::move(event));
+ trigger_event(room, MatrixEventType::USER_INFO, std::move(user_info));
}
}
#else
@@ -3974,19 +4121,6 @@ namespace QuickMedia {
#endif
}
- void Matrix::enable_event_queue(RoomData *room) {
- std::lock_guard<std::mutex> lock(event_queue_mutex);
- assert(!current_event_queue_room);
- current_event_queue_room = room;
- }
-
- void Matrix::disable_event_queue() {
- std::lock_guard<std::mutex> lock(event_queue_mutex);
- assert(current_event_queue_room);
- current_event_queue_room = nullptr;
- event_queue.clear();
- }
-
void Matrix::update() {
std::optional<std::function<void()>> task;
while((task = ui_thread_tasks.pop_if_available()) != std::nullopt) {
@@ -3994,20 +4128,27 @@ namespace QuickMedia {
}
}
- std::unique_ptr<MatrixEvent> Matrix::pop_event() {
- std::lock_guard<std::mutex> lock(event_queue_mutex);
- if(!current_event_queue_room || event_queue.empty())
- return nullptr;
-
- auto event_data = std::move(event_queue.front());
- event_queue.pop_front();
- return event_data;
- }
-
- void Matrix::trigger_event(RoomData *room, std::unique_ptr<MatrixEvent> event) {
- std::lock_guard<std::mutex> lock(event_queue_mutex);
- if(sync_is_cache || !current_event_queue_room || current_event_queue_room != room)
- return;
- event_queue.push_back(std::move(event));
+ void Matrix::trigger_event(RoomData *room, MatrixEventType type, MatrixEventUserInfo user_info) {
+ user_info.room = room;
+ switch(type) {
+ case MatrixEventType::ADD_USER: {
+ ui_thread_tasks.push([this, user_info{std::move(user_info)}]{
+ delegate->add_user(std::move(user_info));
+ });
+ break;
+ }
+ case MatrixEventType::REMOVE_USER: {
+ ui_thread_tasks.push([this, user_info{std::move(user_info)}]{
+ delegate->remove_user(std::move(user_info));
+ });
+ break;
+ }
+ case MatrixEventType::USER_INFO: {
+ ui_thread_tasks.push([this, user_info{std::move(user_info)}]{
+ delegate->set_user_info(std::move(user_info));
+ });
+ break;
+ }
+ }
}
} \ No newline at end of file