aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2022-10-25 08:12:36 +0200
committerdec05eba <dec05eba@protonmail.com>2022-10-25 08:12:36 +0200
commitd77d315eaf5658e93cf7384cc7f1ebf7a86bd87c (patch)
tree670f86b1c7932c63afc93bf2e55915cdb9071689 /src
parent162502874dc266bce6a73d5cd70e06c3829ead28 (diff)
Matrix: apply user display name and avatar update by timestamp
Diffstat (limited to 'src')
-rw-r--r--src/plugins/Matrix.cpp177
1 files changed, 110 insertions, 67 deletions
diff --git a/src/plugins/Matrix.cpp b/src/plugins/Matrix.cpp
index 14f49bf..7715a6b 100644
--- a/src/plugins/Matrix.cpp
+++ b/src/plugins/Matrix.cpp
@@ -116,15 +116,30 @@ namespace QuickMedia {
return colors[color_hash_code(user_id) % num_colors];
}
+ bool TimestampedDisplayData::set_data_if_newer(std::string new_data, time_t new_timestamp) {
+ if(new_timestamp == 0) {
+ data = std::move(new_data);
+ return true;
+ }
+
+ if(new_timestamp < timestamp)
+ return false;
+
+ data = std::move(new_data);
+ timestamp = new_timestamp;
+ return true;
+ }
+
UserInfo::UserInfo(RoomData *room, std::string user_id) :
room(room), display_name_color(user_id_to_color(user_id)), user_id(user_id)
{
- display_name = user_id;
+ display_name.set_data_if_newer(user_id, 0);
}
- 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)) {
-
+ UserInfo::UserInfo(RoomData *room, std::string _user_id, std::string _display_name, std::string _avatar_url, time_t update_timestamp_ms) :
+ room(room), display_name_color(user_id_to_color(user_id)), user_id(std::move(_user_id)) {
+ display_name.set_data_if_newer(std::move(_display_name), update_timestamp_ms);
+ avatar_url.set_data_if_newer(std::move(_avatar_url), update_timestamp_ms);
}
// TODO: Remove this when images are embedded inside the text instead of using the same space as the author
@@ -161,24 +176,27 @@ namespace QuickMedia {
std::string RoomData::get_user_display_name(const std::shared_ptr<UserInfo> &user) {
std::lock_guard<std::mutex> lock(user_mutex);
- return user->display_name;
+ return user->display_name.data;
}
std::string RoomData::get_user_avatar_url(const std::shared_ptr<UserInfo> &user) {
std::lock_guard<std::mutex> lock(user_mutex);
- return user->avatar_url;
+ return user->avatar_url.data;
}
- void RoomData::set_user_display_name(std::shared_ptr<UserInfo> &user, std::string display_name) {
+ bool RoomData::set_user_display_name(std::shared_ptr<UserInfo> &user, std::string display_name, time_t update_timestamp_ms) {
std::lock_guard<std::mutex> lock(user_mutex);
- user->display_name = std::move(display_name);
- if(user->display_name.empty())
- user->display_name = user->user_id;
+ if(display_name.empty()) {
+ user->display_name.data = user->user_id;
+ return true;
+ } else {
+ return user->display_name.set_data_if_newer(std::move(display_name), update_timestamp_ms);
+ }
}
- void RoomData::set_user_avatar_url(std::shared_ptr<UserInfo> &user, std::string avatar_url) {
+ bool RoomData::set_user_avatar_url(std::shared_ptr<UserInfo> &user, std::string avatar_url, time_t update_timestamp_ms) {
std::lock_guard<std::mutex> lock(user_mutex);
- user->avatar_url = std::move(avatar_url);
+ return user->avatar_url.set_data_if_newer(std::move(avatar_url), update_timestamp_ms);
}
size_t RoomData::prepend_messages_reverse(const Messages &new_messages) {
@@ -283,42 +301,42 @@ namespace QuickMedia {
bool RoomData::has_name() {
std::lock_guard<std::recursive_mutex> lock(room_mutex);
- return !name.empty();
+ return !name.data.empty();
}
- void RoomData::set_name(const std::string &new_name) {
+ bool RoomData::set_name(const std::string &new_name, time_t update_timestamp_ms) {
std::lock_guard<std::recursive_mutex> lock(room_mutex);
- name = new_name;
+ return name.set_data_if_newer(new_name, update_timestamp_ms);
}
std::string RoomData::get_name() {
std::lock_guard<std::recursive_mutex> lock(room_mutex);
- return name;
+ return name.data;
}
- void RoomData::set_topic(const std::string &new_topic) {
+ bool RoomData::set_topic(const std::string &new_topic, time_t update_timestamp_ms) {
std::lock_guard<std::recursive_mutex> lock(room_mutex);
- topic = new_topic;
+ return topic.set_data_if_newer(new_topic, update_timestamp_ms);
}
std::string RoomData::get_topic() {
std::lock_guard<std::recursive_mutex> lock(room_mutex);
- return topic;
+ return topic.data;
}
bool RoomData::has_avatar_url() {
std::lock_guard<std::recursive_mutex> lock(room_mutex);
- return !avatar_url.empty();
+ return !avatar_url.data.empty();
}
- void RoomData::set_avatar_url(const std::string &new_avatar_url) {
+ bool RoomData::set_avatar_url(const std::string &new_avatar_url, time_t update_timestamp_ms) {
std::lock_guard<std::recursive_mutex> lock(room_mutex);
- avatar_url = new_avatar_url;
+ return avatar_url.set_data_if_newer(new_avatar_url, update_timestamp_ms);
}
std::string RoomData::get_avatar_url() {
std::lock_guard<std::recursive_mutex> lock(room_mutex);
- return avatar_url;
+ return avatar_url.data;
}
void RoomData::set_pinned_events(std::vector<std::string> new_pinned_events) {
@@ -1507,8 +1525,8 @@ namespace QuickMedia {
return PluginResult::ERR;
const rapidjson::Value &state_json = GetMember(json_root, "state");
- events_add_user_info(state_json, room);
- //events_set_room_info(state_json, room_data);
+ events_add_user_info(state_json, room, 0);
+ //events_set_room_info(state_json, room_data, 0);
const rapidjson::Value &chunk_json = GetMember(json_root, "chunk");
if(chunk_json.IsArray()) {
@@ -1742,8 +1760,8 @@ namespace QuickMedia {
const rapidjson::Value &state_json = GetMember(it.value, "state");
if(state_json.IsObject()) {
const rapidjson::Value &events_json = GetMember(state_json, "events");
- events_add_user_info(events_json, room);
- events_set_room_info(events_json, room);
+ events_add_user_info(events_json, room, 0);
+ events_set_room_info(events_json, room, 0);
events_add_pinned_events(events_json, room);
}
@@ -1770,8 +1788,8 @@ namespace QuickMedia {
}
const rapidjson::Value &events_json = GetMember(timeline_json, "events");
- events_add_user_info(events_json, room);
- events_set_room_info(events_json, room);
+ events_add_user_info(events_json, room, 0);
+ events_set_room_info(events_json, room, 0);
set_room_info_to_users_if_empty(room, my_user_id);
if(account_data_json.IsObject()) {
@@ -1841,7 +1859,7 @@ namespace QuickMedia {
return PluginResult::OK;
}
- void Matrix::events_add_user_info(const rapidjson::Value &events_json, RoomData *room_data) {
+ void Matrix::events_add_user_info(const rapidjson::Value &events_json, RoomData *room_data, int64_t timestamp) {
if(!events_json.IsArray())
return;
@@ -1865,7 +1883,14 @@ namespace QuickMedia {
if(!content_json.IsObject())
continue;
- parse_user_info(content_json, sender_json->GetString(), room_data);
+ int64_t item_timestamp = timestamp;
+ if(item_timestamp == 0) {
+ const rapidjson::Value &origin_server_ts = GetMember(event_item_json, "origin_server_ts");
+ if(origin_server_ts.IsInt64())
+ item_timestamp = origin_server_ts.GetInt64();
+ }
+
+ parse_user_info(content_json, sender_json->GetString(), room_data, item_timestamp);
}
}
@@ -1890,7 +1915,7 @@ namespace QuickMedia {
return homeserver + "/_matrix/media/r0/thumbnail/" + mxc_id + "?width=" + size + "&height=" + size + "&method=crop";
}
- std::shared_ptr<UserInfo> Matrix::parse_user_info(const rapidjson::Value &json, const std::string &user_id, RoomData *room_data) {
+ std::shared_ptr<UserInfo> Matrix::parse_user_info(const rapidjson::Value &json, const std::string &user_id, RoomData *room_data, int64_t timestamp) {
assert(json.IsObject());
std::string avatar_url_str;
const rapidjson::Value &avatar_url_json = GetMember(json, "avatar_url");
@@ -1908,18 +1933,26 @@ namespace QuickMedia {
//room_data->add_user(user_info);
bool is_new_user;
auto user_info = get_user_by_id(room_data, user_id, &is_new_user);
- room_data->set_user_display_name(user_info, display_name);
- room_data->set_user_avatar_url(user_info, avatar_url);
+ bool update_display_name = room_data->set_user_display_name(user_info, display_name, timestamp);
+ bool update_avatar_url = room_data->set_user_avatar_url(user_info, avatar_url, timestamp);
MatrixEventUserInfo event_user_info;
event_user_info.user_id = user_id;
- event_user_info.display_name = display_name;
- event_user_info.avatar_url = avatar_url;
+ event_user_info.display_name = std::move(display_name);
+ event_user_info.avatar_url = std::move(avatar_url);
- if(is_new_user) {
- trigger_event(room_data, MatrixEventType::ADD_USER, std::move(event_user_info));
- } else {
- trigger_event(room_data, MatrixEventType::USER_INFO, std::move(event_user_info));
+ if(!update_display_name)
+ event_user_info.display_name = std::nullopt;
+
+ if(!update_avatar_url)
+ event_user_info.display_name = std::nullopt;
+
+ if(update_display_name || update_avatar_url) {
+ if(is_new_user) {
+ trigger_event(room_data, MatrixEventType::ADD_USER, std::move(event_user_info));
+ } else {
+ trigger_event(room_data, MatrixEventType::USER_INFO, std::move(event_user_info));
+ }
}
return user_info;
@@ -2335,6 +2368,7 @@ namespace QuickMedia {
std::optional<std::string> new_display_name;
std::optional<std::string> new_avatar_url;
+ bool update_user_display_info = false;
if(prev_membership_json.IsString() && strcmp(prev_membership_json.GetString(), "leave") == 0) {
body = user_display_name + " joined the room";
@@ -2347,27 +2381,27 @@ namespace QuickMedia {
prev_displayname_str = sender_json_str;
body = extract_first_line_remove_newline_elipses(prev_displayname_str, AUTHOR_MAX_LENGTH) + " changed his display name to " + extract_first_line_remove_newline_elipses(new_displayname_str, AUTHOR_MAX_LENGTH);
new_display_name = new_displayname_str;
- room_data->set_user_display_name(user, std::move(new_displayname_str));
+ update_user_display_info = room_data->set_user_display_name(user, std::move(new_displayname_str), timestamp);
} else if((!new_displayname_json.IsString() || new_displayname_json.GetStringLength() == 0) && prev_displayname_json.IsString()) {
body = user_display_name + " removed his display name";
new_display_name = "";
- room_data->set_user_display_name(user, "");
+ update_user_display_info = room_data->set_user_display_name(user, "", timestamp);
} else if(new_avatar_url_json.IsString() && new_avatar_url_json.GetStringLength() > 0 && (!prev_avatar_url_json.IsString() || strcmp(new_avatar_url_json.GetString(), prev_avatar_url_json.GetString()) != 0)) {
body = user_display_name + " changed his 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 = get_thumbnail_url(homeserver, new_avatar_url_str); // TODO: Remove the constant strings around to reduce memory usage (6.3mb)
new_avatar_url = new_avatar_url_str;
- room_data->set_user_avatar_url(user, std::move(new_avatar_url_str));
+ update_user_display_info = room_data->set_user_avatar_url(user, std::move(new_avatar_url_str), timestamp);
} else if((!new_avatar_url_json.IsString() || new_avatar_url_json.GetStringLength() == 0) && prev_avatar_url_json.IsString()) {
body = user_display_name + " removed his profile picture";
new_avatar_url = "";
- room_data->set_user_avatar_url(user, "");
+ update_user_display_info = room_data->set_user_avatar_url(user, "", timestamp);
} else {
body = user_display_name + " joined the room";
}
- if(new_display_name || new_avatar_url) {
+ if(update_user_display_info) {
MatrixEventUserInfo user_info;
user_info.user_id = user->user_id;
user_info.display_name = std::move(new_display_name);
@@ -2599,7 +2633,7 @@ namespace QuickMedia {
return result;
}
- void Matrix::events_set_room_info(const rapidjson::Value &events_json, RoomData *room_data) {
+ void Matrix::events_set_room_info(const rapidjson::Value &events_json, RoomData *room_data, int64_t timestamp) {
if(!events_json.IsArray())
return;
@@ -2611,6 +2645,13 @@ namespace QuickMedia {
if(!type_json.IsString())
continue;
+ int64_t item_timestamp = timestamp;
+ if(item_timestamp == 0) {
+ const rapidjson::Value &origin_server_ts = GetMember(event_item_json, "origin_server_ts");
+ if(origin_server_ts.IsInt64())
+ item_timestamp = origin_server_ts.GetInt64();
+ }
+
if(strcmp(type_json.GetString(), "m.room.name") == 0) {
const rapidjson::Value &content_json = GetMember(event_item_json, "content");
if(!content_json.IsObject())
@@ -2620,7 +2661,7 @@ namespace QuickMedia {
if(!name_json.IsString())
continue;
- room_data->set_name(name_json.GetString());
+ room_data->set_name(name_json.GetString(), item_timestamp); // TODO: Update room name in gui
room_data->name_is_fallback = false;
} else if(strcmp(type_json.GetString(), "m.room.avatar") == 0) {
const rapidjson::Value &content_json = GetMember(event_item_json, "content");
@@ -2631,7 +2672,7 @@ namespace QuickMedia {
if(!url_json.IsString() || strncmp(url_json.GetString(), "mxc://", 6) != 0)
continue;
- room_data->set_avatar_url(get_thumbnail_url(homeserver, thumbnail_url_extract_media_id(url_json.GetString())));
+ room_data->set_avatar_url(get_thumbnail_url(homeserver, thumbnail_url_extract_media_id(url_json.GetString())), item_timestamp); // TODO: Update avatar url in gui
room_data->avatar_is_fallback = false;
} else if(strcmp(type_json.GetString(), "m.room.topic") == 0) {
const rapidjson::Value &content_json = GetMember(event_item_json, "content");
@@ -2642,7 +2683,7 @@ namespace QuickMedia {
if(!topic_json.IsString())
continue;
- room_data->set_topic(topic_json.GetString());
+ room_data->set_topic(topic_json.GetString(), item_timestamp); // TODO: Update topic in gui
}
}
}
@@ -2656,7 +2697,7 @@ namespace QuickMedia {
users_excluding_me = room->get_users_excluding_me(my_user_id);
if(!has_room_name) {
- room->set_name(combine_user_display_names_for_room_name(users_excluding_me, room_creator_user_id));
+ room->set_name(combine_user_display_names_for_room_name(users_excluding_me, room_creator_user_id), 0); // TODO: Update in gui
room->name_is_fallback = true;
}
@@ -2664,10 +2705,10 @@ namespace QuickMedia {
if(users_excluding_me.empty()) {
auto user = get_user_by_id(room, room_creator_user_id);
if(user)
- room->set_avatar_url(room->get_user_avatar_url(user));
+ room->set_avatar_url(room->get_user_avatar_url(user), 0); // TODO: Update in gui
} else {
// TODO: If there are multiple users, then we want to use some other type of avatar, not the first users avatar
- room->set_avatar_url(room->get_user_avatar_url(users_excluding_me.front()));
+ room->set_avatar_url(room->get_user_avatar_url(users_excluding_me.front()), 0); // TODO: Update in gui
}
room->avatar_is_fallback = true;
}
@@ -2818,6 +2859,8 @@ namespace QuickMedia {
const rapidjson::Value &membership_json = GetMember(content_json, "membership");
if(membership_json.IsString() && strcmp(membership_json.GetString(), "invite") == 0) {
+ const int64_t timestamp = timestamp_json.GetInt64();
+
// TODO: Check this this room should be saved in the rooms list, which might be needed if the server doesn't give a non-invite events
// for the same data (user display name update, etc)
Invite invite;
@@ -2825,8 +2868,8 @@ namespace QuickMedia {
RoomData *room = invite_room.get();
invite_rooms.push_back(std::move(invite_room));
- events_add_user_info(events_json, room);
- events_set_room_info(events_json, room);
+ events_add_user_info(events_json, room, timestamp);
+ events_set_room_info(events_json, room, timestamp);
std::string sender_json_str(sender_json.GetString(), sender_json.GetStringLength());
auto invited_by = get_user_by_id(room, sender_json_str);
@@ -2836,7 +2879,7 @@ namespace QuickMedia {
invite.room_name = room->get_name();
invite.room_avatar_url = room->get_avatar_url();
invite.invited_by = invited_by;
- invite.timestamp = timestamp_json.GetInt64();
+ invite.timestamp = timestamp;
invite.new_invite = !sync_is_cache;
std::string room_id_str(room_id.GetString(), room_id.GetStringLength());
@@ -2934,7 +2977,7 @@ namespace QuickMedia {
PluginResult Matrix::get_previous_room_messages(RoomData *room_data, bool latest_messages, size_t &num_new_messages, bool *reached_end) {
num_new_messages = 0;
std::string from = room_data->get_prev_batch();
- if(from.empty() || latest_messages)
+ if(from.empty() || latest_messages) // TODO: Remove. In v1.3 (/v3/) from can be empty
from = "END";
rapidjson::Document request_data(rapidjson::kObjectType);
@@ -2962,8 +3005,8 @@ namespace QuickMedia {
const rapidjson::Value &state_json = GetMember(json_root, "state");
// TODO: Remove?
- events_add_user_info(state_json, room_data);
- //events_set_room_info(state_json, room_data);
+ events_add_user_info(state_json, room_data, 0);
+ //events_set_room_info(state_json, room_data, 0);
const rapidjson::Value &chunk_json = GetMember(json_root, "chunk");
num_new_messages = events_add_messages(chunk_json, room_data, MessageDirection::BEFORE, false);
@@ -3574,9 +3617,9 @@ namespace QuickMedia {
return nullptr;
}
- // TODO: Do this? what about state apply order?
+ // TODO: Do this?
//const rapidjson::Value &state_json = GetMember(json_root, "state");
- //events_add_user_info(state_json, room);
+ //events_add_user_info(state_json, room, 0);
std::shared_ptr<Message> new_message = parse_message_event(json_root, room);
room->fetched_messages_by_event_id.insert(std::make_pair(event_id, new_message));
@@ -3622,9 +3665,9 @@ namespace QuickMedia {
}
}
- // TODO: Do this? what about state apply order?
+ // TODO: Do this?
//const rapidjson::Value &state_json = GetMember(json_root, "state");
- //events_add_user_info(state_json, room);
+ //events_add_user_info(state_json, room, 0);
const rapidjson::Value &start_json = GetMember(json_root, "start");
const rapidjson::Value &end_json = GetMember(json_root, "end");
@@ -4261,8 +4304,8 @@ namespace QuickMedia {
if(!room) {
auto new_room = std::make_unique<RoomData>();
new_room->id = room_id;
- new_room->set_name(invite_it->second.room_name);
- new_room->set_avatar_url(invite_it->second.room_avatar_url);
+ new_room->set_name(invite_it->second.room_name, invite_it->second.timestamp);
+ new_room->set_avatar_url(invite_it->second.room_avatar_url, invite_it->second.timestamp);
room = new_room.get();
add_room(std::move(new_room));
@@ -4706,8 +4749,8 @@ namespace QuickMedia {
avatar_url = std::string(avatar_url_json.GetString(), avatar_url_json.GetStringLength());
if(!avatar_url.empty())
avatar_url = get_thumbnail_url(homeserver, thumbnail_url_extract_media_id(avatar_url)); // TODO: Remove the constant strings around to reduce memory usage (6.3mb)
- room->set_user_avatar_url(user, avatar_url);
- room->set_user_display_name(user, display_name);
+ room->set_user_avatar_url(user, avatar_url, 0);
+ room->set_user_display_name(user, display_name, 0);
MatrixEventUserInfo user_info;
user_info.user_id = user_id;
@@ -4740,7 +4783,7 @@ namespace QuickMedia {
if(!chunk_json.IsArray())
return;
- events_add_user_info(chunk_json, room);
+ events_add_user_info(chunk_json, room, 0);
#endif
}