From 4af367373f6f92b0fc1d79b2871fa942e1eb86fa Mon Sep 17 00:00:00 2001 From: dec05eba Date: Mon, 9 Nov 2020 00:08:53 +0100 Subject: Matrix: update user display name/avatar when updated in /sync; fix backspace search delay --- src/plugins/Matrix.cpp | 148 +++++++++++++++++++++++++++++++------------------ 1 file changed, 93 insertions(+), 55 deletions(-) (limited to 'src/plugins/Matrix.cpp') diff --git a/src/plugins/Matrix.cpp b/src/plugins/Matrix.cpp index 7c170c9..0c94dd5 100644 --- a/src/plugins/Matrix.cpp +++ b/src/plugins/Matrix.cpp @@ -84,6 +84,30 @@ namespace QuickMedia { } } + static sf::Color user_id_to_color(const std::string &user_id) { + uint32_t color = 2166136261; + for(unsigned char c : user_id) { + color = (color * 16777619) ^ c; + } + sf::Uint8 *col = (sf::Uint8*)&color; + sf::Color result(col[0], col[1], col[2]); + result.r = std::min(255, 80 + (int)result.r); + result.g = std::min(255, 80 + (int)result.g); + result.b = std::min(255, 80 + (int)result.b); + result.a = 255; + return result; + } + + UserInfo::UserInfo(RoomData *room, std::string user_id) : + room(room), display_name_color(user_id_to_color(user_id)), user_id(std::move(user_id)), display_name(user_id) { + + } + + UserInfo::UserInfo(RoomData *room, std::string user_id, std::string display_name, std::string avatar_url) : + room(room), display_name_color(user_id_to_color(user_id)), user_id(std::move(user_id)), display_name(std::move(display_name)), avatar_url(std::move(avatar_url)) { + + } + std::shared_ptr RoomData::get_user_by_id(const std::string &user_id) { std::lock_guard lock(room_mutex); auto user_it = user_info_by_user_id.find(user_id); @@ -102,11 +126,33 @@ namespace QuickMedia { user->read_marker_event_id = event_id; } - std::string RoomData::get_user_read_marker(std::shared_ptr &user) { + std::string RoomData::get_user_read_marker(const std::shared_ptr &user) { std::lock_guard lock(user_mutex); return user->read_marker_event_id; } + std::string RoomData::get_user_display_name(const std::shared_ptr &user) { + std::lock_guard lock(user_mutex); + return user->display_name; + } + + std::string RoomData::get_user_avatar_url(const std::shared_ptr &user) { + std::lock_guard lock(user_mutex); + return user->avatar_url; + } + + void RoomData::set_user_display_name(std::shared_ptr &user, std::string display_name) { + std::lock_guard lock(user_mutex); + user->display_name = std::move(display_name); + if(user->display_name.empty()) + user->display_name = user->user_id; + } + + void RoomData::set_user_avatar_url(std::shared_ptr &user, std::string avatar_url) { + std::lock_guard lock(user_mutex); + user->avatar_url = std::move(avatar_url); + } + void RoomData::prepend_messages_reverse(const std::vector> &new_messages) { std::lock_guard lock(room_mutex); for(auto it = new_messages.begin(); it != new_messages.end(); ++it) { @@ -280,8 +326,9 @@ namespace QuickMedia { } void MatrixQuickMedia::add_invite(const std::string &room_id, const Invite &invite) { + std::string invited_by_display_name = invite.invited_by->room->get_user_display_name(invite.invited_by); auto body_item = BodyItem::create(invite.room_name); - body_item->set_description("Invited by " + invite.invited_by->display_name + " (" + invite.invited_by->user_id + ")"); + body_item->set_description("Invited by " + invited_by_display_name + " (" + invite.invited_by->user_id + ")"); body_item->url = room_id; body_item->thumbnail_url = invite.room_avatar_url; body_item->thumbnail_mask_type = ThumbnailMaskType::CIRCLE; @@ -289,7 +336,7 @@ namespace QuickMedia { body_item->set_timestamp(invite.timestamp); invites_page->add_body_item(std::move(body_item)); if(invite.new_invite) - show_notification("QuickMedia matrix - " + invite.room_name, "You were invited to " + invite.room_name + " by " + invite.invited_by->display_name + " (" + invite.invited_by->user_id + ")"); + show_notification("QuickMedia matrix - " + invite.room_name, "You were invited to " + invite.room_name + " by " + invited_by_display_name + " (" + invite.invited_by->user_id + ")"); } void MatrixQuickMedia::remove_invite(const std::string &room_id) { @@ -1381,20 +1428,6 @@ namespace QuickMedia { return PluginResult::OK; } - static sf::Color user_id_to_color(const std::string &user_id) { - uint32_t color = 2166136261; - for(unsigned char c : user_id) { - color = (color * 16777619) ^ c; - } - sf::Uint8 *col = (sf::Uint8*)&color; - sf::Color result(col[0], col[1], col[2]); - result.r = std::min(255, 80 + (int)result.r); - result.g = std::min(255, 80 + (int)result.g); - result.b = std::min(255, 80 + (int)result.b); - result.a = 255; - return result; - } - void Matrix::events_add_user_info(const rapidjson::Value &events_json, RoomData *room_data) { if(!events_json.IsArray()) return; @@ -1439,14 +1472,11 @@ namespace QuickMedia { const rapidjson::Value &display_name_json = GetMember(json, "displayname"); - auto user_info = std::make_shared(); - user_info->user_id = user_id; - user_info->avatar_url = thumbnail_url_extract_media_id(avatar_url_str); - if(!user_info->avatar_url.empty()) - user_info->avatar_url = homeserver + "/_matrix/media/r0/thumbnail/" + user_info->avatar_url + "?width=32&height=32&method=crop"; // TODO: Remove the constant strings around to reduce memory usage (6.3mb) - user_info->display_name = display_name_json.IsString() ? display_name_json.GetString() : user_id; - user_info->display_name_color = user_id_to_color(user_id); - + std::string display_name = display_name_json.IsString() ? display_name_json.GetString() : user_id; + std::string avatar_url = thumbnail_url_extract_media_id(avatar_url_str); + if(!avatar_url.empty()) + avatar_url = homeserver + "/_matrix/media/r0/thumbnail/" + avatar_url + "?width=32&height=32&method=crop"; // TODO: Remove the constant strings around to reduce memory usage (6.3mb) + auto user_info = std::make_shared(room_data, user_id, std::move(display_name), std::move(avatar_url)); // Overwrites user data room_data->add_user(user_info); return user_info; @@ -1590,6 +1620,7 @@ namespace QuickMedia { // TODO: Preallocate std::vector> new_messages; auto me = get_me(room_data); + std::string my_display_name = room_data->get_user_display_name(me); for(const rapidjson::Value &event_item_json : events_json.GetArray()) { std::shared_ptr new_message = parse_message_event(event_item_json, room_data); @@ -1618,7 +1649,7 @@ namespace QuickMedia { // TODO: Is @room ok? shouldn't we also check if the user has permission to do @room? (only when notifications are limited to @mentions) // TODO: Is comparing against read marker timestamp ok enough? if(me && message->timestamp > read_marker_message_timestamp) - message->mentions_me = message_contains_user_mention(message->body, me->display_name) || message_contains_user_mention(message->body, me->user_id) || message_contains_user_mention(message->body, "@room"); + message->mentions_me = message_contains_user_mention(message->body, my_display_name) || message_contains_user_mention(message->body, me->user_id) || message_contains_user_mention(message->body, "@room"); } } @@ -1726,6 +1757,8 @@ namespace QuickMedia { if(strcmp(type_json.GetString(), "m.room.message") == 0) { } else if(strcmp(type_json.GetString(), "m.room.member") == 0) { + std::string user_display_name = room_data->get_user_display_name(user); + std::string sender_display_name = room_data->get_user_display_name(user_sender); std::string body; const rapidjson::Value &membership_json = GetMember(*content_json, "membership"); if(strcmp(membership_json.GetString(), "join") == 0) { @@ -1737,31 +1770,40 @@ namespace QuickMedia { const rapidjson::Value &prev_avatar_url_json = GetMember(prev_content_json, "avatar_url"); const rapidjson::Value &new_displayname_json = GetMember(*content_json, "displayname"); const rapidjson::Value &new_avatar_url_json = GetMember(*content_json, "avatar_url"); - if(new_displayname_json.IsString() && (!prev_displayname_json.IsString() || strcmp(new_displayname_json.GetString(), prev_displayname_json.GetString()) != 0)) - body = user->display_name + " changed their display name to " + std::string(new_displayname_json.GetString()); - else if(!new_displayname_json.IsString() && prev_displayname_json.IsString()) - body = user->display_name + " removed their display name"; - else if(new_avatar_url_json.IsString() && (!prev_avatar_url_json.IsString() || strcmp(new_avatar_url_json.GetString(), prev_avatar_url_json.GetString()) != 0)) - body = user->display_name + " changed their profile picture"; - else if(!new_avatar_url_json.IsString() && prev_avatar_url_json.IsString()) - body = user->display_name + " removed their profile picture."; - else - body = user->display_name + " joined the room"; + if(new_displayname_json.IsString() && (!prev_displayname_json.IsString() || strcmp(new_displayname_json.GetString(), prev_displayname_json.GetString()) != 0)) { + std::string new_displayname_str = std::string(new_displayname_json.GetString()); + body = user_display_name + " changed their display name to " + new_displayname_str; + room_data->set_user_display_name(user, std::move(new_displayname_str)); + } else if(!new_displayname_json.IsString() && prev_displayname_json.IsString()) { + body = user_display_name + " removed their display name"; + room_data->set_user_display_name(user, ""); + } else if(new_avatar_url_json.IsString() && (!prev_avatar_url_json.IsString() || strcmp(new_avatar_url_json.GetString(), prev_avatar_url_json.GetString()) != 0)) { + body = user_display_name + " changed their profile picture"; + std::string new_avatar_url_str = thumbnail_url_extract_media_id(new_avatar_url_json.GetString()); + if(!new_avatar_url_str.empty()) + new_avatar_url_str = homeserver + "/_matrix/media/r0/thumbnail/" + new_avatar_url_str + "?width=32&height=32&method=crop"; // TODO: Remove the constant strings around to reduce memory usage (6.3mb) + room_data->set_user_avatar_url(user, std::move(new_avatar_url_str)); + } else if(!new_avatar_url_json.IsString() && prev_avatar_url_json.IsString()) { + body = user_display_name + " removed their profile picture."; + room_data->set_user_avatar_url(user, ""); + } else { + body = user_display_name + " joined the room"; + } } else { - body = user->display_name + " joined the room"; + body = user_display_name + " joined the room"; } } else { - body = user->display_name + " joined the room"; + body = user_display_name + " joined the room"; } } else if(strcmp(membership_json.GetString(), "leave") == 0) { if(sent_by_somebody_else) - body = user->display_name + " was kicked from the room by " + user_sender->display_name; + body = user_display_name + " was kicked from the room by " + sender_display_name; else - body = user->display_name + " left the room"; + body = user_display_name + " left the room"; } else if(strcmp(membership_json.GetString(), "invite") == 0) { - body = user->display_name + " was invited to the room by " + user_sender->display_name; + body = user_display_name + " was invited to the room by " + sender_display_name; } else if(strcmp(membership_json.GetString(), "ban") == 0) { - body = user->display_name + " was banned from the room by " + user_sender->display_name; + body = user_display_name + " was banned from the room by " + sender_display_name; } else { body = "unimplemented membership: " + std::string(membership_json.GetString()); } @@ -1831,7 +1873,7 @@ namespace QuickMedia { message->type = MessageType::FILE; } else if(strcmp(content_type.GetString(), "m.emote") == 0) { // this is a /me message, TODO: show /me messages differently message->type = MessageType::TEXT; - prefix = "*" + user->display_name + "* "; + prefix = "*" + room_data->get_user_display_name(user) + "* "; } else if(strcmp(content_type.GetString(), "m.notice") == 0) { // TODO: show notices differently message->type = MessageType::TEXT; prefix = "* NOTICE * "; @@ -1867,16 +1909,16 @@ namespace QuickMedia { return user_id.substr(1, index - 1); } - static std::string combine_user_display_names_for_room_name(const std::vector> &user_info, const std::string &fallback_user_id) { + static std::string combine_user_display_names_for_room_name(std::vector> &user_info, const std::string &fallback_user_id) { std::string result; if(user_info.size() == 0) result = extract_user_name_from_user_id(fallback_user_id); else if(user_info.size() == 1) - result = user_info[0]->display_name; + result = user_info[0]->room->get_user_display_name(user_info[0]); else if(user_info.size() == 2) - result = user_info[0]->display_name + " and " + user_info[1]->display_name; + result = user_info[0]->room->get_user_display_name(user_info[0]) + " and " + user_info[1]->room->get_user_display_name(user_info[1]); else if(user_info.size() > 2) - result = user_info[0]->display_name + ", " + user_info[1]->display_name + " and " + std::to_string(user_info.size() - 2) + " other(s)"; + result = user_info[0]->room->get_user_display_name(user_info[0]) + ", " + user_info[1]->room->get_user_display_name(user_info[1]) + " and " + std::to_string(user_info.size() - 2) + " other(s)"; return result; } @@ -1956,10 +1998,10 @@ namespace QuickMedia { if(users_excluding_me.empty()) { auto user = get_user_by_id(room_data, creator_json.GetString()); if(user) - room_data->set_avatar_url(user->avatar_url); + room_data->set_avatar_url(room_data->get_user_avatar_url(user)); } else { // TODO: If there are multiple users, then we want to use some other type of avatar, not the first users avatar - room_data->set_avatar_url(users_excluding_me.front()->avatar_url); + room_data->set_avatar_url(room_data->get_user_avatar_url(users_excluding_me.front())); } has_room_avatar_url = true; } @@ -3128,8 +3170,7 @@ namespace QuickMedia { } std::string Matrix::message_get_author_displayname(Message *message) const { - // TODO: Thread safe? - return message->user->display_name; + return message->user->room->get_user_display_name(message->user); } PluginResult Matrix::get_config(int *upload_size) { @@ -3255,10 +3296,7 @@ namespace QuickMedia { return parse_user_info(json_root, user_id, room); #else fprintf(stderr, "Unknown user: %s, creating locally... synapse bug?\n", user_id.c_str()); - auto user_info = std::make_shared(); - user_info->user_id = user_id; - user_info->display_name = user_id; - user_info->display_name_color = user_id_to_color(user_id); + auto user_info = std::make_shared(room, user_id); room->add_user(user_info); return user_info; #endif -- cgit v1.2.3