Compare commits

...

2 Commits

Author SHA1 Message Date
7948d820c3 fix filepaths on windows 2024-01-30 15:16:01 +01:00
5aac3422aa allow "copy file" which sets the text/uri-list with the file path 2024-01-30 11:58:01 +01:00
4 changed files with 84 additions and 16 deletions

View File

@ -17,10 +17,8 @@
#include "./media_meta_info_loader.hpp"
#include "./sdl_clipboard_utils.hpp"
#include "SDL_clipboard.h"
#include <cctype>
#include <cstdint>
#include <ctime>
#include <cstdio>
#include <chrono>
@ -28,10 +26,7 @@
#include <fstream>
#include <iomanip>
#include <sstream>
#include <string>
#include <variant>
#include <vector>
namespace Components {
@ -72,6 +67,48 @@ static std::string file_path_url_escape(const std::string&& value) {
return escaped.str();
}
const void* clipboard_callback(void* userdata, const char* mime_type, size_t* size) {
if (mime_type == nullptr) {
// cleared or new data is set
return nullptr;
}
if (userdata == nullptr) {
// error
return nullptr;
}
auto* cg = static_cast<ChatGui4*>(userdata);
std::lock_guard lg{cg->_set_clipboard_data_mutex};
if (!cg->_set_clipboard_data.count(mime_type)) {
return nullptr;
}
const auto& sh_vec = cg->_set_clipboard_data.at(mime_type);
if (!static_cast<bool>(sh_vec)) {
// error, empty shared pointer
return nullptr;
}
*size = sh_vec->size();
return sh_vec->data();
}
void ChatGui4::setClipboardData(std::vector<std::string> mime_types, std::shared_ptr<std::vector<uint8_t>>&& data) {
std::vector<const char*> tmp_mimetype_list;
for (const auto& mime_type : mime_types) {
tmp_mimetype_list.push_back(mime_type.data());
}
std::lock_guard lg{_set_clipboard_data_mutex};
for (const auto& mime_type : mime_types) {
_set_clipboard_data[mime_type] = data;
}
SDL_SetClipboardData(clipboard_callback, nullptr, this, tmp_mimetype_list.data(), tmp_mimetype_list.size());
}
ChatGui4::ChatGui4(
ConfigModelI& conf,
RegistryMessageModel& rmm,
@ -80,6 +117,17 @@ ChatGui4::ChatGui4(
) : _conf(conf), _rmm(rmm), _cr(cr), _tal(_cr), _contact_tc(_tal, tu), _msg_tc(_mil, tu), _sip(tu) {
}
ChatGui4::~ChatGui4(void) {
// TODO: this is bs
SDL_ClearClipboardData();
// this might be better, need to see if this works (docs needs improving)
//for (const auto& [k, _] : _set_clipboard_data) {
//const auto* tmp_mime_type = k.c_str();
//SDL_SetClipboardData(nullptr, nullptr, nullptr, &tmp_mime_type, 1);
//}
}
void ChatGui4::render(float time_delta) {
if (!_cr.storage<Contact::Components::TagAvatarInvalidate>().empty()) { // handle force-reloads for avatars
std::vector<Contact3> to_purge;
@ -514,7 +562,7 @@ void ChatGui4::render(float time_delta) {
_fss.requestFile(
[](const auto& path) -> bool { return std::filesystem::is_regular_file(path); },
[this](const auto& path){
_rmm.sendFilePath(*_selected_contact, path.filename().u8string(), path.u8string());
_rmm.sendFilePath(*_selected_contact, path.filename().generic_u8string(), path.generic_u8string());
},
[](){}
);
@ -577,7 +625,7 @@ void ChatGui4::render(float time_delta) {
void ChatGui4::sendFilePath(const char* file_path) {
if (_selected_contact && std::filesystem::is_regular_file(file_path)) {
_rmm.sendFilePath(*_selected_contact, std::filesystem::path(file_path).filename().u8string(), file_path);
_rmm.sendFilePath(*_selected_contact, std::filesystem::path(file_path).filename().generic_u8string(), file_path);
}
}
@ -671,10 +719,10 @@ void ChatGui4::renderMessageBodyFile(Message3Registry& reg, const Message3 e) {
//for (const auto& c : _cr.view<entt::get_t<Contact::Components::TagBig>, entt::exclude_t<Contact::Components::RequestIncoming, Contact::Components::TagRequestOutgoing>>()) {
for (const auto& c : _cr.view<Contact::Components::TagBig>()) {
if (renderContactListContactSmall(c, false)) {
//_rmm.sendFilePath(*_selected_contact, path.filename().u8string(), path.u8string());
//_rmm.sendFilePath(*_selected_contact, path.filename().generic_u8string(), path.generic_u8string());
const auto& fil = reg.get<Message::Components::Transfer::FileInfoLocal>(e);
for (const auto& path : fil.file_list) {
_rmm.sendFilePath(c, std::filesystem::path{path}.filename().u8string(), path);
_rmm.sendFilePath(c, std::filesystem::path{path}.filename().generic_u8string(), path);
}
}
}
@ -761,10 +809,19 @@ void ChatGui4::renderMessageBodyFile(Message3Registry& reg, const Message3 e) {
const auto& local_info = reg.get<Message::Components::Transfer::FileInfoLocal>(e);
if (local_info.file_list.size() > i && ImGui::BeginPopupContextItem("##file_c")) {
if (ImGui::MenuItem("open")) {
std::string url{"file://" + file_path_url_escape(std::filesystem::canonical(local_info.file_list.at(i)).u8string())};
const std::string url{"file://" + file_path_url_escape(std::filesystem::canonical(local_info.file_list.at(i)).generic_u8string())};
std::cout << "opening file '" << url << "'\n";
SDL_OpenURL(url.c_str());
}
if (ImGui::MenuItem("copy file")) {
const std::string url{"file://" + file_path_url_escape(std::filesystem::canonical(local_info.file_list.at(i)).generic_u8string())};
//ImGui::SetClipboardText(url.c_str());
setClipboardData({"text/uri-list", "text/x-moz-url"}, std::make_shared<std::vector<uint8_t>>(url.begin(), url.end()));
}
if (ImGui::MenuItem("copy filepath")) {
const auto file_path = std::filesystem::canonical(local_info.file_list.at(i)).u8string(); //TODO: use generic over native?
ImGui::SetClipboardText(file_path.c_str());
}
ImGui::EndPopup();
}
}
@ -1065,7 +1122,7 @@ void ChatGui4::pasteFile(const char* mime_type) {
std::ofstream(tmp_file_path, std::ios_base::out | std::ios_base::binary)
.write(reinterpret_cast<const char*>(img_data.data()), img_data.size());
_rmm.sendFilePath(*_selected_contact, tmp_file_name.str(), tmp_file_path.u8string());
_rmm.sendFilePath(*_selected_contact, tmp_file_name.str(), tmp_file_path.generic_u8string());
},
[](){}
);

View File

@ -9,9 +9,13 @@
#include "./message_image_loader.hpp"
#include "./file_selector.hpp"
#include "./send_image_popup.hpp"
#include "entt/container/dense_map.hpp"
#include <cstdint>
#include <vector>
#include <set>
#include <string>
#include <mutex>
#include <memory>
class ChatGui4 {
ConfigModelI& _conf;
@ -37,6 +41,12 @@ class ChatGui4 {
float TEXT_BASE_WIDTH {1};
float TEXT_BASE_HEIGHT {1};
// mimetype -> data
entt::dense_map<std::string, std::shared_ptr<std::vector<uint8_t>>> _set_clipboard_data;
std::mutex _set_clipboard_data_mutex; // might be called out of order
friend const void* clipboard_callback(void* userdata, const char* mime_type, size_t* size);
void setClipboardData(std::vector<std::string> mime_types, std::shared_ptr<std::vector<uint8_t>>&& data);
public:
ChatGui4(
ConfigModelI& conf,
@ -44,6 +54,7 @@ class ChatGui4 {
Contact3Registry& cr,
TextureUploaderI& tu
);
~ChatGui4(void);
public:
void render(float time_delta);

View File

@ -47,7 +47,7 @@ void FileSelector::render(void) {
std::filesystem::path current_path = _current_file_path;
current_path.remove_filename();
ImGui::Text("path: %s", _current_file_path.u8string().c_str());
ImGui::Text("path: %s", _current_file_path.generic_u8string().c_str());
// begin table with selectables
constexpr ImGuiTableFlags table_flags =
@ -175,7 +175,7 @@ void FileSelector::render(void) {
}
if (ImGui::TableNextColumn()) {
ImGui::TextUnformatted((dir_entry.path().filename().u8string() + "/").c_str());
ImGui::TextUnformatted((dir_entry.path().filename().generic_u8string() + "/").c_str());
}
if (ImGui::TableNextColumn()) {
@ -206,7 +206,7 @@ void FileSelector::render(void) {
}
if (ImGui::TableNextColumn()) {
ImGui::TextUnformatted(dir_entry.path().filename().u8string().c_str());
ImGui::TextUnformatted(dir_entry.path().filename().generic_u8string().c_str());
}
if (ImGui::TableNextColumn()) {

View File

@ -83,7 +83,7 @@ std::string ToxAvatarManager::getAvatarPath(const ToxKey& key) const {
const std::string_view avatar_save_path {_conf.get_string("ToxAvatarManager", "save_path").value()};
const auto pub_key_string = bin2hex({key.data.cbegin(), key.data.cend()});
const auto file_path = std::filesystem::path(avatar_save_path) / (pub_key_string + ".png");
return file_path.u8string();
return file_path.generic_u8string();
}
void ToxAvatarManager::addAvatarFileToContact(const Contact3 c, const ToxKey& key) {