aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2022-11-15 19:36:10 +0100
committerdec05eba <dec05eba@protonmail.com>2022-11-15 19:36:10 +0100
commit59c4a651ab9d795c0d1788a8ddf29949a56b1ab9 (patch)
tree63e025ebb51a7f9f844a1fa88ee1348cee0a43a9
parent7b25a28366be259dc9a165ba13e0be0512e19d78 (diff)
Matrix: use a local cache of latest read marker timestamps to try and avoid many unread message notices
-rw-r--r--TODO4
-rw-r--r--plugins/Matrix.hpp3
-rw-r--r--src/plugins/Matrix.cpp81
3 files changed, 73 insertions, 15 deletions
diff --git a/TODO b/TODO
index d708f6d..beea673 100644
--- a/TODO
+++ b/TODO
@@ -242,4 +242,6 @@ Text editing should take into consideration FORMATTED_TEXT_START/FORMATTED_TEXT_
Matrix autocomplete for emoji (and custom emoji) and option show different sizes (for custom emoji).
Nicer custom emoji upload options - Selecting name, size, cropping.
Add option to copy somebody else custom emoji in matrix by pressing enter to bring up message option and in that a list of every emoji in the message should be added with "Add (emoji)..." text to add the emoji.
-Detect invidious urls too, even the ones that dont have watch?v=.. this could be done by downloading the webpage (maybe only HEAD?) to check if it's invidious. \ No newline at end of file
+Detect invidious urls too, even the ones that dont have watch?v=.. this could be done by downloading the webpage (maybe only HEAD?) to check if it's invidious.
+Atomic file operations should use a random generated name instead of .tmp, because multiple instances of quickmedia may be running and they may try to write to the same file at the same time. In such cases they can also write to the same temporary file at the same time.
+TODO: https://github.com/matrix-org/synapse/issues/14444. \ No newline at end of file
diff --git a/plugins/Matrix.hpp b/plugins/Matrix.hpp
index 77ef252..671f718 100644
--- a/plugins/Matrix.hpp
+++ b/plugins/Matrix.hpp
@@ -722,6 +722,8 @@ namespace QuickMedia {
PluginResult set_pinned_events(RoomData *room, const std::vector<std::string> &pinned_events, bool is_add);
PluginResult set_qm_last_read_message_timestamp(RoomData *room, int64_t timestamp);
+ void load_qm_read_markers_from_cache();
+ void update_room_qm_read_markers_in_cache(const std::string &room_id, int64_t timestamp);
PluginResult parse_sync_response(const rapidjson::Document &root, bool is_additional_messages_sync, bool initial_sync);
PluginResult parse_notifications(const rapidjson::Value &notifications_json, std::function<void(const MatrixNotification&)> callback_func);
@@ -797,5 +799,6 @@ namespace QuickMedia {
std::unordered_map<std::string, CustomEmoji> custom_emoji_by_key;
std::unordered_set<std::string> silenced_invites;
+ std::unordered_map<std::string, int64_t> qm_read_markers_by_room_cache;
};
} \ No newline at end of file
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<std::recursive_mutex> 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<rapidjson::StringBuffer> 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<std::recursive_mutex> 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));
}