aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/QuickMedia.cpp51
-rw-r--r--src/plugins/Matrix.cpp93
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); });