From 59c4a651ab9d795c0d1788a8ddf29949a56b1ab9 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Tue, 15 Nov 2022 19:36:10 +0100 Subject: Matrix: use a local cache of latest read marker timestamps to try and avoid many unread message notices --- src/plugins/Matrix.cpp | 81 +++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 67 insertions(+), 14 deletions(-) (limited to 'src/plugins/Matrix.cpp') diff --git a/src/plugins/Matrix.cpp b/src/plugins/Matrix.cpp index ba4111d..d3c6f81 100644 --- a/src/plugins/Matrix.cpp +++ b/src/plugins/Matrix.cpp @@ -730,7 +730,7 @@ namespace QuickMedia { if(!room->body_item) return; - if(!sync_is_cache && (last_unread_message || room->unread_notification_count > 0)) { + if(!sync_is_cache && last_unread_message) { bool is_window_focused = program->is_window_focused(); RoomData *current_room = program->get_current_chat_room(); Body *chat_body = chat_page ? chat_page->chat_body : nullptr; @@ -748,20 +748,13 @@ namespace QuickMedia { room->body_item->set_description_color(get_theme().faded_text_color); } - if(last_unread_message) { - if(!room_desc.empty()) - room_desc += '\n'; - } + if(!room_desc.empty()) + room_desc += '\n'; if(!unread_mentions && set_room_as_unread) room_desc += "Unread: "; - if(last_unread_message) { - room->latest_message = extract_first_line_remove_newline_elipses(matrix->message_get_author_displayname(last_unread_message), AUTHOR_MAX_LENGTH) + ": " + message_to_room_description_text(matrix, last_unread_message, custom_emoji_max_size); - } else { - room->latest_message.clear(); - } - + room->latest_message = extract_first_line_remove_newline_elipses(matrix->message_get_author_displayname(last_unread_message), AUTHOR_MAX_LENGTH) + ": " + message_to_room_description_text(matrix, last_unread_message, custom_emoji_max_size); room_desc += room->latest_message; room->body_item->set_description(std::move(room_desc)); @@ -1557,6 +1550,7 @@ namespace QuickMedia { load_silenced_invites(); load_custom_emoji_from_cache(); + load_qm_read_markers_from_cache(); sync_thread = std::thread([this, matrix_cache_dir]() { sync_is_cache = true; @@ -1764,6 +1758,8 @@ namespace QuickMedia { filter_cached.reset(); finished_fetching_notifications = false; custom_emoji_by_key.clear(); + silenced_invites.clear(); + qm_read_markers_by_room_cache.clear(); } bool Matrix::is_initial_sync_finished() { @@ -4815,6 +4811,9 @@ namespace QuickMedia { Path custom_emoji_path = get_cache_dir().join("matrix").join("custom_emoji.json"); remove(custom_emoji_path.data.c_str()); + + Path read_markers_path = get_cache_dir().join("matrix").join("read_markers.json"); + remove(read_markers_path.data.c_str()); //Path filter_cache_path = get_storage_dir().join("matrix").join("filter"); //remove(filter_cache_path.data.c_str()); for_files_in_dir(get_cache_dir().join("matrix").join("events"), [](const Path &filepath, FileType) { @@ -5203,11 +5202,62 @@ namespace QuickMedia { { "--data-binary", buffer.GetString() } }; - room->read_marker_event_timestamp = timestamp; - std::string server_response; DownloadResult download_result = download_to_string(homeserver + "/_matrix/client/r0/user/" + my_user_id + "/rooms/" + room->id + "/account_data/qm.last_read_message_timestamp", server_response, std::move(additional_args), true); - return download_result_to_plugin_result(download_result); + if(download_result != DownloadResult::OK) + return download_result_to_plugin_result(download_result); + + room->read_marker_event_timestamp = timestamp; + update_room_qm_read_markers_in_cache(room->id, timestamp); + return PluginResult::OK; + } + + // TODO: Separate file for each room? + void Matrix::load_qm_read_markers_from_cache() { + std::string file_content; + if(file_get_content(get_cache_dir().join("matrix").join("read_markers.json"), file_content) != 0) + return; + + rapidjson::Document json_root; + rapidjson::ParseResult parse_result = json_root.Parse(file_content.c_str(), file_content.size()); + if(parse_result.IsError()) { + fprintf(stderr, "Warning: failed to parse read_markers.json, error: %d\n", parse_result.Code()); + return; + } + + if(!json_root.IsObject()) { + fprintf(stderr, "Warning: failed to parse read_markers.json\n"); + return; + } + + qm_read_markers_by_room_cache.clear(); + std::lock_guard lock(room_data_mutex); + for(auto const &obj : json_root.GetObject()) { + if(!obj.name.IsString() || !obj.value.IsInt64()) + continue; + + std::string room_id = std::string(obj.name.GetString(), obj.name.GetStringLength()); + auto room_it = room_data_by_id.find(room_id); + if(room_it != room_data_by_id.end()) + rooms[room_it->second]->read_marker_event_timestamp = obj.value.GetInt64(); + qm_read_markers_by_room_cache[std::move(room_id)] = obj.value.GetInt64(); + } + } + + void Matrix::update_room_qm_read_markers_in_cache(const std::string &room_id, int64_t timestamp) { + load_qm_read_markers_from_cache(); // TODO: Remove this? + qm_read_markers_by_room_cache[room_id] = timestamp; + + rapidjson::Document request_data(rapidjson::kObjectType); + for(const auto &[key, val] : qm_read_markers_by_room_cache) { + request_data.AddMember(rapidjson::Value(key.c_str(), request_data.GetAllocator()).Move(), val, request_data.GetAllocator()); + } + + rapidjson::StringBuffer buffer; + rapidjson::Writer writer(buffer); + request_data.Accept(writer); + + file_overwrite_atomic(get_cache_dir().join("matrix").join("read_markers.json"), std::string(buffer.GetString(), buffer.GetSize())); } PluginResult Matrix::join_room(const std::string &room_id_or_name) { @@ -5587,6 +5637,9 @@ namespace QuickMedia { std::lock_guard lock(room_data_mutex); room->index = rooms.size(); room_data_by_id.insert(std::make_pair(room->id, room->index)); + auto read_marker_it = qm_read_markers_by_room_cache.find(room->id); + if(read_marker_it != qm_read_markers_by_room_cache.end()) + room->read_marker_event_timestamp = read_marker_it->second; rooms.push_back(std::move(room)); } -- cgit v1.2.3