mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-07-30 15:42:02 +08:00
SPE-2564: Use scripts to add listener to read keyboard shortcuts for reloading webview on Mac.
Add listener for hyperlinks in Printables to be opened in external browser.
This commit is contained in:
parent
e1b0826df5
commit
882e291daa
@ -278,6 +278,13 @@ void WebViewPanel::on_loaded(wxWebViewEvent& evt)
|
||||
{
|
||||
if (evt.GetURL().IsEmpty())
|
||||
return;
|
||||
|
||||
if (evt.GetURL().StartsWith(m_default_url)) {
|
||||
define_css();
|
||||
} else {
|
||||
m_styles_defined = false;
|
||||
}
|
||||
|
||||
m_load_default_url_on_next_error = false;
|
||||
if (evt.GetURL().Find(GUI::format_wxstr("/web/%1%.html", m_loading_html)) != wxNOT_FOUND && m_load_default_url) {
|
||||
m_load_default_url = false;
|
||||
@ -554,10 +561,15 @@ void WebViewPanel::do_reload()
|
||||
{
|
||||
if (!m_browser) {
|
||||
return;
|
||||
}
|
||||
// IsBusy on Linux very often returns true due to loading about:blank after loading requested url.
|
||||
#ifndef __linux__
|
||||
if (m_browser->IsBusy()) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
const wxString current_url = m_browser->GetCurrentURL();
|
||||
if (current_url.StartsWith(m_default_url))
|
||||
{
|
||||
if (current_url.StartsWith(m_default_url)) {
|
||||
m_browser->Reload();
|
||||
return;
|
||||
}
|
||||
@ -569,6 +581,7 @@ void WebViewPanel::load_default_url()
|
||||
if (!m_browser || m_do_late_webview_create) {
|
||||
return;
|
||||
}
|
||||
m_styles_defined = false;
|
||||
load_url(m_default_url);
|
||||
}
|
||||
|
||||
@ -579,6 +592,64 @@ void WebViewPanel::sys_color_changed()
|
||||
#endif
|
||||
}
|
||||
|
||||
void WebViewPanel::define_css()
|
||||
{
|
||||
|
||||
if (m_styles_defined) {
|
||||
return;
|
||||
}
|
||||
m_styles_defined = true;
|
||||
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__;
|
||||
std::string script = R"(
|
||||
// loading overlay
|
||||
var style = document.createElement('style');
|
||||
style.innerHTML = `
|
||||
body {}
|
||||
.slic3r-loading-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: rgba(127 127 127 / 50%);
|
||||
z-index: 50;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.slic3r-loading-anim {
|
||||
width: 60px;
|
||||
aspect-ratio: 4;
|
||||
--_g: no-repeat radial-gradient(circle closest-side,#000 90%,#0000);
|
||||
background:
|
||||
var(--_g) 0% 50%,
|
||||
var(--_g) 50% 50%,
|
||||
var(--_g) 100% 50%;
|
||||
background-size: calc(100%/3) 100%;
|
||||
animation: slic3r-loading-anim 1s infinite linear;
|
||||
}
|
||||
@keyframes slic3r-loading-anim {
|
||||
33%{background-size:calc(100%/3) 0% ,calc(100%/3) 100%,calc(100%/3) 100%}
|
||||
50%{background-size:calc(100%/3) 100%,calc(100%/3) 0% ,calc(100%/3) 100%}
|
||||
66%{background-size:calc(100%/3) 100%,calc(100%/3) 100%,calc(100%/3) 0% }
|
||||
}
|
||||
|
||||
document.head.appendChild(style);
|
||||
)";
|
||||
#ifdef __APPLE__
|
||||
// WebView on Windows does read keyboard shortcuts
|
||||
// Thus doing f.e. Reload twice would make the oparation to fail
|
||||
script += R"(
|
||||
document.addEventListener('keydown', function (event) {
|
||||
if (event.key === 'F5' || (event.ctrlKey && event.key === 'r') || (event.metaKey && event.key === 'r')) {
|
||||
window.ExternalApp.postMessage(JSON.stringify({ event: 'reloadHomePage', fromKeyboard: 1}));
|
||||
}
|
||||
});
|
||||
)";
|
||||
#endif // !_WIN32
|
||||
run_script(script);
|
||||
}
|
||||
|
||||
ConnectWebViewPanel::ConnectWebViewPanel(wxWindow* parent)
|
||||
: WebViewPanel(parent, GUI::from_u8(Utils::ServiceConfig::instance().connect_url()), { "_prusaSlicer" }, "connect_loading", "connect_error", false)
|
||||
{
|
||||
@ -796,6 +867,12 @@ void ConnectWebViewPanel::on_navigation_request(wxWebViewEvent &evt)
|
||||
m_url->SetValue(evt.GetURL());
|
||||
#endif
|
||||
BOOST_LOG_TRIVIAL(debug) << "Navigation requested to: " << into_u8(evt.GetURL());
|
||||
|
||||
// we need to do this to redefine css when reload is hit
|
||||
if (evt.GetURL().StartsWith(m_default_url) && evt.GetURL() == m_browser->GetCurrentURL()) {
|
||||
m_styles_defined = false;
|
||||
}
|
||||
|
||||
if (evt.GetURL() == m_default_url) {
|
||||
m_reached_default_url = true;
|
||||
return;
|
||||
@ -828,7 +905,22 @@ void ConnectWebViewPanel::on_connect_action_error(const std::string &message_dat
|
||||
|
||||
void ConnectWebViewPanel::on_reload_event(const std::string& message_data)
|
||||
{
|
||||
load_default_url();
|
||||
// Event from our error page button or keyboard shortcut
|
||||
m_styles_defined = false;
|
||||
try {
|
||||
std::stringstream ss(message_data);
|
||||
pt::ptree ptree;
|
||||
pt::read_json(ss, ptree);
|
||||
if (const auto keyboard = ptree.get_optional<bool>("fromKeyboard"); keyboard && *keyboard) {
|
||||
do_reload();
|
||||
} else {
|
||||
// On error page do load of default url.
|
||||
load_default_url();
|
||||
}
|
||||
} catch (const std::exception &e) {
|
||||
BOOST_LOG_TRIVIAL(error) << "Could not parse printables message. " << e.what();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void ConnectWebViewPanel::logout()
|
||||
@ -885,10 +977,17 @@ PrinterWebViewPanel::PrinterWebViewPanel(wxWindow* parent, const wxString& defau
|
||||
void PrinterWebViewPanel::on_navigation_request(wxWebViewEvent &evt)
|
||||
{
|
||||
const wxString url = evt.GetURL();
|
||||
if (url.StartsWith(m_default_url) && !m_api_key_sent) {
|
||||
if (url.StartsWith(m_default_url)) {
|
||||
m_reached_default_url = true;
|
||||
if (!m_usr.empty() && !m_psk.empty()) {
|
||||
send_credentials();
|
||||
if (url == m_browser->GetCurrentURL()) {
|
||||
// we need to do this to redefine css when reload is hit
|
||||
m_styles_defined = false;
|
||||
}
|
||||
|
||||
if ( !m_api_key_sent) {
|
||||
if (!m_usr.empty() && !m_psk.empty()) {
|
||||
send_credentials();
|
||||
}
|
||||
}
|
||||
} else if (m_reached_default_url && evt.GetURL().Find(GUI::format_wxstr("/web/%1%.html", m_loading_html)) != wxNOT_FOUND) {
|
||||
// Do not allow back button to loading screen
|
||||
@ -900,6 +999,13 @@ void PrinterWebViewPanel::on_loaded(wxWebViewEvent& evt)
|
||||
{
|
||||
if (evt.GetURL().IsEmpty())
|
||||
return;
|
||||
|
||||
if (evt.GetURL().StartsWith(m_default_url)) {
|
||||
define_css();
|
||||
} else {
|
||||
m_styles_defined = false;
|
||||
}
|
||||
|
||||
m_load_default_url_on_next_error = false;
|
||||
if (evt.GetURL().Find(GUI::format_wxstr("/web/%1%.html", m_loading_html)) != wxNOT_FOUND && m_load_default_url) {
|
||||
m_load_default_url = false;
|
||||
@ -969,8 +1075,7 @@ PrintablesWebViewPanel::PrintablesWebViewPanel(wxWindow* parent)
|
||||
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);
|
||||
|
||||
|
||||
m_events["openExternalUrl"] = std::bind(&PrintablesWebViewPanel::on_printables_event_open_url, this, std::placeholders::_1);
|
||||
}
|
||||
|
||||
void PrintablesWebViewPanel::handle_message(const std::string& message)
|
||||
@ -1002,9 +1107,13 @@ void PrintablesWebViewPanel::handle_message(const std::string& message)
|
||||
|
||||
void PrintablesWebViewPanel::on_navigation_request(wxWebViewEvent &evt)
|
||||
{
|
||||
const wxString url = evt.GetURL();
|
||||
const wxString url = evt.GetURL();
|
||||
if (url.StartsWith(m_default_url)) {
|
||||
m_reached_default_url = true;
|
||||
if (url == m_browser->GetCurrentURL()) {
|
||||
// we need to do this to redefine css when reload is hit
|
||||
m_styles_defined = false;
|
||||
}
|
||||
} else if (m_reached_default_url && url.StartsWith("http")) {
|
||||
BOOST_LOG_TRIVIAL(info) << evt.GetURL() << " does not start with default url. Vetoing.";
|
||||
evt.Veto();
|
||||
@ -1240,9 +1349,22 @@ void PrintablesWebViewPanel::on_printables_event_access_token_expired(const std:
|
||||
|
||||
void PrintablesWebViewPanel::on_reload_event(const std::string& message_data)
|
||||
{
|
||||
// Event from our error / loading html pages
|
||||
// Event from our error page button or keyboard shortcut
|
||||
m_styles_defined = false;
|
||||
load_default_url();
|
||||
try {
|
||||
std::stringstream ss(message_data);
|
||||
pt::ptree ptree;
|
||||
pt::read_json(ss, ptree);
|
||||
if (const auto keyboard = ptree.get_optional<bool>("fromKeyboard"); keyboard && *keyboard) {
|
||||
do_reload();
|
||||
} else {
|
||||
// On error page do load of default url.
|
||||
load_default_url();
|
||||
}
|
||||
} catch (const std::exception &e) {
|
||||
BOOST_LOG_TRIVIAL(error) << "Could not parse printables message. " << e.what();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
@ -1342,20 +1464,36 @@ void PrintablesWebViewPanel::on_printables_event_required_login(const std::strin
|
||||
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << " " << message_data;
|
||||
wxGetApp().printables_login_request();
|
||||
}
|
||||
void PrintablesWebViewPanel::on_printables_event_open_url(const std::string& message_data)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << " " << message_data;
|
||||
|
||||
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) {
|
||||
wxGetApp().open_browser_with_warning_dialog(GUI::from_u8(*url));
|
||||
}
|
||||
} catch (const std::exception &e) {
|
||||
BOOST_LOG_TRIVIAL(error) << "Could not parse Printables message. " << e.what();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void PrintablesWebViewPanel::define_css()
|
||||
{
|
||||
|
||||
if (m_styles_defined) {
|
||||
return;
|
||||
}
|
||||
m_styles_defined = true;
|
||||
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__;
|
||||
const std::string script = R"(
|
||||
std::string script = R"(
|
||||
// Loading overlay and Notification style
|
||||
var style = document.createElement('style');
|
||||
style.innerHTML = `
|
||||
body {
|
||||
/* Add your body styles here */
|
||||
}
|
||||
body {}
|
||||
.slic3r-loading-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
@ -1436,8 +1574,41 @@ void PrintablesWebViewPanel::define_css()
|
||||
font-weight: bold;
|
||||
}
|
||||
`;
|
||||
document.head.appendChild(style);
|
||||
document.head.appendChild(style);
|
||||
|
||||
// Capture click on hypertext
|
||||
// Rewritten from mobileApp code
|
||||
(function() {
|
||||
document.addEventListener('click', function(event) {
|
||||
const target = event.target.closest('a[href]');
|
||||
if (!target) return; // Ignore clicks that are not on links
|
||||
const url = target.href;
|
||||
// Allow empty iframe navigation
|
||||
if (url === 'about:blank') {
|
||||
return; // Let it proceed
|
||||
}
|
||||
// Debug log for navigation
|
||||
console.log(`Printables:onNavigationRequest: ${url}`);
|
||||
// Handle all non-printables.com domains in an external browser
|
||||
if (!/printables\.com/.test(url)) {
|
||||
window.ExternalApp.postMessage(JSON.stringify({ event: 'openExternalUrl', url }))
|
||||
event.preventDefault();
|
||||
}
|
||||
// Default: Allow navigation to proceed
|
||||
}, true); // Capture the event during the capture phase
|
||||
})();
|
||||
)";
|
||||
#ifdef __APPLE__
|
||||
// WebView on Windows does read keyboard shortcuts
|
||||
// Thus doing f.e. Reload twice would make the oparation to fail
|
||||
script += R"(
|
||||
document.addEventListener('keydown', function (event) {
|
||||
if (event.key === 'F5' || (event.ctrlKey && event.key === 'r') || (event.metaKey && event.key === 'r')) {
|
||||
window.ExternalApp.postMessage(JSON.stringify({ event: 'reloadHomePage', fromKeyboard: 1}));
|
||||
}
|
||||
});
|
||||
)";
|
||||
#endif // !_WIN32
|
||||
run_script(script);
|
||||
}
|
||||
|
||||
|
@ -73,10 +73,10 @@ public:
|
||||
virtual void sys_color_changed();
|
||||
|
||||
void set_load_default_url_on_next_error(bool val) { m_load_default_url_on_next_error = val; }
|
||||
|
||||
|
||||
protected:
|
||||
virtual void late_create();
|
||||
|
||||
virtual void define_css();
|
||||
virtual void on_page_will_load();
|
||||
|
||||
wxWebView* m_browser { nullptr };
|
||||
@ -118,6 +118,7 @@ protected:
|
||||
bool m_shown { false };
|
||||
bool m_load_default_url_on_next_error { false };
|
||||
bool m_do_late_webview_create {false};
|
||||
bool m_styles_defined {false};
|
||||
|
||||
std::vector<std::string> m_script_message_hadler_names;
|
||||
};
|
||||
@ -194,6 +195,8 @@ public:
|
||||
void send_will_refresh();
|
||||
wxString get_default_url() const override;
|
||||
void set_next_show_url(const std::string& url) {m_next_show_url = Utils::ServiceConfig::instance().printables_url() + url; }
|
||||
protected:
|
||||
void define_css() override;
|
||||
private:
|
||||
void handle_message(const std::string& message);
|
||||
void on_printables_event_access_token_expired(const std::string& message_data);
|
||||
@ -202,9 +205,9 @@ private:
|
||||
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 on_printables_event_open_url(const std::string& message_data);
|
||||
void load_default_url() override;
|
||||
std::string get_url_lang_theme(const wxString& url) const;
|
||||
void define_css();
|
||||
void show_download_notification(const std::string& filename);
|
||||
void show_loading_overlay();
|
||||
void hide_loading_overlay();
|
||||
@ -213,7 +216,6 @@ private:
|
||||
std::string m_next_show_url;
|
||||
|
||||
bool m_refreshing_token {false};
|
||||
bool m_styles_defined {false};
|
||||
#ifdef _WIN32
|
||||
bool m_remove_request_auth { false };
|
||||
#endif
|
||||
|
@ -143,5 +143,4 @@ void load_request(wxWebView* web_view, const std::string& address, const std::st
|
||||
// Load the request in the WebView
|
||||
webkit_web_view_load_request(native_backend, request);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -303,6 +303,5 @@ void load_request(wxWebView* web_view, const std::string& address, const std::st
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Slic3r::GUI
|
||||
#endif // WIN32
|
||||
|
Loading…
x
Reference in New Issue
Block a user