From 8af5901fb893c3fc25b31bf484a90b47d1c24c2c Mon Sep 17 00:00:00 2001 From: dec05eba Date: Tue, 10 Aug 2021 13:01:50 +0200 Subject: Matrix: add ctrl+p/ctrl+d to pin/unpin messages --- src/plugins/Matrix.cpp | 93 ++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 83 insertions(+), 10 deletions(-) (limited to 'src/plugins/Matrix.cpp') diff --git a/src/plugins/Matrix.cpp b/src/plugins/Matrix.cpp index b471522..d59e6d5 100644 --- a/src/plugins/Matrix.cpp +++ b/src/plugins/Matrix.cpp @@ -29,8 +29,9 @@ namespace QuickMedia { static const sf::Vector2i thumbnail_max_size(600, 337); static const char* SERVICE_NAME = "matrix"; static const char* OTHERS_ROOM_TAG = "tld.name.others"; - // Filter without account data - static const char* INITIAL_FILTER = "{\"presence\":{\"limit\":0,\"types\":[\"\"]},\"account_data\":{\"limit\":0,\"types\":[\"\"]},\"room\":{\"state\":{\"not_types\":[\"m.room.related_groups\",\"m.room.power_levels\",\"m.room.join_rules\",\"m.room.history_visibility\"],\"lazy_load_members\":true},\"timeline\":{\"types\":[\"m.room.message\"],\"limit\":1,\"lazy_load_members\":true},\"ephemeral\":{\"limit\":0,\"types\":[\"\"],\"lazy_load_members\":true},\"account_data\":{\"limit\":1,\"types\":[\"m.fully_read\",\"m.tag\",\"qm.last_read_message_timestamp\"],\"lazy_load_members\":true}}}"; + // Filter without account data. TODO: We include pinned events but limit events to 1. That means if the last event is a pin, + // then we cant see room message preview. TODO: Fix this somehow. + static const char* INITIAL_FILTER = "{\"presence\":{\"limit\":0,\"types\":[\"\"]},\"account_data\":{\"limit\":0,\"types\":[\"\"]},\"room\":{\"state\":{\"not_types\":[\"m.room.related_groups\",\"m.room.power_levels\",\"m.room.join_rules\",\"m.room.history_visibility\"],\"lazy_load_members\":true},\"timeline\":{\"types\":[\"m.room.message\",\"m.room.pinned_events\"],\"limit\":1,\"lazy_load_members\":true},\"ephemeral\":{\"limit\":0,\"types\":[\"\"],\"lazy_load_members\":true},\"account_data\":{\"limit\":1,\"types\":[\"m.fully_read\",\"m.tag\",\"qm.last_read_message_timestamp\"],\"lazy_load_members\":true}}}"; static const char* ADDITIONAL_MESSAGES_FILTER = "{\"presence\":{\"limit\":0,\"types\":[\"\"]},\"account_data\":{\"limit\":0,\"types\":[\"\"]},\"room\":{\"state\":{\"not_types\":[\"m.room.related_groups\",\"m.room.power_levels\",\"m.room.join_rules\",\"m.room.history_visibility\"],\"lazy_load_members\":true},\"timeline\":{\"limit\":20,\"lazy_load_members\":true},\"ephemeral\":{\"limit\":0,\"types\":[\"\"],\"lazy_load_members\":true},\"account_data\":{\"limit\":0,\"types\":[\"\"],\"lazy_load_members\":true}}}"; static const char* CONTINUE_FILTER = "{\"presence\":{\"limit\":0,\"types\":[\"\"]},\"account_data\":{\"limit\":0,\"types\":[\"\"]},\"room\":{\"state\":{\"not_types\":[\"m.room.related_groups\",\"m.room.power_levels\",\"m.room.join_rules\",\"m.room.history_visibility\"],\"lazy_load_members\":true},\"timeline\":{\"lazy_load_members\":true},\"ephemeral\":{\"limit\":0,\"types\":[\"\"],\"lazy_load_members\":true},\"account_data\":{\"types\":[\"m.fully_read\",\"m.tag\",\"qm.last_read_message_timestamp\"],\"lazy_load_members\":true}}}"; @@ -255,7 +256,7 @@ namespace QuickMedia { return messages; } - const std::vector& RoomData::get_pinned_events_unsafe() const { + const std::vector& RoomData::get_pinned_events_thread_unsafe() const { return pinned_events; } @@ -322,7 +323,7 @@ namespace QuickMedia { pinned_events_updated = true; } - std::set& RoomData::get_tags_unsafe() { + std::set& RoomData::get_tags_thread_unsafe() { return tags; } @@ -635,7 +636,7 @@ namespace QuickMedia { rooms_page->move_room_to_top(room); room_tags_page->move_room_to_top(room); - } else if(is_initial_sync) { + } else { room->body_item->set_description(extract_first_line_remove_newline_elipses(matrix->message_get_author_displayname(last_new_message.get()), AUTHOR_MAX_LENGTH) + ": " + message_to_room_description_text(last_new_message.get())); room->body_item->set_description_color(get_current_theme().faded_text_color); } @@ -1410,7 +1411,7 @@ namespace QuickMedia { room->messages_read_index = room_messages.size(); } if(room->pinned_events_updated) { - sync_data.pinned_events = room->get_pinned_events_unsafe(); + sync_data.pinned_events = room->get_pinned_events_thread_unsafe(); room->pinned_events_updated = false; } room->release_room_lock(); @@ -1425,7 +1426,7 @@ namespace QuickMedia { void Matrix::get_all_pinned_events(RoomData *room, std::vector &events) { room->acquire_room_lock(); - events = room->get_pinned_events_unsafe(); + events = room->get_pinned_events_thread_unsafe(); room->pinned_events_updated = false; room->release_room_lock(); } @@ -1709,7 +1710,7 @@ namespace QuickMedia { if(is_new_room) { room->acquire_room_lock(); - std::set &room_tags = room->get_tags_unsafe(); + std::set &room_tags = room->get_tags_thread_unsafe(); if(room_tags.empty()) { room_tags.insert(OTHERS_ROOM_TAG); ui_thread_tasks.push([this, room]{ delegate->room_add_tag(room, OTHERS_ROOM_TAG); }); @@ -2641,7 +2642,7 @@ namespace QuickMedia { // When we receive a list of tags its always the full list of tags if(has_tags) { room_data->acquire_room_lock(); - std::set &room_tags = room_data->get_tags_unsafe(); + std::set &room_tags = room_data->get_tags_thread_unsafe(); for(const std::string &room_tag : room_tags) { auto it = new_tags.find(room_tag); @@ -3784,6 +3785,78 @@ namespace QuickMedia { return PluginResult::OK; } + PluginResult Matrix::pin_message(RoomData *room, const std::string &event_id) { + if(!is_initial_sync_finished()) { + show_notification("QuickMedia", "Can't pin messages while sync is in progress", Urgency::CRITICAL); + return PluginResult::ERR; + } + + room->acquire_room_lock(); + auto pinned_events = room->get_pinned_events_thread_unsafe(); + room->release_room_lock(); + + pinned_events.push_back(event_id); + return set_pinned_events(room, pinned_events, true); + } + + PluginResult Matrix::unpin_message(RoomData *room, const std::string &event_id) { + if(!is_initial_sync_finished()) { + show_notification("QuickMedia", "Can't unpin messages while sync is in progress", Urgency::CRITICAL); + return PluginResult::ERR; + } + + room->acquire_room_lock(); + auto pinned_events = room->get_pinned_events_thread_unsafe(); + room->release_room_lock(); + + auto find_it = std::find(pinned_events.begin(), pinned_events.end(), event_id); + if(find_it != pinned_events.end()) + pinned_events.erase(find_it); + + return set_pinned_events(room, pinned_events, false); + } + + PluginResult Matrix::set_pinned_events(RoomData *room, const std::vector &pinned_events, bool is_add) { + rapidjson::Document request_data(rapidjson::kObjectType); + rapidjson::Value pinned_events_json(rapidjson::kArrayType); + for(auto &pinned_event : pinned_events) { + pinned_events_json.PushBack(rapidjson::StringRef(pinned_event.c_str()), request_data.GetAllocator()); + } + request_data.AddMember("pinned", std::move(pinned_events_json), request_data.GetAllocator()); + + rapidjson::StringBuffer buffer; + rapidjson::Writer writer(buffer); + request_data.Accept(writer); + + std::vector additional_args = { + { "-X", "PUT" }, + { "-H", "content-type: application/json" }, + { "-H", "Authorization: Bearer " + access_token }, + { "--data-binary", buffer.GetString() } + }; + + char url[512]; + snprintf(url, sizeof(url), "%s/_matrix/client/r0/rooms/%s/state/m.room.pinned_events/", homeserver.c_str(), room->id.c_str()); + + rapidjson::Document json_root; + std::string err_msg; + DownloadResult download_result = download_json(json_root, url, std::move(additional_args), true, &err_msg); + if(download_result != DownloadResult::OK) return download_result_to_plugin_result(download_result); + + if(!json_root.IsObject()) { + show_notification("QuickMedia", "Failed to parse server response", Urgency::CRITICAL); + return PluginResult::ERR; + } + + const rapidjson::Value &error_json = GetMember(json_root, "error"); + if(error_json.IsString()) { + show_notification("QuickMedia", std::string("Failed to ") + (is_add ? "pin" : "unpin") + " message, error: " + std::string(error_json.GetString(), error_json.GetStringLength()), Urgency::CRITICAL); + return PluginResult::ERR; + } + + return PluginResult::OK; + } + PluginResult Matrix::load_cached_session() { Path session_path = get_storage_dir().join(SERVICE_NAME).join("session.json"); std::string session_json_content; @@ -3964,7 +4037,7 @@ namespace QuickMedia { ui_thread_tasks.push([this, room]{ delegate->join_room(room); }); room->acquire_room_lock(); - std::set &room_tags = room->get_tags_unsafe(); + std::set &room_tags = room->get_tags_thread_unsafe(); if(room_tags.empty()) { room_tags.insert(OTHERS_ROOM_TAG); ui_thread_tasks.push([this, room]{ delegate->room_add_tag(room, OTHERS_ROOM_TAG); }); -- cgit v1.2.3