aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2022-10-29 19:31:22 +0200
committerdec05eba <dec05eba@protonmail.com>2022-10-29 19:31:22 +0200
commit555f0e7e910b2231073734816727379e1276aa6c (patch)
tree2081bb231c0526e8fa20f195e049af6d23d2525d /src
parent1b82048e16ae998c780a31ff14317d4ac1fbbacd (diff)
Matrix: add media reply with ctrl+u
Diffstat (limited to 'src')
-rw-r--r--src/AsyncImageLoader.cpp2
-rw-r--r--src/FileAnalyzer.cpp2
-rw-r--r--src/QuickMedia.cpp34
-rw-r--r--src/plugins/Matrix.cpp69
4 files changed, 88 insertions, 19 deletions
diff --git a/src/AsyncImageLoader.cpp b/src/AsyncImageLoader.cpp
index 09c01df..d12f9af 100644
--- a/src/AsyncImageLoader.cpp
+++ b/src/AsyncImageLoader.cpp
@@ -137,7 +137,7 @@ namespace QuickMedia {
}
if(is_content_type_video(file_analyzer.get_content_type())) {
- if(file_analyzer.load_metadata() && video_get_first_frame(file_analyzer, thumbnail_path_resized.data.c_str(), resize_target_size.x, resize_target_size.y)) {
+ if(file_analyzer.load_metadata() && video_get_middle_frame(file_analyzer, thumbnail_path_resized.data.c_str(), resize_target_size.x, resize_target_size.y)) {
thumbnail_data->loading_state = LoadingState::READY_TO_LOAD;
} else {
fprintf(stderr, "Failed to get video frame of %s\n", thumbnail_path.data.c_str());
diff --git a/src/FileAnalyzer.cpp b/src/FileAnalyzer.cpp
index aeb88f7..0f312cf 100644
--- a/src/FileAnalyzer.cpp
+++ b/src/FileAnalyzer.cpp
@@ -127,7 +127,7 @@ namespace QuickMedia {
return 0;
}
- bool video_get_first_frame(const FileAnalyzer &file, const char *destination_path, int width, int height) {
+ bool video_get_middle_frame(const FileAnalyzer &file, const char *destination_path, int width, int height) {
Path destination_path_tmp = destination_path;
destination_path_tmp.append(".tmp.jpg"); // TODO: .png, but the below code also needs to be changed for that
diff --git a/src/QuickMedia.cpp b/src/QuickMedia.cpp
index 57c5489..13931d2 100644
--- a/src/QuickMedia.cpp
+++ b/src/QuickMedia.cpp
@@ -5864,15 +5864,19 @@ namespace QuickMedia {
}
};
- auto upload_file = [this, &current_room](const std::string &filepath, const std::string &filename) {
- run_task_with_loading_screen([this, &current_room, filepath, filename]() {
+ auto upload_file = [this, &current_room, &tabs, &ui_tabs, &chat_state](const std::string &filepath, const std::string &filename) {
+ const int selected_tab = ui_tabs.get_selected();
+ std::shared_ptr<BodyItem> selected = tabs[selected_tab].body->get_selected_shared();
+ void *message_to_reply_to = chat_state == ChatState::REPLYING ? selected->userdata : nullptr;
+
+ run_task_with_loading_screen([this, &current_room, filepath, filename, message_to_reply_to]() {
std::string filepath_mod = filepath;
if(string_starts_with(filepath_mod, "file://"))
filepath_mod.erase(filepath_mod.begin(), filepath_mod.begin() + 7);
std::string event_id_response;
std::string err_msg;
- if(matrix->post_file(current_room, filepath_mod, filename, event_id_response, err_msg) == PluginResult::OK) {
+ if(matrix->post_file(current_room, filepath_mod, filename, event_id_response, err_msg, message_to_reply_to) == PluginResult::OK) {
return true;
} else {
show_notification("QuickMedia", "Failed to upload media to room, error: " + err_msg, Urgency::CRITICAL);
@@ -7102,6 +7106,14 @@ namespace QuickMedia {
continue;
launch_url(selected_item->get_title());
}
+ } else if(event.type == mgl::Event::KeyPressed && chat_state == ChatState::REPLYING) {
+ if(selected_tab == MESSAGES_TAB_INDEX) {
+ if(event.key.code == mgl::Keyboard::U && event.key.control) {
+ frame_skip_text_entry = true;
+ new_page = PageType::FILE_MANAGER;
+ chat_input.set_editable(false);
+ }
+ }
}
if((chat_state == ChatState::TYPING_MESSAGE || chat_state == ChatState::REPLYING || chat_state == ChatState::EDITING) && selected_tab == MESSAGES_TAB_INDEX && !frame_skip_text_entry) {
@@ -7190,6 +7202,22 @@ namespace QuickMedia {
}
redraw = true;
avatar_applied = false;
+
+ if(selected_files.empty()) {
+ if(chat_state == ChatState::REPLYING)
+ chat_input.set_editable(true);
+ } else {
+ mention.hide();
+ chat_input.set_editable(false);
+ chat_input.set_text("");
+ chat_state = ChatState::NAVIGATING;
+ currently_operating_on_item = nullptr;
+ if(typing && current_room) {
+ fprintf(stderr, "Stopped typing\n");
+ typing = false;
+ typing_state_queue.push(false);
+ }
+ }
break;
}
case PageType::CHAT_LOGIN: {
diff --git a/src/plugins/Matrix.cpp b/src/plugins/Matrix.cpp
index b5948d2..13d42bb 100644
--- a/src/plugins/Matrix.cpp
+++ b/src/plugins/Matrix.cpp
@@ -3387,7 +3387,7 @@ namespace QuickMedia {
"</mx-reply>" + std::move(formatted_body);
}
- PluginResult Matrix::post_reply(RoomData *room, const std::string &body, void *relates_to, std::string &event_id_response, const std::string &custom_transaction_id) {
+ PluginResult Matrix::post_reply(RoomData *room, const std::string &body, void *relates_to, std::string &event_id_response, const std::string &custom_transaction_id, const std::optional<UploadInfo> &file_info, const std::optional<UploadInfo> &thumbnail_info) {
Message *relates_to_message_raw = (Message*)relates_to;
std::string transaction_id = custom_transaction_id;
@@ -3397,7 +3397,8 @@ namespace QuickMedia {
if(transaction_id.empty())
return PluginResult::ERR;
- my_events_transaction_ids.insert(transaction_id);
+ if(!file_info)
+ my_events_transaction_ids.insert(transaction_id);
rapidjson::Document in_reply_to_json(rapidjson::kObjectType);
in_reply_to_json.AddMember("event_id", rapidjson::StringRef(relates_to_message_raw->event_id.c_str()), in_reply_to_json.GetAllocator());
@@ -3409,12 +3410,43 @@ namespace QuickMedia {
std::string formatted_message_reply_body = create_formatted_body_for_message_reply(room, relates_to_message_raw, body);
rapidjson::Document request_data(rapidjson::kObjectType);
- request_data.AddMember("msgtype", "m.text", request_data.GetAllocator()); // TODO: Allow image reply? element doesn't do that but we could!
+ request_data.AddMember("msgtype", rapidjson::StringRef(file_info ? content_type_to_message_type(file_info->content_type) : "m.text"), request_data.GetAllocator());
request_data.AddMember("body", rapidjson::StringRef(message_reply_body.c_str()), request_data.GetAllocator());
request_data.AddMember("format", "org.matrix.custom.html", request_data.GetAllocator());
request_data.AddMember("formatted_body", rapidjson::StringRef(formatted_message_reply_body.c_str()), request_data.GetAllocator());
request_data.AddMember("m.relates_to", std::move(relates_to_json), request_data.GetAllocator());
+ // TODO: Add hashblur?
+ if(file_info) {
+ rapidjson::Value info_json(rapidjson::kObjectType);
+ info_json.AddMember("size", file_info->file_size, request_data.GetAllocator());
+ info_json.AddMember("mimetype", rapidjson::StringRef(content_type_to_string(file_info->content_type)), request_data.GetAllocator());
+ if(file_info->dimensions) {
+ info_json.AddMember("w", file_info->dimensions->width, request_data.GetAllocator());
+ info_json.AddMember("h", file_info->dimensions->height, request_data.GetAllocator());
+ }
+ if(file_info->duration_seconds) {
+ // TODO: Check for overflow?
+ info_json.AddMember("duration", (int)(file_info->duration_seconds.value() * 1000.0), request_data.GetAllocator());
+ }
+
+ if(thumbnail_info) {
+ rapidjson::Value thumbnail_info_json(rapidjson::kObjectType);
+ thumbnail_info_json.AddMember("size", thumbnail_info->file_size, request_data.GetAllocator());
+ thumbnail_info_json.AddMember("mimetype", rapidjson::StringRef(content_type_to_string(thumbnail_info->content_type)), request_data.GetAllocator());
+ if(thumbnail_info->dimensions) {
+ thumbnail_info_json.AddMember("w", thumbnail_info->dimensions->width, request_data.GetAllocator());
+ thumbnail_info_json.AddMember("h", thumbnail_info->dimensions->height, request_data.GetAllocator());
+ }
+
+ info_json.AddMember("thumbnail_url", rapidjson::StringRef(thumbnail_info->content_uri.c_str()), request_data.GetAllocator());
+ info_json.AddMember("thumbnail_info", std::move(thumbnail_info_json), request_data.GetAllocator());
+ }
+
+ request_data.AddMember("info", std::move(info_json), request_data.GetAllocator());
+ request_data.AddMember("url", rapidjson::StringRef(file_info->content_uri.c_str()), request_data.GetAllocator());
+ }
+
rapidjson::StringBuffer buffer;
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
request_data.Accept(writer);
@@ -3714,7 +3746,10 @@ namespace QuickMedia {
return filepath.c_str() + index + 1;
}
- PluginResult Matrix::post_file(RoomData *room, const std::string &filepath, std::string filename, std::string &event_id_response, std::string &err_msg) {
+ PluginResult Matrix::post_file(RoomData *room, const std::string &filepath, std::string filename, std::string &event_id_response, std::string &err_msg, void *relates_to) {
+ if(filename.empty())
+ filename = file_get_filename(filepath);
+
UploadInfo file_info;
UploadInfo thumbnail_info;
PluginResult upload_file_result = upload_file(room, filepath, filename, file_info, thumbnail_info, err_msg);
@@ -3726,10 +3761,10 @@ namespace QuickMedia {
if(!thumbnail_info.content_uri.empty())
thumbnail_info_opt = std::move(thumbnail_info);
- if(filename.empty())
- filename = file_get_filename(filepath);
-
- return post_message(room, filename, event_id_response, file_info_opt, thumbnail_info_opt);
+ if(relates_to)
+ return post_reply(room, filename, relates_to, event_id_response, "", file_info_opt, thumbnail_info_opt);
+ else
+ return post_message(room, filename, event_id_response, file_info_opt, thumbnail_info_opt);
}
PluginResult Matrix::upload_file(RoomData *room, const std::string &filepath, std::string filename, UploadInfo &file_info, UploadInfo &thumbnail_info, std::string &err_msg, bool upload_thumbnail) {
@@ -3744,6 +3779,9 @@ namespace QuickMedia {
file_info.dimensions = file_analyzer.get_dimensions();
file_info.duration_seconds = file_analyzer.get_duration_seconds();
+ if(filename.empty())
+ filename = file_get_filename(filepath);
+
int upload_limit;
PluginResult config_result = get_config(&upload_limit);
if(config_result != PluginResult::OK) {
@@ -3766,9 +3804,12 @@ namespace QuickMedia {
char tmp_filename[] = "/tmp/quickmedia_video_frame_XXXXXX";
int tmp_file = mkstemp(tmp_filename);
if(tmp_file != -1) {
- if(video_get_first_frame(file_analyzer, tmp_filename, thumbnail_max_size.x, thumbnail_max_size.y)) {
+ Path thumbnail_filename = filename;
+ thumbnail_filename = thumbnail_filename.filename_no_ext() + ".thumb.jpg"; // TODO: See video_get_middle_frame why this is jpg
+
+ if(video_get_middle_frame(file_analyzer, tmp_filename, thumbnail_max_size.x, thumbnail_max_size.y)) {
UploadInfo upload_info_ignored; // Ignore because it wont be set anyways. Thumbnails dont have thumbnails.
- PluginResult upload_thumbnail_result = upload_file(room, tmp_filename, "", thumbnail_info, upload_info_ignored, err_msg, false);
+ PluginResult upload_thumbnail_result = upload_file(room, tmp_filename, thumbnail_filename.data, thumbnail_info, upload_info_ignored, err_msg, false);
if(upload_thumbnail_result != PluginResult::OK) {
close(tmp_file);
remove(tmp_filename);
@@ -3792,8 +3833,11 @@ namespace QuickMedia {
else
thumbnail_path = filepath;
+ Path thumbnail_filename = filename;
+ thumbnail_filename = thumbnail_filename.filename_no_ext() + ".thumb" + thumbnail_filename.ext();
+
UploadInfo upload_info_ignored; // Ignore because it wont be set anyways. Thumbnails dont have thumbnails.
- PluginResult upload_thumbnail_result = upload_file(room, thumbnail_path, "", thumbnail_info, upload_info_ignored, err_msg, false);
+ PluginResult upload_thumbnail_result = upload_file(room, thumbnail_path, thumbnail_filename.data, thumbnail_info, upload_info_ignored, err_msg, false);
if(upload_thumbnail_result != PluginResult::OK) {
close(tmp_file);
remove(tmp_filename);
@@ -3814,9 +3858,6 @@ namespace QuickMedia {
{ "--data-binary", "@" + filepath }
};
- if(filename.empty())
- filename = file_get_filename(filepath);
-
std::string filename_escaped = url_param_encode(filename);
char url[512];