From da49e8edfb0b6e2f1afb4c498c5bc680106de13b Mon Sep 17 00:00:00 2001 From: David Kocik Date: Mon, 28 Oct 2024 10:39:58 +0100 Subject: [PATCH] SPE-2535: Improvments of Printables events Missing include Printables event Require login Improved error page Prepare opening Printables to Connect upload dialog debug fix Another debug fix prevent reload on load request Load new url already in on_show Improved javascript notification --- resources/web/other_connection_failed.html | 28 ----- resources/web/other_error.html | 70 +++++++++++ src/slic3r/GUI/GUI_App.cpp | 5 + src/slic3r/GUI/GUI_App.hpp | 1 + src/slic3r/GUI/MainFrame.cpp | 7 +- src/slic3r/GUI/Plater.cpp | 12 ++ src/slic3r/GUI/Plater.hpp | 1 + src/slic3r/GUI/WebViewDialog.cpp | 25 ++++ src/slic3r/GUI/WebViewDialog.hpp | 9 ++ src/slic3r/GUI/WebViewPanel.cpp | 133 +++++++++++++-------- src/slic3r/GUI/WebViewPanel.hpp | 9 +- src/slic3r/GUI/format.hpp | 1 + 12 files changed, 218 insertions(+), 83 deletions(-) delete mode 100644 resources/web/other_connection_failed.html create mode 100644 resources/web/other_error.html diff --git a/resources/web/other_connection_failed.html b/resources/web/other_connection_failed.html deleted file mode 100644 index 3ea607b3be..0000000000 --- a/resources/web/other_connection_failed.html +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - Connection failed - - - -
-

Connection failed

-

Something went wrong.

- -
- - diff --git a/resources/web/other_error.html b/resources/web/other_error.html new file mode 100644 index 0000000000..24b29d72d2 --- /dev/null +++ b/resources/web/other_error.html @@ -0,0 +1,70 @@ + + + + + + Connect-Slicer integration + + + +
+
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+

Something went wrong.

