aboutsummaryrefslogtreecommitdiff
path: root/src/plugins
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2021-08-19 16:40:42 +0200
committerdec05eba <dec05eba@protonmail.com>2021-08-19 17:13:17 +0200
commit4ff87535e7aae35bfbd66fe88402dcb513af249c (patch)
tree6427d23446d8f2aec80abc15d912010c26ae38fa /src/plugins
parentf4a02cabfd7452ed13b9c7b2e8b20ea5886768c8 (diff)
Matrix: add ctrl+r to navigate to replied to message and navigate to message from notifications tab
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/Matrix.cpp194
1 files changed, 155 insertions, 39 deletions
diff --git a/src/plugins/Matrix.cpp b/src/plugins/Matrix.cpp
index 8c7c884..df4fa52 100644
--- a/src/plugins/Matrix.cpp
+++ b/src/plugins/Matrix.cpp
@@ -182,7 +182,7 @@ namespace QuickMedia {
user->avatar_url = std::move(avatar_url);
}
- size_t RoomData::prepend_messages_reverse(const std::vector<std::shared_ptr<Message>> &new_messages) {
+ size_t RoomData::prepend_messages_reverse(const Messages &new_messages) {
std::lock_guard<std::recursive_mutex> lock(room_mutex);
int64_t last_new_message_timestamp = last_message_timestamp;
size_t num_new_messages = 0;
@@ -199,7 +199,7 @@ namespace QuickMedia {
return num_new_messages;
}
- size_t RoomData::append_messages(const std::vector<std::shared_ptr<Message>> &new_messages) {
+ size_t RoomData::append_messages(const Messages &new_messages) {
std::lock_guard<std::recursive_mutex> lock(room_mutex);
int64_t last_new_message_timestamp = last_message_timestamp;
size_t num_new_messages = 0;
@@ -253,7 +253,7 @@ namespace QuickMedia {
room_mutex.unlock();
}
- const std::vector<std::shared_ptr<Message>>& RoomData::get_messages_thread_unsafe() const {
+ const Messages& RoomData::get_messages_thread_unsafe() const {
return messages;
}
@@ -268,9 +268,7 @@ namespace QuickMedia {
void RoomData::set_prev_batch(const std::string &new_prev_batch) {
std::lock_guard<std::recursive_mutex> lock(room_mutex);
- // TODO: Check if this always works and if it also works for other homeservers than synapse
- if(prev_batch.empty() || new_prev_batch < prev_batch)
- prev_batch = new_prev_batch;
+ prev_batch = new_prev_batch;
}
std::string RoomData::get_prev_batch() {
@@ -884,7 +882,9 @@ namespace QuickMedia {
title = "Invites (0)";
}
- MatrixChatPage::MatrixChatPage(Program *program, std::string room_id, MatrixRoomsPage *rooms_page) : Page(program), room_id(std::move(room_id)), rooms_page(rooms_page) {
+ MatrixChatPage::MatrixChatPage(Program *program, std::string room_id, MatrixRoomsPage *rooms_page, std::string jump_to_event_id) :
+ Page(program), room_id(std::move(room_id)), rooms_page(rooms_page), jump_to_event_id(std::move(jump_to_event_id))
+ {
assert(rooms_page);
rooms_page->set_current_chat_page(this);
rooms_page->matrix_delegate->chat_page = this;
@@ -1059,7 +1059,7 @@ namespace QuickMedia {
return PluginResult::OK;
NotificationsExtraData *extra_data = static_cast<NotificationsExtraData*>(selected_item->extra.get());
- result_tabs.push_back(Tab{nullptr, std::make_unique<MatrixChatPage>(program, extra_data->room->id, all_rooms_page), nullptr});
+ result_tabs.push_back(Tab{nullptr, std::make_unique<MatrixChatPage>(program, extra_data->room->id, all_rooms_page, selected_item->url), nullptr});
return PluginResult::OK;
}
@@ -1450,9 +1450,59 @@ namespace QuickMedia {
room->release_room_lock();
}
- PluginResult Matrix::get_previous_room_messages(RoomData *room, Messages &messages, bool latest_messages) {
+ PluginResult Matrix::get_messages_in_direction(RoomData *room, const std::string &token, MessageDirection message_dir, Messages &messages, std::string &new_token) {
+ // TODO: Retry on failure (after a timeout) instead of setting new token to an empty string
+ new_token.clear();
+
+ rapidjson::Document request_data(rapidjson::kObjectType);
+ request_data.AddMember("lazy_load_members", true, request_data.GetAllocator());
+
+ rapidjson::StringBuffer buffer;
+ rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
+ request_data.Accept(writer);
+
+ std::vector<CommandArg> additional_args = {
+ { "-H", "Authorization: Bearer " + access_token }
+ };
+
+ std::string filter = url_param_encode(buffer.GetString());
+
+ char url[512];
+ snprintf(url, sizeof(url), "%s/_matrix/client/r0/rooms/%s/messages?from=%s&limit=20&dir=%s&filter=%s", homeserver.c_str(), room->id.c_str(), token.c_str(), message_dir == MessageDirection::BEFORE ? "b" : "f", filter.c_str());
+
+ rapidjson::Document json_root;
+ DownloadResult download_result = download_json(json_root, url, std::move(additional_args), true);
+ if(download_result != DownloadResult::OK) return download_result_to_plugin_result(download_result);
+
+ if(!json_root.IsObject())
+ return PluginResult::ERR;
+
+ const rapidjson::Value &state_json = GetMember(json_root, "state");
+ events_add_user_info(state_json, room);
+ //events_set_room_info(state_json, room_data);
+
+ const rapidjson::Value &chunk_json = GetMember(json_root, "chunk");
+ if(chunk_json.IsArray()) {
+ for(const rapidjson::Value &event_item_json : chunk_json.GetArray()) {
+ std::shared_ptr<Message> new_message = parse_message_event(event_item_json, room);
+ if(new_message)
+ messages.push_back(std::move(new_message));
+ }
+ }
+
+ const rapidjson::Value &end_json = GetMember(json_root, "end");
+ if(end_json.IsString())
+ new_token.assign(end_json.GetString(), end_json.GetStringLength());
+
+ if(new_token == token)
+ new_token.clear();
+
+ return PluginResult::OK;
+ }
+
+ PluginResult Matrix::get_previous_room_messages(RoomData *room, Messages &messages, bool latest_messages, bool *reached_end) {
size_t num_new_messages = 0;
- PluginResult result = get_previous_room_messages(room, latest_messages, num_new_messages);
+ PluginResult result = get_previous_room_messages(room, latest_messages, num_new_messages, reached_end);
if(result != PluginResult::OK)
return result;
@@ -1993,7 +2043,7 @@ namespace QuickMedia {
return 0;
// TODO: Preallocate
- std::vector<std::shared_ptr<Message>> new_messages;
+ Messages new_messages;
auto me = get_me(room_data);
std::string my_display_name = room_data->get_user_display_name(me);
@@ -2839,7 +2889,7 @@ namespace QuickMedia {
}
}
- PluginResult Matrix::get_previous_room_messages(RoomData *room_data, bool latest_messages, size_t &num_new_messages) {
+ PluginResult Matrix::get_previous_room_messages(RoomData *room_data, bool latest_messages, size_t &num_new_messages, bool *reached_end) {
num_new_messages = 0;
std::string from = room_data->get_prev_batch();
if(from.empty() || latest_messages)
@@ -2869,6 +2919,7 @@ namespace QuickMedia {
return PluginResult::ERR;
const rapidjson::Value &state_json = GetMember(json_root, "state");
+ // TODO: Remove?
events_add_user_info(state_json, room_data);
//events_set_room_info(state_json, room_data);
@@ -2879,9 +2930,14 @@ namespace QuickMedia {
if(!end_json.IsString()) {
room_data->set_prev_batch("invalid");
fprintf(stderr, "Warning: matrix messages response is missing 'end', this could happen if we received the very first messages in the room\n");
+ if(reached_end)
+ *reached_end = true;
return PluginResult::OK;
}
+ if(reached_end)
+ *reached_end = strcmp(end_json.GetString(), from.c_str()) == 0;
+
room_data->set_prev_batch(end_json.GetString());
return PluginResult::OK;
}
@@ -3424,30 +3480,14 @@ namespace QuickMedia {
auto fetched_message_it = room->fetched_messages_by_event_id.find(event_id);
if(fetched_message_it != room->fetched_messages_by_event_id.end())
return fetched_message_it->second;
-#if 0
- rapidjson::Document request_data(rapidjson::kObjectType);
- request_data.AddMember("lazy_load_members", true, request_data.GetAllocator());
-
- rapidjson::StringBuffer buffer;
- rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
- request_data.Accept(writer);
std::vector<CommandArg> additional_args = {
{ "-H", "Authorization: Bearer " + access_token }
};
- std::string filter = url_param_encode(buffer.GetString());
-
- char url[512];
- snprintf(url, sizeof(url), "%s/_matrix/client/r0/rooms/%s/context/%s?limit=0&filter=%s", homeserver.c_str(), room->id.c_str(), event_id.c_str(), filter.c_str());
-#else
- std::vector<CommandArg> additional_args = {
- { "-H", "Authorization: Bearer " + access_token }
- };
-
char url[512];
snprintf(url, sizeof(url), "%s/_matrix/client/r0/rooms/%s/event/%s", homeserver.c_str(), room->id.c_str(), event_id.c_str());
-#endif
+
std::string response;
DownloadResult download_result = download_to_string_cache(url, response, std::move(additional_args), true, [](std::string &response) {
rapidjson::Document json_root;
@@ -3491,21 +3531,97 @@ namespace QuickMedia {
room->fetched_messages_by_event_id.insert(std::make_pair(event_id, nullptr));
return nullptr;
}
-#if 0
- const rapidjson::Value &state_json = GetMember(json_root, "state");
- events_add_user_info(state_json, room);
-#endif
- //events_set_room_info(state_json, room);
-#if 0
- const rapidjson::Value &event_json = GetMember(json_root, "event");
- std::shared_ptr<Message> new_message = parse_message_event(event_json, room);
-#else
+
+ // TODO: Do this? what about state apply order?
+ //const rapidjson::Value &state_json = GetMember(json_root, "state");
+ //events_add_user_info(state_json, room);
+
std::shared_ptr<Message> new_message = parse_message_event(json_root, room);
-#endif
room->fetched_messages_by_event_id.insert(std::make_pair(event_id, new_message));
return new_message;
}
+ PluginResult Matrix::get_message_context(RoomData *room, const std::string &event_id, std::shared_ptr<Message> &message, Messages &before_messages, Messages &after_messages, std::string &before_token, std::string &after_token) {
+ rapidjson::Document request_data(rapidjson::kObjectType);
+ request_data.AddMember("lazy_load_members", true, request_data.GetAllocator());
+
+ rapidjson::StringBuffer buffer;
+ rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
+ request_data.Accept(writer);
+
+ std::vector<CommandArg> additional_args = {
+ { "-H", "Authorization: Bearer " + access_token }
+ };
+
+ std::string filter = url_param_encode(buffer.GetString());
+
+ char url[512];
+ snprintf(url, sizeof(url), "%s/_matrix/client/r0/rooms/%s/context/%s?limit=20&filter=%s", homeserver.c_str(), room->id.c_str(), event_id.c_str(), filter.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) {
+ show_notification("QuickMedia", "Failed to get message", Urgency::CRITICAL);
+ 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 &errcode_json = GetMember(json_root, "errcode");
+ if(errcode_json.IsString() && strcmp(errcode_json.GetString(), "M_NOT_FOUND") != 0) {
+ const rapidjson::Value &error_json = GetMember(json_root, "error");
+ if(error_json.IsString()) {
+ show_notification("QuickMedia", "Failed to get message, error: " + std::string(error_json.GetString(), error_json.GetStringLength()), Urgency::CRITICAL);
+ return PluginResult::ERR;
+ }
+ }
+
+ // TODO: Do this? what about state apply order?
+ //const rapidjson::Value &state_json = GetMember(json_root, "state");
+ //events_add_user_info(state_json, room);
+
+ const rapidjson::Value &start_json = GetMember(json_root, "start");
+ const rapidjson::Value &end_json = GetMember(json_root, "end");
+
+ const rapidjson::Value &event_json = GetMember(json_root, "event");
+ const rapidjson::Value &events_before_json = GetMember(json_root, "events_before");
+ const rapidjson::Value &events_after_json = GetMember(json_root, "events_after");
+
+ if(start_json.IsString())
+ before_token.assign(start_json.GetString(), start_json.GetStringLength());
+
+ if(end_json.IsString())
+ after_token.assign(end_json.GetString(), end_json.GetStringLength());
+
+ message = parse_message_event(event_json, room);
+
+ if(events_before_json.IsArray()) {
+ for(const rapidjson::Value &event_item_json : events_before_json.GetArray()) {
+ std::shared_ptr<Message> new_message = parse_message_event(event_item_json, room);
+ if(new_message)
+ before_messages.push_back(std::move(new_message));
+ }
+ }
+
+ if(events_after_json.IsArray()) {
+ for(const rapidjson::Value &event_item_json : events_after_json.GetArray()) {
+ std::shared_ptr<Message> new_message = parse_message_event(event_item_json, room);
+ if(new_message)
+ after_messages.push_back(std::move(new_message));
+ }
+ }
+
+ return PluginResult::OK;
+ }
+
+ void Matrix::clear_previous_messages_token(RoomData *room) {
+ room->set_prev_batch("");
+ }
+
static const char* file_get_filename(const std::string &filepath) {
size_t index = filepath.rfind('/');
if(index == std::string::npos)