diff --git a/include/Helpers/StringHelpers.cpp b/include/Helpers/StringHelpers.cpp index 785d102..b4c72c9 100644 --- a/include/Helpers/StringHelpers.cpp +++ b/include/Helpers/StringHelpers.cpp @@ -1,6 +1,7 @@ #include "StringHelpers.hpp" #include #include +#include std::vector split_string_by_token(std::string str, std::string token) { // slightly modified from: https://stackoverflow.com/a/46943631 @@ -66,3 +67,13 @@ std::string read_file_to_string(const std::filesystem::path& filePath) { return toRet; } + +bool is_valid_http_url(const std::string& str) { + if(str.empty()) + return false; + + // Regex to check valid URL (from https://stackoverflow.com/a/3809435) + std::regex pattern(R"rawstr(https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*))rawstr"); + + return std::regex_match(str, pattern); +} diff --git a/include/Helpers/StringHelpers.hpp b/include/Helpers/StringHelpers.hpp index 1dd07d9..7eed591 100644 --- a/include/Helpers/StringHelpers.hpp +++ b/include/Helpers/StringHelpers.hpp @@ -11,3 +11,4 @@ uint8_t ascii_hex_char_to_number_no_checks(char asciiHex); std::string byte_vector_to_hex_str(const std::vector& byteVec); std::string read_file_to_string(const std::filesystem::path& filePath); void remove_whitespaces_from_str(std::string& str); +bool is_valid_http_url(const std::string& str); diff --git a/src/DrawingProgram/DrawingProgram.cpp b/src/DrawingProgram/DrawingProgram.cpp index ac27d69..040639a 100644 --- a/src/DrawingProgram/DrawingProgram.cpp +++ b/src/DrawingProgram/DrawingProgram.cpp @@ -19,6 +19,8 @@ #include #include "../World.hpp" #include "../MainProgram.hpp" +#include "Helpers/FileDownloader.hpp" +#include "Helpers/StringHelpers.hpp" #include "LassoSelectTool.hpp" #include #include @@ -362,6 +364,7 @@ void DrawingProgram::update() { check_delayed_update_timers(); check_updateable_components(); + update_downloading_dropped_files(); if(drawTool->get_type() == DrawingProgramToolType::ERASER) { EraserTool* eraserTool = static_cast(drawTool.get()); @@ -432,10 +435,59 @@ void DrawingProgram::drag_drop_update() { add_file_to_canvas_by_path(droppedItem.droppedData, droppedItem.pos, true); #endif } + else if(!droppedItem.isFile && is_valid_http_url(droppedItem.droppedData)) { + auto img(std::make_shared()); + img->coords = world.drawData.cam.c; + img->commit_update(*this); + uint64_t placement = components.client_list().size(); + auto objAdd = components.client_insert(placement, img); + img->client_send_place(*this); + add_undo_place_component(objAdd); + droppedDownloadingFiles.emplace_back(objAdd, world.main.window.size.cast(), FileDownloader::download_data_from_url(droppedItem.droppedData)); + Vector2f imDim = Vector2f{100.0f, 100.0f}; + img->d.p1 = droppedItem.pos - imDim; + img->d.p2 = droppedItem.pos + imDim; + img->d.imageID = {0, 0}; + } } } } +void DrawingProgram::update_downloading_dropped_files() { + std::erase_if(droppedDownloadingFiles, [&](auto& downFile) { + switch(downFile.downData->status) { + case FileDownloader::DownloadData::Status::SUCCESS: { + std::shared_ptr img = std::static_pointer_cast(downFile.comp->obj); + Vector2f dropPos = (img->d.p1 + img->d.p2) * 0.5f; + + ResourceData newResource; + newResource.data = std::make_shared(downFile.downData->str); + newResource.name = "downloaded file"; + ServerClientID imageID = world.rMan.add_resource(newResource); + + std::shared_ptr display = world.rMan.get_display_data(imageID); + Vector2f imTrueDim = display->get_dimensions(); + + float imWidth = imTrueDim.x() / (imTrueDim.x() + imTrueDim.y()); + float imHeight = imTrueDim.y() / (imTrueDim.x() + imTrueDim.y()); + Vector2f imDim = Vector2f{downFile.windowSizeWhenDropped.x() * imWidth, downFile.windowSizeWhenDropped.x() * imHeight} * display->get_dimension_scale(); + img->d.p1 = dropPos - imDim; + img->d.p2 = dropPos + imDim; + img->d.imageID = imageID; + img->commit_update(*this); + img->client_send_update(*this, true); + return true; + } + case FileDownloader::DownloadData::Status::FAILURE: + client_erase_set({downFile.comp}); + return true; + case FileDownloader::DownloadData::Status::IN_PROGRESS: + return false; + } + return false; + }); +} + void DrawingProgram::add_file_to_canvas_by_path(const std::string& filePath, Vector2f dropPos, bool addInSameThread) { if(addInSameThread) add_file_to_canvas_by_path_execute(filePath, dropPos); diff --git a/src/DrawingProgram/DrawingProgram.hpp b/src/DrawingProgram/DrawingProgram.hpp index 4fc1cd7..9d0b1c8 100644 --- a/src/DrawingProgram/DrawingProgram.hpp +++ b/src/DrawingProgram/DrawingProgram.hpp @@ -15,6 +15,7 @@ #include "DrawingProgramSelection.hpp" #include "../CollabList.hpp" #include "DrawingProgramToolBase.hpp" +#include class World; @@ -120,6 +121,15 @@ class DrawingProgram { std::unique_ptr drawTool; uint32_t nextID = 0; + + struct DroppedDownloadingFile { + CollabListType::ObjectInfoPtr comp; + Vector2f windowSizeWhenDropped; + std::shared_ptr downData; + }; + std::vector droppedDownloadingFiles; + + void update_downloading_dropped_files(); friend class EyeDropperTool; friend class RectDrawTool; diff --git a/src/main.cpp b/src/main.cpp index f0f4efe..3fe2eb3 100755 --- a/src/main.cpp +++ b/src/main.cpp @@ -695,7 +695,7 @@ SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) { break; case SDL_EVENT_DROP_TEXT: mS.m->input.droppedItems.emplace_back(InputManager::DroppedItem{ - true, + false, Vector2f{event->drop.x, event->drop.y}, event->drop.data });