424 lines
13 KiB
C++
424 lines
13 KiB
C++
#include "pch.h"
|
|
|
|
#include "legacy_cloud_services.h"
|
|
|
|
#include "app.h"
|
|
#include "canvas.h"
|
|
#include "legacy_app_dialog_services.h"
|
|
#include "legacy_canvas_view_services.h"
|
|
#include "legacy_document_session_services.h"
|
|
#include "legacy_document_open_services.h"
|
|
#include "legacy_ui_overlay_services.h"
|
|
#include "node_dialog_cloud.h"
|
|
#include "node_progress_bar.h"
|
|
#include "util.h"
|
|
|
|
namespace pp::panopainter {
|
|
pp::foundation::Status execute_legacy_cloud_download_selection_action(
|
|
App& app,
|
|
pp::app::CloudDownloadSelectionAction action,
|
|
NodeDialogCloud& dialog);
|
|
|
|
namespace {
|
|
|
|
#if WITH_CURL
|
|
int progress_callback_download(void* clientp, curl_off_t dltotal,
|
|
curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow)
|
|
{
|
|
(void)ultotal;
|
|
(void)ulnow;
|
|
auto* progress = static_cast<std::function<void(float)>*>(clientp);
|
|
const auto plan = pp::app::plan_cloud_transfer_progress(
|
|
static_cast<std::int64_t>(dltotal),
|
|
static_cast<std::int64_t>(dlnow));
|
|
if (progress != nullptr && *progress && plan.notify)
|
|
(*progress)(plan.fraction);
|
|
return 0;
|
|
}
|
|
|
|
int progress_callback_upload(void* clientp, curl_off_t dltotal,
|
|
curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow)
|
|
{
|
|
(void)dltotal;
|
|
(void)dlnow;
|
|
auto* progress = static_cast<std::function<void(float)>*>(clientp);
|
|
const auto plan = pp::app::plan_cloud_transfer_progress(
|
|
static_cast<std::int64_t>(ultotal),
|
|
static_cast<std::int64_t>(ulnow));
|
|
if (progress != nullptr && *progress && plan.notify)
|
|
(*progress)(plan.fraction);
|
|
return 0;
|
|
}
|
|
|
|
struct curl_httppost* create_cloud_upload_form(const std::string& filename)
|
|
{
|
|
struct curl_httppost* formpost = NULL;
|
|
struct curl_httppost* lastptr = NULL;
|
|
|
|
curl_formadd(&formpost,
|
|
&lastptr,
|
|
CURLFORM_COPYNAME, "fileToUpload",
|
|
CURLFORM_FILE, filename.c_str(),
|
|
CURLFORM_END);
|
|
|
|
return formpost;
|
|
}
|
|
|
|
void handle_cloud_upload_transfer_result(CURLcode err, const std::string& res)
|
|
{
|
|
(void)err;
|
|
std::cout << "\n\nUPLOAD RESULT\n" << res << "\n\n\n";
|
|
}
|
|
|
|
void execute_cloud_download_transfer(
|
|
App& app,
|
|
std::string url,
|
|
std::string dest_filepath,
|
|
std::function<void(float)> progress);
|
|
|
|
void execute_cloud_download_flow(
|
|
App& app,
|
|
const pp::app::CloudDownloadRequest& request);
|
|
|
|
std::shared_ptr<NodeMessageBox> create_cloud_download_progress_dialog(App& app)
|
|
{
|
|
return pp::panopainter::create_legacy_app_message_dialog(
|
|
app,
|
|
pp::app::plan_cloud_download_progress_prompt());
|
|
}
|
|
|
|
void execute_cloud_download_transfer_with_progress_dialog(
|
|
App& app,
|
|
const pp::app::CloudDownloadRequest& request,
|
|
const std::shared_ptr<NodeMessageBox>& dialog)
|
|
{
|
|
const std::string url = "https://panopainter.com/cloud/cloud-dwl.php?file=" + request.selected_file;
|
|
execute_cloud_download_transfer(app, url, request.selected_path, [dialog](float p) {
|
|
const auto progress = pp::app::format_cloud_download_progress_message(p);
|
|
dialog->m_message->set_text(progress.c_str());
|
|
});
|
|
}
|
|
|
|
void execute_cloud_download_transfer(
|
|
App& app,
|
|
std::string url,
|
|
std::string dest_filepath,
|
|
std::function<void(float)> progress)
|
|
{
|
|
const auto plan = pp::app::plan_cloud_download_transfer(
|
|
url,
|
|
dest_filepath,
|
|
progress != nullptr,
|
|
app.disables_network_tls_verification());
|
|
if (plan.action != pp::app::CloudTransferAction::start_transfer) {
|
|
LOG("download skipped: invalid transfer request");
|
|
return;
|
|
}
|
|
|
|
CURL* curl = curl_easy_init();
|
|
if (curl)
|
|
{
|
|
FILE* fp = fopen(dest_filepath.c_str(), "wb");
|
|
if (fp == nullptr) {
|
|
LOG("download failed to open destination %s", dest_filepath.c_str());
|
|
curl_easy_cleanup(curl);
|
|
return;
|
|
}
|
|
LOG("download %s to %s", url.c_str(), dest_filepath.c_str());
|
|
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
|
|
curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
|
|
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_data_write);
|
|
if (plan.disable_tls_verification)
|
|
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
|
|
if (plan.enable_progress)
|
|
{
|
|
curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, progress_callback_download);
|
|
curl_easy_setopt(curl, CURLOPT_XFERINFODATA, &progress);
|
|
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
|
|
}
|
|
auto err = curl_easy_perform(curl);
|
|
curl_easy_cleanup(curl);
|
|
fclose(fp);
|
|
}
|
|
}
|
|
|
|
void open_downloaded_project_and_close_dialog(
|
|
App& app,
|
|
const pp::app::CloudDownloadRequest& request,
|
|
const std::shared_ptr<NodeMessageBox>& dialog)
|
|
{
|
|
execute_legacy_downloaded_project_open(app, request.selected_path, request.selected_name);
|
|
pp::panopainter::close_legacy_dialog_node(*dialog);
|
|
}
|
|
|
|
void execute_cloud_download_flow(
|
|
App& app,
|
|
const pp::app::CloudDownloadRequest& request)
|
|
{
|
|
auto m = create_cloud_download_progress_dialog(app);
|
|
execute_cloud_download_transfer_with_progress_dialog(app, request, m);
|
|
open_downloaded_project_and_close_dialog(app, request, m);
|
|
}
|
|
|
|
void execute_cloud_upload_transfer(
|
|
App& app,
|
|
std::string filename,
|
|
std::string name,
|
|
std::function<void(float)> progress)
|
|
{
|
|
const auto plan = pp::app::plan_cloud_upload_transfer(
|
|
filename,
|
|
progress != nullptr,
|
|
app.disables_network_tls_verification());
|
|
if (plan.action != pp::app::CloudTransferAction::start_transfer) {
|
|
LOG("upload skipped: invalid transfer request");
|
|
return;
|
|
}
|
|
|
|
CURL* curl;
|
|
auto* formpost = create_cloud_upload_form(filename);
|
|
|
|
//curl_global_init(CURL_GLOBAL_ALL);
|
|
|
|
curl = curl_easy_init();
|
|
std::string res;
|
|
|
|
if (curl)
|
|
{
|
|
std::string url = "https://panopainter.com/cloud/cloud-upl.php?name=" + name;
|
|
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
|
|
curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
|
|
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &res);
|
|
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_data_handler);
|
|
if (plan.disable_tls_verification)
|
|
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
|
|
if (plan.enable_progress)
|
|
{
|
|
curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, progress_callback_upload);
|
|
curl_easy_setopt(curl, CURLOPT_XFERINFODATA, &progress);
|
|
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
|
|
}
|
|
auto err = curl_easy_perform(curl);
|
|
handle_cloud_upload_transfer_result(err, res);
|
|
curl_easy_cleanup(curl);
|
|
}
|
|
}
|
|
|
|
void execute_cloud_download_thread(
|
|
App& app,
|
|
const pp::app::CloudDownloadRequest& request)
|
|
{
|
|
BT_SetTerminate();
|
|
execute_cloud_download_flow(app, request);
|
|
}
|
|
|
|
void launch_cloud_download_thread(
|
|
App& app,
|
|
const pp::app::CloudDownloadRequest& request)
|
|
{
|
|
std::thread([app = &app, request] {
|
|
execute_cloud_download_thread(*app, request);
|
|
}).detach();
|
|
}
|
|
|
|
void execute_cloud_publish_worker(App& app, bool save_before_upload)
|
|
{
|
|
BT_SetTerminate();
|
|
|
|
if (save_before_upload)
|
|
{
|
|
execute_legacy_document_save_before_cloud_upload(app);
|
|
}
|
|
|
|
const auto progress_plan = pp::app::plan_cloud_upload_progress_dialog();
|
|
auto pb = app.show_progress(progress_plan.title, progress_plan.total);
|
|
|
|
execute_cloud_upload_transfer(app, app.doc_path, app.doc_filename, [pb](float p) {
|
|
pb->set_progress(p);
|
|
});
|
|
|
|
pp::panopainter::close_legacy_dialog_node(*pb);
|
|
const auto success_plan = pp::app::plan_cloud_upload_success_prompt();
|
|
app.message_box(success_plan.title, success_plan.message, success_plan.show_cancel);
|
|
}
|
|
|
|
void wire_cloud_publish_prompt_buttons(
|
|
const std::shared_ptr<NodeMessageBox>& dialog,
|
|
std::function<void()> upload_thread)
|
|
{
|
|
dialog->btn_ok->on_click = [dialog, upload_thread](Node*) {
|
|
std::thread(upload_thread).detach();
|
|
pp::panopainter::close_legacy_dialog_node(*dialog);
|
|
};
|
|
dialog->btn_cancel->on_click = [dialog](Node*) {
|
|
pp::panopainter::close_legacy_dialog_node(*dialog);
|
|
};
|
|
}
|
|
|
|
void show_cloud_publish_prompt(App& app, bool save_before_upload)
|
|
{
|
|
auto upload_thread = [&app, save_before_upload] {
|
|
execute_cloud_publish_worker(app, save_before_upload);
|
|
};
|
|
|
|
const auto prompt_plan = pp::app::plan_cloud_publish_prompt();
|
|
auto dialog = app.message_box(prompt_plan.title, prompt_plan.message, prompt_plan.show_cancel);
|
|
wire_cloud_publish_prompt_buttons(dialog, upload_thread);
|
|
}
|
|
|
|
std::shared_ptr<NodeProgressBar> create_cloud_bulk_upload_progress(
|
|
App& app,
|
|
int progress_total)
|
|
{
|
|
const auto progress_plan = pp::app::plan_cloud_bulk_upload_progress_dialog(progress_total);
|
|
return app.show_progress(progress_plan.title, progress_plan.total);
|
|
}
|
|
|
|
void execute_cloud_bulk_upload_files(
|
|
App& app,
|
|
const std::vector<std::string>& names,
|
|
const std::shared_ptr<NodeProgressBar>& bulk_progress)
|
|
{
|
|
[[maybe_unused]] gl_state gl;
|
|
for (const auto& n : names)
|
|
{
|
|
std::string path = app.data_path + "/" + n;
|
|
execute_cloud_upload_transfer(app, path, std::string(), std::function<void(float)> {});
|
|
|
|
if (bulk_progress) {
|
|
bulk_progress->increment();
|
|
}
|
|
}
|
|
}
|
|
|
|
void close_cloud_bulk_upload_progress(std::shared_ptr<NodeProgressBar>& progress)
|
|
{
|
|
if (progress) {
|
|
pp::panopainter::close_legacy_dialog_node(*progress);
|
|
}
|
|
progress.reset();
|
|
}
|
|
#endif //WITH_CURL
|
|
|
|
void wire_cloud_browser_ok_button(
|
|
const std::shared_ptr<NodeDialogCloud>& dialog,
|
|
App* app)
|
|
{
|
|
dialog->btn_ok->on_click = [app, dialog](Node*) {
|
|
const auto selection_plan = pp::app::plan_cloud_download_selection(dialog->selected_file);
|
|
const auto status = execute_legacy_cloud_download_selection_action(*app, selection_plan, *dialog);
|
|
if (!status.ok())
|
|
LOG("Cloud download selection action failed: %s", status.message);
|
|
};
|
|
}
|
|
|
|
void show_cloud_browser_dialog(App& app)
|
|
{
|
|
auto dialog = pp::panopainter::create_legacy_cloud_browser_dialog_overlay(app);
|
|
wire_cloud_browser_ok_button(dialog, &app);
|
|
}
|
|
|
|
void show_cloud_save_required_warning(App& app);
|
|
|
|
class LegacyCloudServices final : public pp::app::CloudServices {
|
|
public:
|
|
explicit LegacyCloudServices(App& app) noexcept
|
|
: app_(app)
|
|
{
|
|
}
|
|
|
|
void show_save_required_warning() override
|
|
{
|
|
show_cloud_save_required_warning(app_);
|
|
}
|
|
|
|
void prompt_publish(bool save_before_upload) override
|
|
{
|
|
show_cloud_publish_prompt(app_, save_before_upload);
|
|
}
|
|
|
|
void begin_bulk_upload(int progress_total, bool show_progress) override
|
|
{
|
|
bulk_progress_.reset();
|
|
if (show_progress) {
|
|
bulk_progress_ = create_cloud_bulk_upload_progress(app_, progress_total);
|
|
}
|
|
}
|
|
|
|
void upload_all_bulk_files() override
|
|
{
|
|
auto names = Asset::list_files(app_.data_path, ".*\\.ppi");
|
|
execute_cloud_bulk_upload_files(app_, names, bulk_progress_);
|
|
}
|
|
|
|
void end_bulk_upload() override
|
|
{
|
|
close_cloud_bulk_upload_progress(bulk_progress_);
|
|
}
|
|
|
|
void show_browser() override
|
|
{
|
|
show_cloud_browser_dialog(app_);
|
|
}
|
|
|
|
void start_download(const pp::app::CloudDownloadRequest& request) override
|
|
{
|
|
launch_cloud_download_thread(app_, request);
|
|
}
|
|
|
|
private:
|
|
App& app_;
|
|
std::shared_ptr<NodeProgressBar> bulk_progress_;
|
|
};
|
|
|
|
void show_cloud_save_required_warning(App& app)
|
|
{
|
|
const auto plan = pp::app::plan_cloud_save_required_prompt();
|
|
app.message_box(plan.title, plan.message, plan.show_cancel);
|
|
}
|
|
|
|
} // namespace
|
|
|
|
pp::foundation::Status execute_legacy_cloud_upload_plan(
|
|
App& app,
|
|
const pp::app::CloudUploadPlan& plan)
|
|
{
|
|
LegacyCloudServices services(app);
|
|
return pp::app::execute_cloud_upload_plan(plan, services);
|
|
}
|
|
|
|
pp::foundation::Status execute_legacy_cloud_bulk_upload_plan(
|
|
App& app,
|
|
const pp::app::CloudBulkUploadPlan& plan)
|
|
{
|
|
LegacyCloudServices services(app);
|
|
return pp::app::execute_cloud_bulk_upload_plan(plan, services);
|
|
}
|
|
|
|
pp::foundation::Status execute_legacy_cloud_browse_action(
|
|
App& app,
|
|
pp::app::CloudBrowseAction action)
|
|
{
|
|
LegacyCloudServices services(app);
|
|
return pp::app::execute_cloud_browse_action(action, services);
|
|
}
|
|
|
|
pp::foundation::Status execute_legacy_cloud_download_selection_action(
|
|
App& app,
|
|
pp::app::CloudDownloadSelectionAction action,
|
|
NodeDialogCloud& dialog)
|
|
{
|
|
pp::app::CloudDownloadRequest request {
|
|
.selected_file = dialog.selected_file,
|
|
.selected_path = dialog.selected_path,
|
|
.selected_name = dialog.selected_name,
|
|
};
|
|
if (action == pp::app::CloudDownloadSelectionAction::start_download) {
|
|
pp::panopainter::close_legacy_dialog_node(dialog);
|
|
}
|
|
LegacyCloudServices services(app);
|
|
return pp::app::execute_cloud_download_selection_action(action, services, request);
|
|
}
|
|
|
|
} // namespace pp::panopainter
|