diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/QuickMedia.cpp | 51 | ||||
-rw-r--r-- | src/plugins/Matrix.cpp | 93 |
2 files changed, 126 insertions, 18 deletions
diff --git a/src/QuickMedia.cpp b/src/QuickMedia.cpp index a21cf11..a45da87 100644 --- a/src/QuickMedia.cpp +++ b/src/QuickMedia.cpp @@ -5876,17 +5876,15 @@ namespace QuickMedia { } } - if(current_room) { - if(event.key.control && event.key.code == sf::Keyboard::C) { - BodyItem *selected = tabs[selected_tab].body->get_selected(); - if(selected) { - auto desc = selected->get_description(); - sf::Clipboard::setString(sf::String::fromUtf8(desc.begin(), desc.end())); - } + if(event.key.control && event.key.code == sf::Keyboard::C) { + BodyItem *selected = tabs[selected_tab].body->get_selected(); + if(selected) { + auto desc = selected->get_description(); + sf::Clipboard::setString(sf::String::fromUtf8(desc.begin(), desc.end())); } } - if(selected_tab == MESSAGES_TAB_INDEX && current_room) { + if(selected_tab == MESSAGES_TAB_INDEX) { if(event.key.code == sf::Keyboard::U) { frame_skip_text_entry = true; new_page = PageType::FILE_MANAGER; @@ -5983,6 +5981,43 @@ namespace QuickMedia { show_notification("QuickMedia", "No message selected for deletion"); } } + + if(event.key.control && event.key.code == sf::Keyboard::P && !chat_input.is_editable()) { + frame_skip_text_entry = true; + BodyItem *selected = tabs[selected_tab].body->get_selected(); + if(selected) { + Message *selected_message = static_cast<Message*>(selected->userdata); + if(!is_state_message_type(selected_message)) { + if(selected_message->event_id.empty()) { + // TODO: Show inline notification + show_notification("QuickMedia", "You can't pin a message that hasn't been sent yet"); + } else { + run_task_with_loading_screen([this, current_room, selected_message] { + return matrix->pin_message(current_room, selected_message->event_id) == PluginResult::OK; + }); + } + } + } else { + // TODO: Show inline notification + show_notification("QuickMedia", "No message selected for pinning"); + } + } + } else if(selected_tab == PINNED_TAB_INDEX) { + if(event.key.control && event.key.code == sf::Keyboard::D && !chat_input.is_editable()) { + frame_skip_text_entry = true; + BodyItem *selected = tabs[selected_tab].body->get_selected(); + if(selected) { + PinnedEventData *selected_pinned_event_data = static_cast<PinnedEventData*>(selected->userdata); + if(selected_pinned_event_data) { + run_task_with_loading_screen([this, current_room, selected_pinned_event_data] { + return matrix->unpin_message(current_room, selected_pinned_event_data->event_id) == PluginResult::OK; + }); + } + } else { + // TODO: Show inline notification + show_notification("QuickMedia", "No message selected for unpinning"); + } + } } } else if(event.type == sf::Event::KeyPressed && chat_state == ChatState::URL_SELECTION) { if(event.key.code == sf::Keyboard::Escape) { 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<std::string>& RoomData::get_pinned_events_unsafe() const { + const std::vector<std::string>& RoomData::get_pinned_events_thread_unsafe() const { return pinned_events; } @@ -322,7 +323,7 @@ namespace QuickMedia { pinned_events_updated = true; } - std::set<std::string>& RoomData::get_tags_unsafe() { + std::set<std::string>& 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<std::string> &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<std::string> &room_tags = room->get_tags_unsafe(); + std::set<std::string> &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<std::string> &room_tags = room_data->get_tags_unsafe(); + std::set<std::string> &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<std::string> &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<rapidjson::StringBuffer> writer(buffer); + request_data.Accept(writer); + + std::vector<CommandArg> 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<std::string> &room_tags = room->get_tags_unsafe(); + std::set<std::string> &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); }); |