316 lines
8.5 KiB
C++
316 lines
8.5 KiB
C++
#pragma once
|
|
|
|
#include "app_core/app_dialog.h"
|
|
#include "foundation/result.h"
|
|
|
|
#include <cstdio>
|
|
#include <cstddef>
|
|
#include <cstdint>
|
|
#include <limits>
|
|
#include <string>
|
|
#include <string_view>
|
|
|
|
namespace pp::app {
|
|
|
|
enum class CloudUploadAction {
|
|
unavailable_no_canvas,
|
|
show_save_required_warning,
|
|
prompt_publish,
|
|
};
|
|
|
|
enum class CloudBrowseAction {
|
|
unavailable_no_canvas,
|
|
show_browser,
|
|
};
|
|
|
|
enum class CloudDownloadSelectionAction {
|
|
wait_for_selection,
|
|
start_download,
|
|
};
|
|
|
|
enum class CloudTransferDirection {
|
|
download,
|
|
upload,
|
|
};
|
|
|
|
enum class CloudTransferAction {
|
|
reject_missing_source,
|
|
reject_missing_destination,
|
|
start_transfer,
|
|
};
|
|
|
|
struct CloudUploadPlan {
|
|
CloudUploadAction action = CloudUploadAction::unavailable_no_canvas;
|
|
bool save_before_upload = false;
|
|
};
|
|
|
|
struct CloudBulkUploadPlan {
|
|
std::size_t file_count = 0;
|
|
int progress_total = 0;
|
|
bool show_progress = false;
|
|
};
|
|
|
|
struct CloudDownloadRequest {
|
|
std::string selected_file;
|
|
std::string selected_path;
|
|
std::string selected_name;
|
|
};
|
|
|
|
struct CloudTransferPlan {
|
|
CloudTransferDirection direction = CloudTransferDirection::download;
|
|
CloudTransferAction action = CloudTransferAction::reject_missing_source;
|
|
bool enable_progress = false;
|
|
bool disable_tls_verification = false;
|
|
};
|
|
|
|
struct CloudTransferProgressPlan {
|
|
bool notify = false;
|
|
float fraction = 0.0F;
|
|
};
|
|
|
|
[[nodiscard]] inline AppMessageDialogPlan plan_cloud_save_required_prompt()
|
|
{
|
|
return plan_app_message_dialog(
|
|
"Warning",
|
|
"This document needs to be saved before upload.",
|
|
false);
|
|
}
|
|
|
|
[[nodiscard]] inline AppMessageDialogPlan plan_cloud_publish_prompt()
|
|
{
|
|
return plan_app_message_dialog(
|
|
"Publish document",
|
|
"Would you like to upload to the public domain?",
|
|
true,
|
|
"Yes",
|
|
"No");
|
|
}
|
|
|
|
[[nodiscard]] inline AppMessageDialogPlan plan_cloud_upload_success_prompt()
|
|
{
|
|
return plan_app_message_dialog(
|
|
"Success",
|
|
"This document has been succesfully uploaded.",
|
|
false);
|
|
}
|
|
|
|
[[nodiscard]] inline AppProgressDialogPlan plan_cloud_upload_progress_dialog()
|
|
{
|
|
return plan_app_progress_dialog("Uploading", 0);
|
|
}
|
|
|
|
[[nodiscard]] inline AppProgressDialogPlan plan_cloud_bulk_upload_progress_dialog(int progress_total)
|
|
{
|
|
return plan_app_progress_dialog("Export Pano Image", progress_total);
|
|
}
|
|
|
|
[[nodiscard]] inline AppMessageDialogPlan plan_cloud_download_progress_prompt()
|
|
{
|
|
return plan_app_message_dialog(
|
|
"Downloading",
|
|
"Download in progress",
|
|
true);
|
|
}
|
|
|
|
[[nodiscard]] inline std::string format_cloud_download_progress_message(float progress_fraction)
|
|
{
|
|
char buffer[64] {};
|
|
std::snprintf(
|
|
buffer,
|
|
sizeof(buffer),
|
|
"Download in progress %.2f%%",
|
|
progress_fraction * 100.0F);
|
|
return buffer;
|
|
}
|
|
|
|
class CloudServices {
|
|
public:
|
|
virtual ~CloudServices() = default;
|
|
|
|
virtual void show_save_required_warning() = 0;
|
|
virtual void prompt_publish(bool save_before_upload) = 0;
|
|
virtual void begin_bulk_upload(int progress_total, bool show_progress) = 0;
|
|
virtual void upload_all_bulk_files() = 0;
|
|
virtual void end_bulk_upload() = 0;
|
|
virtual void show_browser() = 0;
|
|
virtual void start_download(const CloudDownloadRequest& request) = 0;
|
|
};
|
|
|
|
[[nodiscard]] constexpr CloudUploadPlan plan_cloud_upload(
|
|
bool has_canvas,
|
|
bool is_new_document,
|
|
bool has_unsaved_changes) noexcept
|
|
{
|
|
if (!has_canvas) {
|
|
return { CloudUploadAction::unavailable_no_canvas, false };
|
|
}
|
|
|
|
if (is_new_document) {
|
|
return { CloudUploadAction::show_save_required_warning, false };
|
|
}
|
|
|
|
return { CloudUploadAction::prompt_publish, has_unsaved_changes };
|
|
}
|
|
|
|
[[nodiscard]] constexpr CloudBrowseAction plan_cloud_browse(bool has_canvas) noexcept
|
|
{
|
|
return has_canvas
|
|
? CloudBrowseAction::show_browser
|
|
: CloudBrowseAction::unavailable_no_canvas;
|
|
}
|
|
|
|
[[nodiscard]] constexpr CloudDownloadSelectionAction plan_cloud_download_selection(
|
|
std::string_view selected_file) noexcept
|
|
{
|
|
return selected_file.empty()
|
|
? CloudDownloadSelectionAction::wait_for_selection
|
|
: CloudDownloadSelectionAction::start_download;
|
|
}
|
|
|
|
[[nodiscard]] constexpr CloudBulkUploadPlan plan_cloud_bulk_upload(
|
|
std::size_t file_count,
|
|
bool progress_ui_available) noexcept
|
|
{
|
|
const auto max_progress_total = static_cast<std::size_t>(std::numeric_limits<int>::max());
|
|
return {
|
|
file_count,
|
|
file_count > max_progress_total ? std::numeric_limits<int>::max() : static_cast<int>(file_count),
|
|
progress_ui_available,
|
|
};
|
|
}
|
|
|
|
[[nodiscard]] constexpr CloudTransferPlan plan_cloud_download_transfer(
|
|
std::string_view url,
|
|
std::string_view destination_path,
|
|
bool has_progress_callback,
|
|
bool disables_tls_verification) noexcept
|
|
{
|
|
if (url.empty()) {
|
|
return {
|
|
CloudTransferDirection::download,
|
|
CloudTransferAction::reject_missing_source,
|
|
false,
|
|
false,
|
|
};
|
|
}
|
|
|
|
if (destination_path.empty()) {
|
|
return {
|
|
CloudTransferDirection::download,
|
|
CloudTransferAction::reject_missing_destination,
|
|
false,
|
|
false,
|
|
};
|
|
}
|
|
|
|
return {
|
|
CloudTransferDirection::download,
|
|
CloudTransferAction::start_transfer,
|
|
has_progress_callback,
|
|
disables_tls_verification,
|
|
};
|
|
}
|
|
|
|
[[nodiscard]] constexpr CloudTransferPlan plan_cloud_upload_transfer(
|
|
std::string_view filename,
|
|
bool has_progress_callback,
|
|
bool disables_tls_verification) noexcept
|
|
{
|
|
if (filename.empty()) {
|
|
return {
|
|
CloudTransferDirection::upload,
|
|
CloudTransferAction::reject_missing_source,
|
|
false,
|
|
false,
|
|
};
|
|
}
|
|
|
|
return {
|
|
CloudTransferDirection::upload,
|
|
CloudTransferAction::start_transfer,
|
|
has_progress_callback,
|
|
disables_tls_verification,
|
|
};
|
|
}
|
|
|
|
[[nodiscard]] constexpr CloudTransferProgressPlan plan_cloud_transfer_progress(
|
|
std::int64_t total,
|
|
std::int64_t current) noexcept
|
|
{
|
|
if (total <= 0) {
|
|
return {};
|
|
}
|
|
|
|
const auto clamped_current = current < 0
|
|
? std::int64_t { 0 }
|
|
: (current > total ? total : current);
|
|
return {
|
|
true,
|
|
static_cast<float>(static_cast<double>(clamped_current) / static_cast<double>(total)),
|
|
};
|
|
}
|
|
|
|
[[nodiscard]] inline pp::foundation::Status execute_cloud_upload_plan(
|
|
const CloudUploadPlan& plan,
|
|
CloudServices& services)
|
|
{
|
|
switch (plan.action) {
|
|
case CloudUploadAction::unavailable_no_canvas:
|
|
return pp::foundation::Status::success();
|
|
case CloudUploadAction::show_save_required_warning:
|
|
services.show_save_required_warning();
|
|
return pp::foundation::Status::success();
|
|
case CloudUploadAction::prompt_publish:
|
|
services.prompt_publish(plan.save_before_upload);
|
|
return pp::foundation::Status::success();
|
|
}
|
|
|
|
return pp::foundation::Status::invalid_argument("unknown cloud upload action");
|
|
}
|
|
|
|
[[nodiscard]] inline pp::foundation::Status execute_cloud_bulk_upload_plan(
|
|
const CloudBulkUploadPlan& plan,
|
|
CloudServices& services)
|
|
{
|
|
services.begin_bulk_upload(plan.progress_total, plan.show_progress);
|
|
services.upload_all_bulk_files();
|
|
services.end_bulk_upload();
|
|
return pp::foundation::Status::success();
|
|
}
|
|
|
|
[[nodiscard]] inline pp::foundation::Status execute_cloud_browse_action(
|
|
CloudBrowseAction action,
|
|
CloudServices& services)
|
|
{
|
|
switch (action) {
|
|
case CloudBrowseAction::unavailable_no_canvas:
|
|
return pp::foundation::Status::success();
|
|
case CloudBrowseAction::show_browser:
|
|
services.show_browser();
|
|
return pp::foundation::Status::success();
|
|
}
|
|
|
|
return pp::foundation::Status::invalid_argument("unknown cloud browse action");
|
|
}
|
|
|
|
[[nodiscard]] inline pp::foundation::Status execute_cloud_download_selection_action(
|
|
CloudDownloadSelectionAction action,
|
|
CloudServices& services,
|
|
const CloudDownloadRequest& request)
|
|
{
|
|
switch (action) {
|
|
case CloudDownloadSelectionAction::wait_for_selection:
|
|
return pp::foundation::Status::success();
|
|
case CloudDownloadSelectionAction::start_download:
|
|
if (request.selected_file.empty()) {
|
|
return pp::foundation::Status::invalid_argument("cloud download requires a selected file");
|
|
}
|
|
services.start_download(request);
|
|
return pp::foundation::Status::success();
|
|
}
|
|
|
|
return pp::foundation::Status::invalid_argument("unknown cloud download selection action");
|
|
}
|
|
|
|
}
|