mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-16 16:05:54 +08:00
SPE-2535: Handling Printables events
Fix of loading url and deleting cookies Handling Printables events: download and slice Link from notification to Printables tab Webview download notification cleanup No reload button on loading screen
This commit is contained in:
parent
2d41c29505
commit
7ffa854ec2
@ -71,7 +71,7 @@
|
||||
</g>
|
||||
</svg>
|
||||
</p>
|
||||
<button style="margin-top: 20px; padding: 10px 20px; font-size: 16px;" onclick="window._prusaSlicer.postMessage(JSON.stringify({ action: 'RELOAD_HOME_PAGE' }))">Reload</button>
|
||||
<!-- <button style="margin-top: 20px; padding: 10px 20px; font-size: 16px;" onclick="window._prusaSlicer.postMessage(JSON.stringify({ action: 'RELOAD_HOME_PAGE' }))">Reload</button> -->
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
@ -62,7 +62,7 @@
|
||||
</g>
|
||||
</svg>
|
||||
</p>
|
||||
<button style="margin-top: 20px; padding: 10px 20px; font-size: 16px;" onclick="window.ExternalApp.postMessage(JSON.stringify({ event: 'reloadHomePage' }))">Reload</button>
|
||||
<!-- <button style="margin-top: 20px; padding: 10px 20px; font-size: 16px;" onclick="window.ExternalApp.postMessage(JSON.stringify({ event: 'reloadHomePage' }))">Reload</button> -->
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
@ -125,7 +125,7 @@ void ConfigWizardWebViewPage::on_navigation_request(wxWebViewEvent &evt)
|
||||
{
|
||||
wxString url = evt.GetURL();
|
||||
if (url.starts_with(L"prusaslicer")) {
|
||||
delete_cookies(m_browser, "https://account.prusa3d.com");
|
||||
delete_cookies(m_browser, Utils::ServiceConfig::instance().account_url());
|
||||
delete_cookies(m_browser, "https://accounts.google.com");
|
||||
delete_cookies(m_browser, "https://appleid.apple.com");
|
||||
delete_cookies(m_browser, "https://facebook.com");
|
||||
|
@ -90,14 +90,14 @@ std::string unescape_url(const std::string& unescaped)
|
||||
}
|
||||
}
|
||||
|
||||
Download::Download(int ID, std::string url, wxEvtHandler* evt_handler, const boost::filesystem::path& dest_folder)
|
||||
Download::Download(int ID, std::string url, wxEvtHandler* evt_handler, const boost::filesystem::path& dest_folder, bool load_after)
|
||||
: m_id(ID)
|
||||
, m_filename(filename_from_url(url))
|
||||
, m_dest_folder(dest_folder)
|
||||
{
|
||||
assert(boost::filesystem::is_directory(dest_folder));
|
||||
m_final_path = dest_folder / m_filename;
|
||||
m_file_get = std::make_shared<FileGet>(ID, std::move(url), m_filename, evt_handler, dest_folder);
|
||||
m_file_get = std::make_shared<FileGet>(ID, std::move(url), m_filename, evt_handler, dest_folder, load_after);
|
||||
}
|
||||
|
||||
void Download::start()
|
||||
@ -132,11 +132,6 @@ void Download::resume()
|
||||
Downloader::Downloader()
|
||||
: wxEvtHandler()
|
||||
{
|
||||
//Bind(EVT_DWNLDR_FILE_COMPLETE, [](const wxCommandEvent& evt) {});
|
||||
//Bind(EVT_DWNLDR_FILE_PROGRESS, [](const wxCommandEvent& evt) {});
|
||||
//Bind(EVT_DWNLDR_FILE_ERROR, [](const wxCommandEvent& evt) {});
|
||||
//Bind(EVT_DWNLDR_FILE_NAME_CHANGE, [](const wxCommandEvent& evt) {});
|
||||
|
||||
Bind(EVT_DWNLDR_FILE_COMPLETE, &Downloader::on_complete, this);
|
||||
Bind(EVT_DWNLDR_FILE_PROGRESS, &Downloader::on_progress, this);
|
||||
Bind(EVT_DWNLDR_FILE_ERROR, &Downloader::on_error, this);
|
||||
@ -169,14 +164,38 @@ void Downloader::start_download(const std::string& full_url)
|
||||
return;
|
||||
}
|
||||
|
||||
std::string text(escaped_url);
|
||||
m_downloads.emplace_back(std::make_unique<Download>(id, std::move(escaped_url), this, m_dest_folder));
|
||||
m_downloads.emplace_back(std::make_unique<Download>(id, std::move(escaped_url), this, m_dest_folder, true));
|
||||
NotificationManager* ntf_mngr = wxGetApp().notification_manager();
|
||||
ntf_mngr->push_download_URL_progress_notification(id, m_downloads.back()->get_filename(), std::bind(&Downloader::user_action_callback, this, std::placeholders::_1, std::placeholders::_2));
|
||||
m_downloads.back()->start();
|
||||
BOOST_LOG_TRIVIAL(debug) << "started download";
|
||||
}
|
||||
|
||||
void Downloader::start_download_printables(const std::string& url, bool load_after, const std::string& printables_url, GUI_App* app)
|
||||
{
|
||||
assert(m_initialized);
|
||||
|
||||
size_t id = get_next_id();
|
||||
|
||||
if (!boost::starts_with(url, "https://") || !FileGet::is_subdomain(url, "printables.com")) {
|
||||
std::string msg = format(_L("Download won't start. Download URL doesn't point to https://printables.com : %1%"), url);
|
||||
BOOST_LOG_TRIVIAL(error) << msg;
|
||||
NotificationManager* ntf_mngr = wxGetApp().notification_manager();
|
||||
ntf_mngr->push_notification(NotificationType::CustomNotification, NotificationManager::NotificationLevel::RegularNotificationLevel, msg);
|
||||
return;
|
||||
}
|
||||
|
||||
m_downloads.emplace_back(std::make_unique<Download>(id, url, this, m_dest_folder, load_after));
|
||||
NotificationManager* ntf_mngr = wxGetApp().notification_manager();
|
||||
ntf_mngr->push_download_URL_progress_notification_with_printables_link( id
|
||||
, m_downloads.back()->get_filename()
|
||||
, printables_url
|
||||
, std::bind(&Downloader::user_action_callback, this, std::placeholders::_1, std::placeholders::_2)
|
||||
, std::bind(&GUI_App::open_link_in_printables, app, std::placeholders::_1)
|
||||
);
|
||||
m_downloads.back()->start();
|
||||
}
|
||||
|
||||
void Downloader::on_progress(wxCommandEvent& event)
|
||||
{
|
||||
size_t id = event.GetInt();
|
||||
@ -195,14 +214,14 @@ void Downloader::on_error(wxCommandEvent& event)
|
||||
ntf_mngr->set_download_URL_error(id, into_u8(event.GetString()));
|
||||
show_error(nullptr, format_wxstr(L"%1%\n%2%", _L("The download has failed") + ":", event.GetString()));
|
||||
}
|
||||
void Downloader::on_complete(wxCommandEvent& event)
|
||||
void Downloader::on_complete(Event<DownloadEventData>& event)
|
||||
{
|
||||
// TODO: is this always true? :
|
||||
// here we open the file itself, notification should get 1.f progress from on progress.
|
||||
set_download_state(event.GetInt(), DownloadState::DownloadDone);
|
||||
set_download_state(event.data.id, DownloadState::DownloadDone);
|
||||
wxArrayString paths;
|
||||
paths.Add(event.GetString());
|
||||
wxGetApp().plater()->load_files(paths);
|
||||
paths.Add(event.data.path);
|
||||
if (event.data.load_after)
|
||||
wxGetApp().plater()->load_files(paths);
|
||||
}
|
||||
bool Downloader::user_action_callback(DownloaderUserAction action, int id)
|
||||
{
|
||||
|
@ -13,6 +13,7 @@ namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
class NotificationManager;
|
||||
class GUI_App;
|
||||
|
||||
enum DownloadState
|
||||
{
|
||||
@ -35,7 +36,7 @@ enum DownloaderUserAction
|
||||
|
||||
class Download {
|
||||
public:
|
||||
Download(int ID, std::string url, wxEvtHandler* evt_handler, const boost::filesystem::path& dest_folder);
|
||||
Download(int ID, std::string url, wxEvtHandler* evt_handler, const boost::filesystem::path& dest_folder, bool load_after);
|
||||
void start();
|
||||
void cancel();
|
||||
void pause();
|
||||
@ -67,6 +68,8 @@ public:
|
||||
m_initialized = true;
|
||||
}
|
||||
void start_download(const std::string& full_url);
|
||||
|
||||
void start_download_printables(const std::string& url, bool load_after, const std::string& printables_url, GUI_App* app);
|
||||
// cancel = false -> just pause
|
||||
bool user_action_callback(DownloaderUserAction action, int id);
|
||||
private:
|
||||
@ -80,7 +83,7 @@ private:
|
||||
|
||||
void on_progress(wxCommandEvent& event);
|
||||
void on_error(wxCommandEvent& event);
|
||||
void on_complete(wxCommandEvent& event);
|
||||
void on_complete(Event<DownloadEventData>& event);
|
||||
void on_name_change(wxCommandEvent& event);
|
||||
void on_paused(wxCommandEvent& event);
|
||||
void on_canceled(wxCommandEvent& event);
|
||||
|
@ -71,7 +71,7 @@ unsigned get_current_pid()
|
||||
}
|
||||
|
||||
// int = DOWNLOAD ID; string = file path
|
||||
wxDEFINE_EVENT(EVT_DWNLDR_FILE_COMPLETE, wxCommandEvent);
|
||||
wxDEFINE_EVENT(EVT_DWNLDR_FILE_COMPLETE, Event<DownloadEventData>);
|
||||
// int = DOWNLOAD ID; string = error msg
|
||||
wxDEFINE_EVENT(EVT_DWNLDR_FILE_ERROR, wxCommandEvent);
|
||||
// int = DOWNLOAD ID; string = progress percent
|
||||
@ -97,17 +97,19 @@ struct FileGet::priv
|
||||
std::atomic_bool m_stopped { false }; // either canceled or paused - download is not running
|
||||
size_t m_written { 0 };
|
||||
size_t m_absolute_size { 0 };
|
||||
priv(int ID, std::string&& url, const std::string& filename, wxEvtHandler* evt_handler, const boost::filesystem::path& dest_folder);
|
||||
bool m_load_after;
|
||||
priv(int ID, std::string&& url, const std::string& filename, wxEvtHandler* evt_handler, const boost::filesystem::path& dest_folder, bool load_after);
|
||||
|
||||
void get_perform();
|
||||
};
|
||||
|
||||
FileGet::priv::priv(int ID, std::string&& url, const std::string& filename, wxEvtHandler* evt_handler, const boost::filesystem::path& dest_folder)
|
||||
FileGet::priv::priv(int ID, std::string&& url, const std::string& filename, wxEvtHandler* evt_handler, const boost::filesystem::path& dest_folder, bool load_after)
|
||||
: m_id(ID)
|
||||
, m_url(std::move(url))
|
||||
, m_filename(filename)
|
||||
, m_evt_handler(evt_handler)
|
||||
, m_dest_folder(dest_folder)
|
||||
, m_load_after(load_after)
|
||||
{
|
||||
}
|
||||
|
||||
@ -264,23 +266,8 @@ void FileGet::priv::get_perform()
|
||||
m_evt_handler->QueueEvent(evt);
|
||||
})
|
||||
.on_complete([&](std::string body, unsigned /* http_status */) {
|
||||
|
||||
// TODO: perform a body size check
|
||||
//
|
||||
//size_t body_size = body.size();
|
||||
//if (body_size != expected_size) {
|
||||
// return;
|
||||
//}
|
||||
try
|
||||
{
|
||||
/*
|
||||
if (m_written < body.size())
|
||||
{
|
||||
// this code should never be entered. As there should be on_progress call after last bit downloaded.
|
||||
std::string part_for_write = body.substr(m_written);
|
||||
fwrite(part_for_write.c_str(), 1, part_for_write.size(), file);
|
||||
}
|
||||
*/
|
||||
fclose(file);
|
||||
boost::filesystem::rename(m_tmp_path, dest_path);
|
||||
}
|
||||
@ -294,18 +281,15 @@ void FileGet::priv::get_perform()
|
||||
m_evt_handler->QueueEvent(evt);
|
||||
return;
|
||||
}
|
||||
|
||||
wxCommandEvent* evt = new wxCommandEvent(EVT_DWNLDR_FILE_COMPLETE);
|
||||
evt->SetString(dest_path.wstring());
|
||||
evt->SetInt(m_id);
|
||||
m_evt_handler->QueueEvent(evt);
|
||||
DownloadEventData event_data = {m_id, dest_path.wstring(), m_load_after};
|
||||
wxQueueEvent(m_evt_handler, new Event<DownloadEventData>(EVT_DWNLDR_FILE_COMPLETE, event_data));
|
||||
})
|
||||
.perform_sync();
|
||||
|
||||
}
|
||||
|
||||
FileGet::FileGet(int ID, std::string url, const std::string& filename, wxEvtHandler* evt_handler, const boost::filesystem::path& dest_folder)
|
||||
: p(new priv(ID, std::move(url), filename, evt_handler, dest_folder))
|
||||
FileGet::FileGet(int ID, std::string url, const std::string& filename, wxEvtHandler* evt_handler, const boost::filesystem::path& dest_folder, bool load_after)
|
||||
: p(new priv(ID, std::move(url), filename, evt_handler, dest_folder, load_after))
|
||||
{}
|
||||
|
||||
FileGet::FileGet(FileGet&& other) : p(std::move(other.p)) {}
|
||||
|
@ -5,6 +5,8 @@
|
||||
#ifndef slic3r_DownloaderFileGet_hpp_
|
||||
#define slic3r_DownloaderFileGet_hpp_
|
||||
|
||||
#include "Event.hpp"
|
||||
|
||||
#include "../Utils/Http.hpp"
|
||||
|
||||
#include <memory>
|
||||
@ -19,7 +21,7 @@ class FileGet : public std::enable_shared_from_this<FileGet> {
|
||||
private:
|
||||
struct priv;
|
||||
public:
|
||||
FileGet(int ID, std::string url, const std::string& filename, wxEvtHandler* evt_handler,const boost::filesystem::path& dest_folder);
|
||||
FileGet(int ID, std::string url, const std::string& filename, wxEvtHandler* evt_handler,const boost::filesystem::path& dest_folder, bool load_after);
|
||||
FileGet(FileGet&& other);
|
||||
~FileGet();
|
||||
|
||||
@ -27,12 +29,18 @@ public:
|
||||
void cancel();
|
||||
void pause();
|
||||
void resume();
|
||||
static bool is_subdomain(const std::string& url, const std::string& domain);
|
||||
static bool is_subdomain(const std::string& url, const std::string& domain);
|
||||
private:
|
||||
std::unique_ptr<priv> p;
|
||||
};
|
||||
struct DownloadEventData
|
||||
{
|
||||
int id;
|
||||
wxString path;
|
||||
bool load_after;
|
||||
};
|
||||
// int = DOWNLOAD ID; string = file path
|
||||
wxDECLARE_EVENT(EVT_DWNLDR_FILE_COMPLETE, wxCommandEvent);
|
||||
wxDECLARE_EVENT(EVT_DWNLDR_FILE_COMPLETE, Event<DownloadEventData>);
|
||||
// int = DOWNLOAD ID; string = error msg
|
||||
wxDECLARE_EVENT(EVT_DWNLDR_FILE_PROGRESS, wxCommandEvent);
|
||||
// int = DOWNLOAD ID; string = progress percent
|
||||
|
@ -4112,13 +4112,46 @@ void GUI_App::show_printer_webview_tab()
|
||||
mainframe->show_printer_webview_tab(preset_bundle->physical_printers.get_selected_printer_config());
|
||||
}
|
||||
|
||||
void GUI_App::printables_request(const std::string& url)
|
||||
|
||||
void GUI_App::printables_download_request(const std::string& download_url, const std::string& model_url)
|
||||
{
|
||||
//this->mainframe->select_tab(size_t(0));
|
||||
|
||||
//lets always init so if the download dest folder was changed, new dest is used
|
||||
boost::filesystem::path dest_folder(app_config->get("url_downloader_dest"));
|
||||
if (dest_folder.empty() || !boost::filesystem::is_directory(dest_folder)) {
|
||||
std::string msg = _u8L("Could not start URL download. Destination folder is not set. Please choose destination folder in Configuration Wizard.");
|
||||
BOOST_LOG_TRIVIAL(error) << msg;
|
||||
show_error(nullptr, msg);
|
||||
return;
|
||||
}
|
||||
m_downloader->init(dest_folder);
|
||||
m_downloader->start_download_printables(download_url, false, model_url, this);
|
||||
}
|
||||
void GUI_App::printables_slice_request(const std::string& download_url, const std::string& model_url)
|
||||
{
|
||||
this->mainframe->select_tab(size_t(0));
|
||||
start_download(url);
|
||||
|
||||
//lets always init so if the download dest folder was changed, new dest is used
|
||||
boost::filesystem::path dest_folder(app_config->get("url_downloader_dest"));
|
||||
if (dest_folder.empty() || !boost::filesystem::is_directory(dest_folder)) {
|
||||
std::string msg = _u8L("Could not start URL download. Destination folder is not set. Please choose destination folder in Configuration Wizard.");
|
||||
BOOST_LOG_TRIVIAL(error) << msg;
|
||||
show_error(nullptr, msg);
|
||||
return;
|
||||
}
|
||||
m_downloader->init(dest_folder);
|
||||
m_downloader->start_download_printables(download_url, true, model_url, this);
|
||||
}
|
||||
void GUI_App::printables_print_request(const std::string& download_url, const std::string& model_url)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
void GUI_App::open_link_in_printables(const std::string& url)
|
||||
{
|
||||
mainframe->show_printables_tab(url);
|
||||
}
|
||||
|
||||
bool LogGui::ignorred_message(const wxString& msg)
|
||||
{
|
||||
|
@ -436,7 +436,10 @@ public:
|
||||
void request_project_download(std::string project_id) {}
|
||||
void request_open_project(std::string project_id) {}
|
||||
void request_remove_project(std::string project_id) {}
|
||||
void printables_request(const std::string& url);
|
||||
void printables_download_request(const std::string& download_url, const std::string& model_url);
|
||||
void printables_slice_request(const std::string& download_url, const std::string& model_url);
|
||||
void printables_print_request(const std::string& download_url, const std::string& model_url);
|
||||
void open_link_in_printables(const std::string& url);
|
||||
private:
|
||||
bool on_init_inner();
|
||||
void init_app_config();
|
||||
|
@ -875,7 +875,15 @@ void MainFrame::show_connect_tab(const wxString& url)
|
||||
m_connect_webview->set_load_default_url_on_next_error(true);
|
||||
m_connect_webview->load_url(url);
|
||||
}
|
||||
|
||||
void MainFrame::show_printables_tab(const std::string& url)
|
||||
{
|
||||
if (!m_printables_webview_added) {
|
||||
return;
|
||||
}
|
||||
m_tabpanel->SetSelection(m_tabpanel->FindPage(m_printables_webview));
|
||||
m_printables_webview->set_load_default_url_on_next_error(true);
|
||||
m_printables_webview->load_url_from_outside(url);
|
||||
}
|
||||
void MainFrame::add_printables_webview_tab()
|
||||
{
|
||||
if (m_printables_webview_added) {
|
||||
@ -886,8 +894,7 @@ void MainFrame::add_printables_webview_tab()
|
||||
wxWindow* page = m_printables_webview;
|
||||
const wxString text(L"Printables");
|
||||
const std::string bmp_name = "";
|
||||
bool bSelect = false;
|
||||
m_tabpanel->InsertNewPage(n, page, text, bmp_name, bSelect);
|
||||
m_tabpanel->InsertNewPage(n, page, text, bmp_name, false);
|
||||
m_printables_webview->load_default_url_delayed();
|
||||
m_printables_webview_added = true;
|
||||
}
|
||||
|
@ -224,7 +224,8 @@ public:
|
||||
void on_account_will_refresh();
|
||||
void on_account_did_refresh(const std::string& token);
|
||||
void on_account_logout();
|
||||
void show_connect_tab(const wxString &url);
|
||||
void show_connect_tab(const wxString& url);
|
||||
void show_printables_tab(const std::string& url);
|
||||
|
||||
void add_printables_webview_tab();
|
||||
void remove_printables_webview_tab();
|
||||
|
@ -936,9 +936,8 @@ void NotificationManager::ProgressBarNotification::render_text(const float win_s
|
||||
render_cancel_button(win_size_x, win_size_y, win_pos_x, win_pos_y);
|
||||
render_bar(win_size_x, win_size_y, win_pos_x, win_pos_y);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void NotificationManager::ProgressBarNotification::render_bar(const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y)
|
||||
{
|
||||
ImVec4 orange_color = ImVec4(.99f, .313f, .0f, 1.0f);
|
||||
@ -1073,6 +1072,51 @@ void NotificationManager::ProgressBarWithCancelNotification::render_bar(const fl
|
||||
ImGuiPureWrap::text(text.c_str());
|
||||
}
|
||||
|
||||
//------URLDownloadWithPrintablesLinkNotification----------------
|
||||
void NotificationManager::URLDownloadWithPrintablesLinkNotification::init()
|
||||
{
|
||||
PopNotification::init();
|
||||
//m_lines_count++;
|
||||
if (m_endlines.empty()) {
|
||||
m_endlines.push_back(0);
|
||||
}
|
||||
|
||||
m_lines_count = 3;
|
||||
m_multiline = true;
|
||||
while (m_endlines.size() < 3)
|
||||
m_endlines.push_back(m_endlines.back());
|
||||
|
||||
if(m_state == EState::Shown)
|
||||
m_state = EState::NotFading;
|
||||
}
|
||||
bool NotificationManager::URLDownloadWithPrintablesLinkNotification::on_text_click()
|
||||
{
|
||||
m_hypertext_callback_override(m_hypertext);
|
||||
return false;
|
||||
}
|
||||
void NotificationManager::URLDownloadWithPrintablesLinkNotification::render_text(const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y)
|
||||
{
|
||||
assert(m_multiline);
|
||||
assert(m_text1.size() >= m_endlines[0] || m_text1.size() >= m_endlines[1]);
|
||||
if(m_endlines[0] > m_text1.size() || m_endlines[1] > m_text1.size())
|
||||
return;
|
||||
// 1 lines text (what doesn't fit, wont show), 1 line hypertext, 1 line bar
|
||||
ImGui::SetCursorPosX(m_left_indentation);
|
||||
ImGui::SetCursorPosY(m_line_height / 4);
|
||||
ImGuiPureWrap::text(m_text1.substr(0, m_endlines[0]).c_str());
|
||||
|
||||
ImGui::SetCursorPosX(m_left_indentation);
|
||||
ImGui::SetCursorPosY(m_line_height + m_line_height / 4);
|
||||
std::string line = _u8L("Open Printables project page");
|
||||
//ImGuiPureWrap::text(line.c_str());
|
||||
render_hypertext(m_left_indentation, m_line_height + m_line_height / 4, line);
|
||||
|
||||
if (m_has_cancel_button)
|
||||
render_cancel_button(win_size_x, win_size_y, win_pos_x, win_pos_y);
|
||||
render_bar(win_size_x, win_size_y, win_pos_x, win_pos_y);
|
||||
}
|
||||
|
||||
|
||||
//------URLDownloadNotification----------------
|
||||
|
||||
void NotificationManager::URLDownloadNotification::render_close_button(const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y)
|
||||
@ -2495,6 +2539,19 @@ void NotificationManager::push_download_URL_progress_notification(size_t id, con
|
||||
push_notification_data(std::make_unique<NotificationManager::URLDownloadNotification>(data, m_id_provider, m_evt_handler, id, user_action_callback), 0);
|
||||
}
|
||||
|
||||
void NotificationManager::push_download_URL_progress_notification_with_printables_link(size_t id, const std::string& text, const std::string& url, std::function<bool(DownloaderUserAction, int)> user_action_callback, std::function<void(std::string)> hypertext_callback)
|
||||
{
|
||||
// If already exists
|
||||
for (std::unique_ptr<PopNotification>& notification : m_pop_notifications) {
|
||||
if (notification->get_type() == NotificationType::URLDownload && dynamic_cast<URLDownloadNotification*>(notification.get())->get_download_id() == id) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
// push new one
|
||||
NotificationData data{ NotificationType::URLDownload, NotificationLevel::ProgressBarNotificationLevel, 30, _u8L("Download") + ": " + text, url };
|
||||
push_notification_data(std::make_unique<NotificationManager::URLDownloadWithPrintablesLinkNotification>(data, m_id_provider, m_evt_handler, id, user_action_callback, hypertext_callback), 0);
|
||||
}
|
||||
|
||||
void NotificationManager::set_download_URL_progress(size_t id, float percentage)
|
||||
{
|
||||
for (std::unique_ptr<PopNotification>& notification : m_pop_notifications) {
|
||||
|
@ -244,6 +244,7 @@ public:
|
||||
void set_download_progress_percentage(float percentage);
|
||||
// Download URL progress notif
|
||||
void push_download_URL_progress_notification(size_t id, const std::string& text, std::function<bool(DownloaderUserAction, int)> user_action_callback);
|
||||
void push_download_URL_progress_notification_with_printables_link(size_t id, const std::string& text, const std::string& url, std::function<bool(DownloaderUserAction, int)> user_action_callback, std::function<void(std::string)> hypertext_callback);
|
||||
void set_download_URL_progress(size_t id, float percentage);
|
||||
void set_download_URL_paused(size_t id);
|
||||
void set_download_URL_canceled(size_t id);
|
||||
@ -577,6 +578,22 @@ private:
|
||||
std::string m_error_message;
|
||||
};
|
||||
|
||||
class URLDownloadWithPrintablesLinkNotification : public URLDownloadNotification
|
||||
{
|
||||
public:
|
||||
URLDownloadWithPrintablesLinkNotification(const NotificationData& n, NotificationIDProvider& id_provider, wxEvtHandler* evt_handler, size_t download_id, std::function<bool(DownloaderUserAction, int)> user_action_callback, std::function<void(std::string)> hypertext_callback)
|
||||
: URLDownloadNotification(n, id_provider, evt_handler, download_id, user_action_callback)
|
||||
, m_hypertext_callback_override(hypertext_callback)
|
||||
{
|
||||
}
|
||||
protected:
|
||||
void render_text(const float win_size_x, const float win_size_y,
|
||||
const float win_pos_x, const float win_pos_y) override;
|
||||
void init() override;
|
||||
bool on_text_click() override;
|
||||
std::function<void(std::string)> m_hypertext_callback_override;
|
||||
};
|
||||
|
||||
class PrintHostUploadNotification : public ProgressBarNotification
|
||||
{
|
||||
public:
|
||||
|
@ -639,7 +639,7 @@ void LoginWebViewDialog::on_navigation_request(wxWebViewEvent &evt)
|
||||
{
|
||||
wxString url = evt.GetURL();
|
||||
if (url.starts_with(L"prusaslicer")) {
|
||||
delete_cookies(m_browser, "https://account.prusa3d.com");
|
||||
delete_cookies(m_browser, Utils::ServiceConfig::instance().account_url());
|
||||
delete_cookies(m_browser, "https://accounts.google.com");
|
||||
delete_cookies(m_browser, "https://appleid.apple.com");
|
||||
delete_cookies(m_browser, "https://facebook.com");
|
||||
|
@ -190,8 +190,7 @@ void WebViewPanel::on_show(wxShowEvent& evt)
|
||||
m_shown = evt.IsShown();
|
||||
if (evt.IsShown() && m_load_default_url) {
|
||||
m_load_default_url = false;
|
||||
//load_url(m_default_url);
|
||||
load_error_page();
|
||||
load_url(m_default_url);
|
||||
}
|
||||
}
|
||||
|
||||
@ -239,6 +238,8 @@ void WebViewPanel::on_back_button(wxCommandEvent& WXUNUSED(evt))
|
||||
{
|
||||
if (!m_browser)
|
||||
return;
|
||||
if (!m_browser->CanGoBack())
|
||||
return;
|
||||
m_browser->GoBack();
|
||||
}
|
||||
|
||||
@ -249,6 +250,8 @@ void WebViewPanel::on_forward_button(wxCommandEvent& WXUNUSED(evt))
|
||||
{
|
||||
if (!m_browser)
|
||||
return;
|
||||
if (!m_browser->CanGoForward())
|
||||
return;
|
||||
m_browser->GoForward();
|
||||
}
|
||||
|
||||
@ -469,7 +472,7 @@ case type: \
|
||||
WX_ERROR_CASE(wxWEBVIEW_NAV_ERR_OTHER);
|
||||
}
|
||||
|
||||
BOOST_LOG_TRIVIAL(error) << this <<" WebViewPanel error: " << category;
|
||||
BOOST_LOG_TRIVIAL(error) << this <<" WebViewPanel error: " << category << " url: " << evt.GetURL();
|
||||
load_error_page();
|
||||
#ifdef DEBUG_URL_PANEL
|
||||
m_info->ShowMessage(wxString("An error occurred loading ") + evt.GetURL() + "\n" +
|
||||
@ -857,9 +860,14 @@ PrintablesWebViewPanel::PrintablesWebViewPanel(wxWindow* parent)
|
||||
: WebViewPanel(parent, GUI::from_u8(Utils::ServiceConfig::instance().printables_url()), { "ExternalApp" }, "other_loading_reload", "other_connection_failed")
|
||||
{
|
||||
m_browser->Bind(wxEVT_WEBVIEW_LOADED, &PrintablesWebViewPanel::on_loaded, this);
|
||||
|
||||
m_events["accessTokenExpired"] = std::bind(&PrintablesWebViewPanel::on_printables_event_access_token_expired, this, std::placeholders::_1);
|
||||
m_events["printGcode"] = std::bind(&PrintablesWebViewPanel::on_printables_event_print_gcode, this, std::placeholders::_1);
|
||||
m_events["reloadHomePage"] = std::bind(&PrintablesWebViewPanel::on_reload_event, this, std::placeholders::_1);
|
||||
m_events["printGcode"] = std::bind(&PrintablesWebViewPanel::on_printables_event_print_gcode, this, std::placeholders::_1);
|
||||
m_events["downloadFile"] = std::bind(&PrintablesWebViewPanel::on_printables_event_download_file, this, std::placeholders::_1);
|
||||
m_events["sliceFile"] = std::bind(&PrintablesWebViewPanel::on_printables_event_slice_file, this, std::placeholders::_1);
|
||||
m_events["requiredLogin"] = std::bind(&PrintablesWebViewPanel::on_printables_event_required_login, this, std::placeholders::_1);
|
||||
|
||||
}
|
||||
|
||||
void PrintablesWebViewPanel::handle_message(const std::string& message)
|
||||
@ -888,50 +896,16 @@ void PrintablesWebViewPanel::handle_message(const std::string& message)
|
||||
m_events[event_string](message);
|
||||
}
|
||||
}
|
||||
void PrintablesWebViewPanel::on_printables_event_access_token_expired(const std::string& message_data)
|
||||
{
|
||||
// accessTokenExpired
|
||||
// Printables pozaduje refresh access tokenu, muze byt volano nekolikrat.Nechme na Mobilni aplikaci at zaridi to ze zareaguje jen jednou
|
||||
}
|
||||
void PrintablesWebViewPanel::on_printables_event_print_gcode(const std::string& message_data)
|
||||
{
|
||||
// printGcode
|
||||
// Uzivatel kliknul na tlacitko tisk u gcode. Dalsi posilane atributy jsou url, material, printer, nozzlediam
|
||||
}
|
||||
void PrintablesWebViewPanel::on_reload_event(const std::string& message_data)
|
||||
{
|
||||
load_default_url();
|
||||
}
|
||||
/*
|
||||
Eventy Slicer -> Printables
|
||||
accessTokenWillChange
|
||||
WebUI zavola event predtim nez udela refresh access tokenu proti Prusa Accountu na Printables to bude znamenat pozastaveni requestu Mobile app muze chtit udelat refresh i bez explicitni predchozi printables zadosti skrz accessTokenExpired event
|
||||
accessTokenChange
|
||||
window postMessage JSON stringify { event 'accessTokenChange' token 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVC' }
|
||||
volani po uspesne rotaci tokenu
|
||||
historyBack
|
||||
navigace zpet triggerovana z mobilni aplikace
|
||||
historyForward
|
||||
navigace vpred triggerovana z mobilni aplikace
|
||||
*/
|
||||
|
||||
void PrintablesWebViewPanel::on_navigation_request(wxWebViewEvent &evt)
|
||||
{
|
||||
const wxString url = evt.GetURL();
|
||||
// download with url
|
||||
if (url.StartsWith(L"prusaslicer")) {
|
||||
evt.Veto();
|
||||
wxGetApp().printables_request(into_u8(url));
|
||||
return;
|
||||
}
|
||||
if (url.StartsWith(m_default_url)) {
|
||||
m_reached_default_url = true;
|
||||
} else if (m_reached_default_url) {
|
||||
BOOST_LOG_TRIVIAL(info) << evt.GetURL() << " does not start with default url. Vetoing.";
|
||||
evt.Veto();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void PrintablesWebViewPanel::load_default_url()
|
||||
@ -1055,7 +1029,7 @@ void PrintablesWebViewPanel::logout()
|
||||
#endif //
|
||||
|
||||
}
|
||||
void PrintablesWebViewPanel::login(const std::string access_token)
|
||||
void PrintablesWebViewPanel::login(const std::string& access_token)
|
||||
{
|
||||
if (!m_shown) {
|
||||
return;
|
||||
@ -1076,7 +1050,7 @@ void PrintablesWebViewPanel::login(const std::string access_token)
|
||||
|
||||
run_script("window.location.reload();");
|
||||
}
|
||||
void PrintablesWebViewPanel::send_refreshed_token(const std::string access_token)
|
||||
void PrintablesWebViewPanel::send_refreshed_token(const std::string& access_token)
|
||||
{
|
||||
if (m_load_default_url) {
|
||||
return;
|
||||
@ -1097,6 +1071,11 @@ void PrintablesWebViewPanel::send_will_refresh()
|
||||
run_script(script);
|
||||
}
|
||||
|
||||
void PrintablesWebViewPanel::load_url_from_outside(const std::string& url)
|
||||
{
|
||||
load_url(from_u8(Utils::ServiceConfig::instance().printables_url() + url));
|
||||
}
|
||||
|
||||
void PrintablesWebViewPanel::on_script_message(wxWebViewEvent& evt)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(error) << "received message from Printables: " << evt.GetString();
|
||||
@ -1111,4 +1090,157 @@ void PrintablesWebViewPanel::sys_color_changed()
|
||||
WebViewPanel::sys_color_changed();
|
||||
}
|
||||
|
||||
void PrintablesWebViewPanel::on_printables_event_access_token_expired(const std::string& message_data)
|
||||
{
|
||||
// accessTokenExpired
|
||||
// Printables pozaduje refresh access tokenu, muze byt volano nekolikrat.Nechme na Mobilni aplikaci at zaridi to ze zareaguje jen jednou
|
||||
|
||||
// We do no react on this event now - Our Acount managment should know when to renew our tokens.
|
||||
}
|
||||
|
||||
void PrintablesWebViewPanel::on_reload_event(const std::string& message_data)
|
||||
{
|
||||
// Event from our error / loading html pages
|
||||
load_default_url();
|
||||
}
|
||||
void PrintablesWebViewPanel::on_printables_event_print_gcode(const std::string& message_data)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__<< " " << message_data;
|
||||
}
|
||||
void PrintablesWebViewPanel::on_printables_event_download_file(const std::string& message_data)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << " " << message_data;
|
||||
// { "event": "downloadFile", "url": "https://media.printables.com/somesecure.stl", "modelUrl": "https://www.printables.com/model/123" }
|
||||
std::string download_url;
|
||||
std::string model_url;
|
||||
try {
|
||||
std::stringstream ss(message_data);
|
||||
pt::ptree ptree;
|
||||
pt::read_json(ss, ptree);
|
||||
if (const auto url = ptree.get_optional<std::string>("url"); url) {
|
||||
download_url = *url;
|
||||
}
|
||||
if (const auto url = ptree.get_optional<std::string>("modelUrl"); url) {
|
||||
model_url = *url;
|
||||
}
|
||||
} catch (const std::exception &e) {
|
||||
BOOST_LOG_TRIVIAL(error) << "Could not parse printables message. " << e.what();
|
||||
return;
|
||||
}
|
||||
assert(!download_url.empty() && !model_url.empty());
|
||||
boost::filesystem::path url_path(download_url);
|
||||
show_download_notification(url_path.filename().string());
|
||||
wxGetApp().printables_download_request(download_url, model_url);
|
||||
}
|
||||
void PrintablesWebViewPanel::on_printables_event_slice_file(const std::string& message_data)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << " " << message_data;
|
||||
// { "event": "sliceFile", "url": "https://media.printables.com/somesecure.zip", "modelUrl": "https://www.printables.com/model/123" }
|
||||
std::string download_url;
|
||||
std::string model_url;
|
||||
try {
|
||||
std::stringstream ss(message_data);
|
||||
pt::ptree ptree;
|
||||
pt::read_json(ss, ptree);
|
||||
if (const auto url = ptree.get_optional<std::string>("url"); url) {
|
||||
download_url = *url;
|
||||
}
|
||||
if (const auto url = ptree.get_optional<std::string>("modelUrl"); url) {
|
||||
model_url = *url;
|
||||
}
|
||||
} catch (const std::exception &e) {
|
||||
BOOST_LOG_TRIVIAL(error) << "Could not parse printables message. " << e.what();
|
||||
return;
|
||||
}
|
||||
assert(!download_url.empty() && !model_url.empty());
|
||||
wxGetApp().printables_slice_request(download_url, model_url);
|
||||
}
|
||||
|
||||
void PrintablesWebViewPanel::on_printables_event_required_login(const std::string& message_data)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << " " << message_data;
|
||||
}
|
||||
|
||||
void PrintablesWebViewPanel::show_download_notification(const std::string& filename)
|
||||
{
|
||||
std::string message = GUI::format(_u8L("Downloading %1%"),filename);
|
||||
std::string script = GUI::format(R"(
|
||||
// Inject custom CSS
|
||||
var style = document.createElement('style');
|
||||
style.innerHTML = `
|
||||
body {
|
||||
/* Add your body styles here */
|
||||
}
|
||||
.notification-popup {
|
||||
position: fixed;
|
||||
right: 10px;
|
||||
bottom: 10px;
|
||||
background-color: #333333; /* Dark background */
|
||||
padding: 10px;
|
||||
border-radius: 6px; /* Slightly rounded corners */
|
||||
color: #ffffff; /* White text */
|
||||
font-family: Arial, sans-serif;
|
||||
font-size: 12px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.3); /* Add a subtle shadow */
|
||||
min-width: 350px; /* Ensure it has a minimum width */
|
||||
min-height: 50px;
|
||||
}
|
||||
|
||||
.notification-popup a:hover {
|
||||
text-decoration: underline; /* Underline on hover */
|
||||
}
|
||||
.notification-popup .close-button {
|
||||
display: inline-block;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border: 2px solid #ffa500; /* Orange border for the button */
|
||||
border-radius: 4px;
|
||||
text-align: center;
|
||||
font-size: 16px;
|
||||
line-height: 16px;
|
||||
cursor: pointer;
|
||||
padding-top: 1px;
|
||||
}
|
||||
.notification-popup .close-button:hover {
|
||||
background-color: #ffa500; /* Orange background on hover */
|
||||
color: #333333; /* Dark color for the "X" on hover */
|
||||
}
|
||||
.notification-popup .close-button:before {
|
||||
content: 'X';
|
||||
color: #ffa500; /* Orange "X" */
|
||||
font-weight: bold;
|
||||
}
|
||||
`;
|
||||
document.head.appendChild(style);
|
||||
|
||||
// Define the notification functions
|
||||
function appendNotification() {
|
||||
const body = document.getElementsByTagName('body')[0];
|
||||
const notifDiv = document.createElement('div');
|
||||
notifDiv.innerHTML = `
|
||||
<div>
|
||||
<b>PrusaSlicer: </b>%1%
|
||||
</div>
|
||||
`;
|
||||
notifDiv.className = 'notification-popup';
|
||||
notifDiv.id = 'slicer-notification';
|
||||
body.appendChild(notifDiv);
|
||||
|
||||
window.setTimeout(removeNotification, 5000);
|
||||
}
|
||||
|
||||
function removeNotification() {
|
||||
const notifDiv = document.getElementById('slicer-notification');
|
||||
if (notifDiv)
|
||||
notifDiv.remove();
|
||||
}
|
||||
|
||||
appendNotification();
|
||||
)", message);
|
||||
run_script(script);
|
||||
}
|
||||
|
||||
} // namespace slic3r::GUI
|
@ -180,20 +180,36 @@ public:
|
||||
void sys_color_changed() override;
|
||||
|
||||
void logout();
|
||||
void login(const std::string access_token);
|
||||
void send_refreshed_token(const std::string access_token);
|
||||
void login(const std::string& access_token);
|
||||
void send_refreshed_token(const std::string& access_token);
|
||||
void send_will_refresh();
|
||||
void load_url_from_outside(const std::string& url);
|
||||
private:
|
||||
void handle_message(const std::string& message);
|
||||
void on_printables_event_access_token_expired(const std::string& message_data);
|
||||
void on_printables_event_print_gcode(const std::string& message_data);
|
||||
void on_reload_event(const std::string& message_data);
|
||||
|
||||
void on_printables_event_print_gcode(const std::string& message_data);
|
||||
void on_printables_event_download_file(const std::string& message_data);
|
||||
void on_printables_event_slice_file(const std::string& message_data);
|
||||
void on_printables_event_required_login(const std::string& message_data);
|
||||
void load_default_url() override;
|
||||
std::string get_url_lang_theme(const wxString& url);
|
||||
void show_download_notification(const std::string& filename);
|
||||
|
||||
std::map<std::string, std::function<void(const std::string&)>> m_events;
|
||||
|
||||
/*
|
||||
Eventy Slicer -> Printables
|
||||
accessTokenWillChange
|
||||
WebUI zavola event predtim nez udela refresh access tokenu proti Prusa Accountu na Printables to bude znamenat pozastaveni requestu Mobile app muze chtit udelat refresh i bez explicitni predchozi printables zadosti skrz accessTokenExpired event
|
||||
accessTokenChange
|
||||
window postMessage JSON stringify { event 'accessTokenChange' token 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVC' }
|
||||
volani po uspesne rotaci tokenu
|
||||
historyBack
|
||||
navigace zpet triggerovana z mobilni aplikace
|
||||
historyForward
|
||||
navigace vpred triggerovana z mobilni aplikace
|
||||
*/
|
||||
};
|
||||
} // namespace Slic3r::GUI
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user