+ +
+
+ + \ No newline at end of file diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index a938865bb9..a79d6dbc2f 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -4145,7 +4145,12 @@ void GUI_App::printables_slice_request(const std::string& download_url, const st } void GUI_App::printables_print_request(const std::string& download_url, const std::string& model_url) { + plater()->printables_to_connect_gcode(Utils::ServiceConfig::instance().printables_url() + model_url); +} +void GUI_App::printables_login_request() +{ + plater_->get_user_account()->do_login(); } void GUI_App::open_link_in_printables(const std::string& url) diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index cf3c30c287..a85c8a8480 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -439,6 +439,7 @@ public: 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 printables_login_request(); void open_link_in_printables(const std::string& url); private: bool on_init_inner(); diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index eca7401888..0f2bd93484 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -880,9 +880,12 @@ void MainFrame::show_printables_tab(const std::string& url) if (!m_printables_webview_added) { return; } - m_tabpanel->SetSelection(m_tabpanel->FindPage(m_printables_webview)); + // we have to set next url first, than show the tab + // printables_tab has to reload on show everytime + // so it is not possible load_url right after show m_printables_webview->set_load_default_url_on_next_error(true); - m_printables_webview->load_url_from_outside(url); + m_printables_webview->set_next_show_url(url); + m_tabpanel->SetSelection(m_tabpanel->FindPage(m_printables_webview)); } void MainFrame::add_printables_webview_tab() { diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 395f29dc8d..e22d7a260a 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -6017,6 +6017,18 @@ bool load_secret(const std::string& id, const std::string& opt, std::string& usr #endif // wxUSE_SECRETSTORE } } + + +void Plater::printables_to_connect_gcode(const std::string& url) +{ + { + PrintablesConnectUploadDialog dialog(this, url); + if (dialog.ShowModal() != wxID_OK) { + return; + } + } +} + void Plater::connect_gcode() { assert(p->user_account->is_logged()); diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index c492912d3a..e610e552d4 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -229,6 +229,7 @@ public: void send_gcode_inner(DynamicPrintConfig* physical_printer_config); void eject_drive(); void connect_gcode(); + void printables_to_connect_gcode(const std::string& url); std::string get_upload_filename(); void take_snapshot(const std::string &snapshot_name); diff --git a/src/slic3r/GUI/WebViewDialog.cpp b/src/slic3r/GUI/WebViewDialog.cpp index fe33241109..b77e298be2 100644 --- a/src/slic3r/GUI/WebViewDialog.cpp +++ b/src/slic3r/GUI/WebViewDialog.cpp @@ -630,6 +630,31 @@ void PrinterPickWebViewDialog::on_reload_event(const std::string& message_data) m_browser->LoadURL(m_default_url); } +PrintablesConnectUploadDialog::PrintablesConnectUploadDialog(wxWindow* parent, const std::string url) + : WebViewDialog(parent + , GUI::from_u8(url) + , _L("Choose a printer") + , wxSize(parent->GetClientSize().x / 4 * 3, parent->GetClientSize().y/ 5 * 4) + ,{"_prusaSlicer"} + , "connect_loading") +{ + SetMinSize(wxSize(std::max(parent->GetClientSize().x / 2, 100 * wxGetApp().em_unit()), std::max(parent->GetClientSize().y / 2, 70 * wxGetApp().em_unit()))); + Centre(); +} + +void PrintablesConnectUploadDialog::on_dpi_changed(const wxRect &suggested_rect) +{ + wxWindow *parent = GetParent(); + const wxSize &size = wxSize( + std::max(parent->GetClientSize().x / 2, 100 * wxGetApp().em_unit()), + std::max(parent->GetClientSize().y / 2, 70 * wxGetApp().em_unit()) + ); + SetMinSize(size); + Fit(); + Refresh(); +} + + LoginWebViewDialog::LoginWebViewDialog(wxWindow *parent, std::string &ret_val, const wxString& url, wxEvtHandler* evt_handler) : WebViewDialog(parent, url, _L("Log in dialog"), wxSize(50 * wxGetApp().em_unit(), 80 * wxGetApp().em_unit()), {}) diff --git a/src/slic3r/GUI/WebViewDialog.hpp b/src/slic3r/GUI/WebViewDialog.hpp index d9e890fc3f..78fdd35c74 100644 --- a/src/slic3r/GUI/WebViewDialog.hpp +++ b/src/slic3r/GUI/WebViewDialog.hpp @@ -109,6 +109,15 @@ private: std::string& m_ret_val; }; +class PrintablesConnectUploadDialog : public WebViewDialog +{ +public: + PrintablesConnectUploadDialog(wxWindow* parent, const std::string url); +protected: + void on_dpi_changed(const wxRect &suggested_rect) override; + +}; + class LoginWebViewDialog : public WebViewDialog { public: diff --git a/src/slic3r/GUI/WebViewPanel.cpp b/src/slic3r/GUI/WebViewPanel.cpp index 9ec5767ce4..acb0fcc67b 100644 --- a/src/slic3r/GUI/WebViewPanel.cpp +++ b/src/slic3r/GUI/WebViewPanel.cpp @@ -8,10 +8,10 @@ #include "slic3r/GUI/format.hpp" #include "slic3r/GUI/WebView.hpp" #include "slic3r/GUI/WebViewPlatformUtils.hpp" -#include "slic3r/Utils/ServiceConfig.hpp" - #include "slic3r/GUI/MsgDialog.hpp" #include "slic3r/GUI/Field.hpp" +#include "libslic3r/AppConfig.hpp" +#include "libslic3r/Config.hpp" #include // IWYU pragma: keep @@ -207,7 +207,7 @@ void WebViewPanel::on_idle(wxIdleEvent& WXUNUSED(evt)) m_load_error_page = false; if (m_load_default_url_on_next_error) { m_load_default_url_on_next_error = false; - load_url(m_default_url); + load_default_url(); } else { load_url(GUI::format_wxstr("file://%1%/web/%2%.html", boost::filesystem::path(resources_dir()).generic_string(), m_error_html)); } @@ -781,7 +781,7 @@ void ConnectWebViewPanel::on_connect_action_print(const std::string& message_dat } PrinterWebViewPanel::PrinterWebViewPanel(wxWindow* parent, const wxString& default_url) - : WebViewPanel(parent, default_url, {"ExternalApp"}, "other_loading_reload", "other_connection_failed") + : WebViewPanel(parent, default_url, {"ExternalApp"}, "other_loading_reload", "other_error") { if (!m_browser) return; @@ -857,7 +857,7 @@ void PrinterWebViewPanel::sys_color_changed() PrintablesWebViewPanel::PrintablesWebViewPanel(wxWindow* parent) - : WebViewPanel(parent, GUI::from_u8(Utils::ServiceConfig::instance().printables_url()), { "ExternalApp" }, "other_loading_reload", "other_connection_failed") + : WebViewPanel(parent, GUI::from_u8(Utils::ServiceConfig::instance().printables_url()), { "ExternalApp" }, "other_loading_reload", "other_error") { m_browser->Bind(wxEVT_WEBVIEW_LOADED, &PrintablesWebViewPanel::on_loaded, this); @@ -908,27 +908,6 @@ void PrintablesWebViewPanel::on_navigation_request(wxWebViewEvent &evt) } } -void PrintablesWebViewPanel::load_default_url() -{ - std::string actual_default_url = get_url_lang_theme(Utils::ServiceConfig::instance().printables_url() + "/homepage"); - const std::string access_token = wxGetApp().plater()->get_user_account()->get_access_token(); - - // in case of opening printables logged out - delete cookies and localstorage to get rid of last login - if (access_token.empty()) { - delete_cookies(m_browser, Utils::ServiceConfig::instance().printables_url()); - m_browser->AddUserScript("localStorage.clear();"); - load_url(actual_default_url); - return; - } - // add token to first request -#ifdef _WIN32 - add_request_authorization(m_browser, m_default_url, access_token); - load_url(GUI::from_u8(actual_default_url)); -#else - load_request(m_browser, actual_default_url, access_token); -#endif -} - void PrintablesWebViewPanel::on_loaded(wxWebViewEvent& evt) { #ifdef _WIN32 @@ -1000,20 +979,20 @@ void PrintablesWebViewPanel::on_show(wxShowEvent& evt) return; } // in case login changed, resend login / logout - // DK: it seems to me, it is safer to do login / logout (where logout means requesting the page again) + // DK1: it seems to me, it is safer to do login / logout (where logout means requesting the page again) // on every show of panel, // than to keep information if we have printables page in same state as slicer in terms of login // But im afraid it will be concidered not pretty... const std::string access_token = wxGetApp().plater()->get_user_account()->get_access_token(); if (access_token.empty()) { - logout(); + logout(m_next_show_url); } else { - login(access_token); + login(access_token, m_next_show_url); } - + m_next_show_url.clear(); } -void PrintablesWebViewPanel::logout() +void PrintablesWebViewPanel::logout(const std::string& override_url/* = std::string()*/) { if (!m_shown) { return; @@ -1021,15 +1000,18 @@ void PrintablesWebViewPanel::logout() delete_cookies(m_browser, Utils::ServiceConfig::instance().printables_url()); m_browser->RunScript("localStorage.clear();"); + std::string next_url = override_url.empty() + ? get_url_lang_theme(m_browser->GetCurrentURL()) + : get_url_lang_theme(from_u8(override_url)); #ifdef _WIN32 - load_url(GUI::from_u8(get_url_lang_theme(m_browser->GetCurrentURL()))); + load_url(GUI::from_u8(next_url)); #else // We cannot do simple reload here, it would keep the access token in the header - load_request(m_browser, get_url_lang_theme(m_browser->GetCurrentURL()), std::string()); + load_request(m_browser, next_url, std::string()); #endif // } -void PrintablesWebViewPanel::login(const std::string& access_token) +void PrintablesWebViewPanel::login(const std::string& access_token, const std::string& override_url/* = std::string()*/) { if (!m_shown) { return; @@ -1048,8 +1030,34 @@ void PrintablesWebViewPanel::login(const std::string& access_token) , access_token); run_script(script); - run_script("window.location.reload();"); + if ( override_url.empty()) { + run_script("window.location.reload();"); + } else { + load_url(GUI::from_u8(get_url_lang_theme(from_u8(override_url)))); + } } + +void PrintablesWebViewPanel::load_default_url() +{ + std::string actual_default_url = get_url_lang_theme(from_u8(Utils::ServiceConfig::instance().printables_url() + "/homepage")); + const std::string access_token = wxGetApp().plater()->get_user_account()->get_access_token(); + + // in case of opening printables logged out - delete cookies and localstorage to get rid of last login + if (access_token.empty()) { + delete_cookies(m_browser, Utils::ServiceConfig::instance().printables_url()); + m_browser->AddUserScript("localStorage.clear();"); + load_url(actual_default_url); + return; + } + // add token to first request +#ifdef _WIN32 + add_request_authorization(m_browser, m_default_url, access_token); + load_url(GUI::from_u8(actual_default_url)); +#else + load_request(m_browser, actual_default_url, access_token); +#endif +} + void PrintablesWebViewPanel::send_refreshed_token(const std::string& access_token) { if (m_load_default_url) { @@ -1071,11 +1079,6 @@ 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(); @@ -1106,11 +1109,31 @@ void PrintablesWebViewPanel::on_reload_event(const std::string& message_data) void PrintablesWebViewPanel::on_printables_event_print_gcode(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("url"); url) { + download_url = *url; + } + if (const auto url = ptree.get_optional("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_print_request(download_url, model_url); } 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" } + BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << " " << message_data; + // { "event": "printGcode", "url": "https://media.printables.com/somesecure.gcode", "modelUrl": "https://www.printables.com/model/123" } std::string download_url; std::string model_url; try { @@ -1130,11 +1153,11 @@ void PrintablesWebViewPanel::on_printables_event_download_file(const std::string 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); + 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; + BOOST_LOG_TRIVIAL(debug) << __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; @@ -1158,12 +1181,14 @@ void PrintablesWebViewPanel::on_printables_event_slice_file(const std::string& m void PrintablesWebViewPanel::on_printables_event_required_login(const std::string& message_data) { - BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << " " << message_data; + BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << " " << message_data; + wxGetApp().printables_login_request(); } void PrintablesWebViewPanel::show_download_notification(const std::string& filename) { - std::string message = GUI::format(_u8L("Downloading %1%"),filename); + std::string message_filename = GUI::format(_u8L("Downloading %1%"),filename); + std::string message_dest = GUI::format(_u8L("To %1%"), escape_string_cstyle(wxGetApp().app_config->get("url_downloader_dest"))); std::string script = GUI::format(R"( // Inject custom CSS var style = document.createElement('style'); @@ -1185,10 +1210,19 @@ void PrintablesWebViewPanel::show_download_notification(const std::string& filen 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-width: 350px; + max-width: 350px; min-height: 50px; } - + .notification-popup div { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + padding-right: 20px; /* Add padding to make text truncate earlier */ + } + .notification-popup b { + color: #ffa500; + } .notification-popup a:hover { text-decoration: underline; /* Underline on hover */ } @@ -1223,6 +1257,7 @@ void PrintablesWebViewPanel::show_download_notification(const std::string& filen notifDiv.innerHTML = `
PrusaSlicer: %1% +
%2%
`; notifDiv.className = 'notification-popup'; @@ -1239,7 +1274,7 @@ void PrintablesWebViewPanel::show_download_notification(const std::string& filen } appendNotification(); -)", message); +)", message_filename, message_dest); run_script(script); } diff --git a/src/slic3r/GUI/WebViewPanel.hpp b/src/slic3r/GUI/WebViewPanel.hpp index be9e181f22..d5d276cb62 100644 --- a/src/slic3r/GUI/WebViewPanel.hpp +++ b/src/slic3r/GUI/WebViewPanel.hpp @@ -8,6 +8,7 @@ #include "GUI_Utils.hpp" #include "UserAccountSession.hpp" #include "ConnectRequestHandler.hpp" +#include "slic3r/Utils/ServiceConfig.hpp" #ifdef DEBUG_URL_PANEL #include @@ -179,11 +180,11 @@ public: void on_script_message(wxWebViewEvent& evt) override; void sys_color_changed() override; - void logout(); - void login(const std::string& access_token); + void logout(const std::string& override_url = std::string()); + void login(const std::string& access_token, const std::string& override_url = std::string()); void send_refreshed_token(const std::string& access_token); void send_will_refresh(); - void load_url_from_outside(const std::string& url); + void set_next_show_url(const std::string& url) {m_next_show_url = Utils::ServiceConfig::instance().printables_url() + url; } private: void handle_message(const std::string& message); void on_printables_event_access_token_expired(const std::string& message_data); @@ -197,7 +198,7 @@ private: void show_download_notification(const std::string& filename); std::map> m_events; - + std::string m_next_show_url; /* Eventy Slicer -> Printables accessTokenWillChange diff --git a/src/slic3r/GUI/format.hpp b/src/slic3r/GUI/format.hpp index e80017174d..9c80907ee0 100644 --- a/src/slic3r/GUI/format.hpp +++ b/src/slic3r/GUI/format.hpp @@ -12,6 +12,7 @@ // This wrapper also manages implicit conversion from wxString to UTF8 and format_wxstr() variants are provided to format into wxString. #include +#include namespace Slic3r::internal::format { // Wrapper around wxScopedCharBuffer to indicate that the content is UTF8 formatted.