This commit is contained in:
SoftFever
2026-01-23 17:05:56 +08:00
parent 12f51f906e
commit 9703a6b4d7
60 changed files with 13396 additions and 1785 deletions
+82 -15
View File
@@ -75,15 +75,11 @@ ZUserLogin::ZUserLogin() : wxDialog((wxWindow *) (wxGetApp().mainframe), wxID_AN
CentreOnParent();
}
else {
std::string host_url = agent->get_bambulab_host();
TargetUrl = host_url + "/sign-in";
m_networkOk = false;
// Get the login URL from the cloud service agent
wxString strlang = wxGetApp().current_language_code_safe();
if (strlang != "") {
strlang.Replace("_", "-");
TargetUrl = host_url + "/" + strlang + "/sign-in";
}
strlang.Replace("_", "-");
TargetUrl = wxString::FromUTF8(agent->get_cloud_login_url(strlang.ToStdString()));
m_networkOk = TargetUrl.StartsWith("file://");
BOOST_LOG_TRIVIAL(info) << "login url = " << TargetUrl.ToStdString();
@@ -225,9 +221,9 @@ void ZUserLogin::OnDocumentLoaded(wxWebViewEvent &evt)
// Only notify if the document is the main frame, not a subframe
wxString tmpUrl = evt.GetURL();
NetworkAgent* agent = wxGetApp().getAgent();
std::string strHost = agent->get_bambulab_host();
std::string strHost = agent->get_cloud_service_host();
if ( tmpUrl.Contains(strHost) ) {
if (tmpUrl.StartsWith("file://") || tmpUrl.Contains(strHost)) {
m_networkOk = true;
// wxLogMessage("%s", "Document loaded; url='" + evt.GetURL() + "'");
}
@@ -268,28 +264,97 @@ void ZUserLogin::OnFullScreenChanged(wxWebViewEvent &evt)
void ZUserLogin::OnScriptMessage(wxWebViewEvent &evt)
{
wxString str_input = evt.GetString();
BOOST_LOG_TRIVIAL(debug) << "[WebUserLoginDialog] OnScriptMessage received: " << str_input.ToStdString();
try {
json j = json::parse(into_u8(str_input));
BOOST_LOG_TRIVIAL(debug) << "[WebUserLoginDialog] Parsed JSON successfully";
wxString strCmd = j["command"];
BOOST_LOG_TRIVIAL(debug) << "[WebUserLoginDialog] Command: " << strCmd.ToStdString();
NetworkAgent* agent = wxGetApp().getAgent();
if (agent && strCmd == "get_login_cmd" && agent->get_cloud_agent()) {
// Return login config (backend_url, apikey, pkce)
// WebView handles provider selection internally
std::string login_cmd = agent->build_login_cmd();
m_loopback_port = 0;
try {
json cfg = json::parse(login_cmd);
if (cfg.contains("pkce")) {
const auto& pkce = cfg["pkce"];
if (pkce.contains("loopback_port")) {
if (pkce["loopback_port"].is_number_integer()) {
m_loopback_port = pkce["loopback_port"].get<int>();
} else if (pkce["loopback_port"].is_string()) {
m_loopback_port = std::stoi(pkce["loopback_port"].get<std::string>());
}
}
if (m_loopback_port <= 0 && pkce.contains("redirect_uri") && pkce["redirect_uri"].is_string()) {
const std::string redirect_uri = pkce["redirect_uri"].get<std::string>();
const char* prefixes[] = {"localhost:", "127.0.0.1:"};
for (const char* prefix : prefixes) {
auto start = redirect_uri.find(prefix);
if (start == std::string::npos)
continue;
start += strlen(prefix);
auto end = redirect_uri.find('/', start);
std::string port_str = redirect_uri.substr(start, end - start);
try {
m_loopback_port = std::stoi(port_str);
} catch (...) {
m_loopback_port = 0;
}
break;
}
}
}
} catch (...) {
m_loopback_port = 0;
}
wxString str_js = wxString::FromUTF8("window.postMessage(") + wxString::FromUTF8(login_cmd.c_str()) +
wxString::FromUTF8(", '*')");
this->RunScript(str_js);
return;
}
if (strCmd == "autotest_token")
{
m_AutotestToken = j["data"]["token"];
BOOST_LOG_TRIVIAL(debug) << "[WebUserLoginDialog] Stored autotest_token";
}
if (strCmd == "user_login") {
BOOST_LOG_TRIVIAL(debug) << "[WebUserLoginDialog] Processing user_login command";
BOOST_LOG_TRIVIAL(debug) << "[WebUserLoginDialog] User data: " << j["data"].dump();
j["data"]["autotest_token"] = m_AutotestToken;
wxGetApp().handle_script_message(j.dump());
Close();
std::string message_json = j.dump();
BOOST_LOG_TRIVIAL(debug) << "[WebUserLoginDialog] Calling handle_script_message with: " << message_json;
// End modal dialog first to unblock event loop before processing callbacks
BOOST_LOG_TRIVIAL(debug) << "[WebUserLoginDialog] Ending modal dialog";
EndModal(wxID_OK);
// Handle message after modal dialog ends to avoid deadlock
// Use wxTheApp->CallAfter to ensure it runs after modal loop exits
wxTheApp->CallAfter([message_json]() {
BOOST_LOG_TRIVIAL(debug) << "[WebUserLoginDialog] Processing login message after modal ended";
wxGetApp().handle_script_message(message_json);
});
}
else if (strCmd == "get_localhost_url") {
BOOST_LOG_TRIVIAL(info) << "thirdparty_login: get_localhost_url";
wxGetApp().start_http_server();
BOOST_LOG_TRIVIAL(debug) << "thirdparty_login: get_localhost_url";
int loopback_port = m_loopback_port > 0 ? m_loopback_port : LOCALHOST_PORT;
wxGetApp().start_http_server(loopback_port);
std::string sequence_id = j["sequence_id"].get<std::string>();
CallAfter([this, sequence_id] {
json ack_j;
ack_j["command"] = "get_localhost_url";
ack_j["response"]["base_url"] = std::string(LOCALHOST_URL) + std::to_string(LOCALHOST_PORT);
int loopback_port = m_loopback_port > 0 ? m_loopback_port : LOCALHOST_PORT;
ack_j["response"]["base_url"] = std::string(LOCALHOST_URL) + std::to_string(loopback_port);
ack_j["response"]["result"] = "success";
ack_j["sequence_id"] = sequence_id;
wxString str_js = wxString::Format("window.postMessage(%s)", ack_j.dump());
@@ -300,6 +365,8 @@ void ZUserLogin::OnScriptMessage(wxWebViewEvent &evt)
BOOST_LOG_TRIVIAL(info) << "thirdparty_login: thirdparty_login";
if (j["data"].contains("url")) {
std::string jump_url = j["data"]["url"].get<std::string>();
int loopback_port = m_loopback_port > 0 ? m_loopback_port : LOCALHOST_PORT;
wxGetApp().start_http_server(loopback_port);
CallAfter([this, jump_url] {
wxString url = wxString::FromUTF8(jump_url);
wxLaunchDefaultBrowser(url);