Merge branch '2.2.3' into dev_bug_fixed_2.3.0_alves

This commit is contained in:
alves
2026-01-19 16:16:55 +08:00
18 changed files with 588 additions and 733 deletions

View File

@@ -39,9 +39,24 @@ namespace Slic3r {
static const std::string VERSION_CHECK_URL_STABLE = "https://api.github.com/repos/Snapmaker/OrcaSlicer/releases/latest"; static const std::string VERSION_CHECK_URL_STABLE = "https://api.github.com/repos/Snapmaker/OrcaSlicer/releases/latest";
static const std::string VERSION_CHECK_URL = "https://api.github.com/repos/Snapmaker/OrcaSlicer/releases"; static const std::string VERSION_CHECK_URL = "https://api.github.com/repos/Snapmaker/OrcaSlicer/releases";
static const std::string PROFILE_UPDATE_URL = "https://api.github.com/repos/Snapmaker/Orca_Presets/releases/latest"; static const std::string PROFILE_UPDATE_URL = "/upgrade/profile/";
static const std::string FLUTTER_UPDATE_URL = "/upgrade/flutter/";
static const std::string MODELS_STR = "models"; static const std::string MODELS_STR = "models";
#define APP_UPDATE_URL_BASE_CN "https://meta-cfg.snapmaker.cn"
#define APP_UPDATE_URL_BASE_EN "https://meta-cfg.snapmaker.com"
#if defined(_WIN32)
static const std::string APP_UPDATE_URL = std::string("/upgrade/orca/win/");
#elif defined(__APPLE__)
static const std::string APP_UPDATE_URL = std::string("/upgrade/orca/mac/");
#elif defined(__linux__)
static const std::string APP_UPDATE_URL = std::string("/upgrade/orca/linux/");
#else
static const std::string APP_UPDATE_URL = "";
#endif
const std::string AppConfig::SECTION_FILAMENTS = "filaments"; const std::string AppConfig::SECTION_FILAMENTS = "filaments";
const std::string AppConfig::SECTION_MATERIALS = "sla_materials"; const std::string AppConfig::SECTION_MATERIALS = "sla_materials";
const std::string AppConfig::SECTION_EMBOSS_STYLE = "font"; const std::string AppConfig::SECTION_EMBOSS_STYLE = "font";
@@ -1423,17 +1438,52 @@ std::string AppConfig::config_path()
return path; return path;
} }
std::string AppConfig::get_preset_upgrade_url()
{
std::string localLanguage = get("language");
if (localLanguage != "zh_CN")
localLanguage = "en";
std::string url = APP_UPDATE_URL_BASE_EN + PROFILE_UPDATE_URL + localLanguage + std::string("/version.json");
auto countryArea = get_country_code();
if (countryArea == std::string("CN"))
url = APP_UPDATE_URL_BASE_CN + PROFILE_UPDATE_URL + localLanguage + std::string("/version.json");
return url;
}
std::string AppConfig::get_web_resource_upgrade_url()
{
std::string localLanguage = get("language");
if (localLanguage != "zh_CN")
localLanguage = "en";
std::string url = APP_UPDATE_URL_BASE_EN + FLUTTER_UPDATE_URL + localLanguage + std::string("/version.json");
auto countryArea = get_country_code();
if (countryArea == std::string("CN"))
url = APP_UPDATE_URL_BASE_CN + FLUTTER_UPDATE_URL + localLanguage + std::string("/version.json");
return url;
}
std::string AppConfig::get_version_upgrade_url(bool stable_only /* = false*/)
{
//get local area and get the resource from diff server
std::string localLanguage = get("language");
if (localLanguage != "zh_CN")
localLanguage = "en";
std::string url = APP_UPDATE_URL_BASE_EN + APP_UPDATE_URL + localLanguage + std::string("/version.json");
auto countryArea = get_country_code();
if (countryArea == std::string("CN"))
url = APP_UPDATE_URL_BASE_CN + APP_UPDATE_URL + localLanguage + std::string("/version.json");
return url;
}
std::string AppConfig::version_check_url(bool stable_only/* = false*/) const std::string AppConfig::version_check_url(bool stable_only/* = false*/) const
{ {
auto from_settings = get("version_check_url"); auto from_settings = get("version_check_url");
return from_settings.empty() ? stable_only ? VERSION_CHECK_URL_STABLE : VERSION_CHECK_URL : from_settings; return from_settings.empty() ? stable_only ? VERSION_CHECK_URL_STABLE : VERSION_CHECK_URL : from_settings;
} }
std::string AppConfig::profile_update_url() const
{
return PROFILE_UPDATE_URL;
}
bool AppConfig::exists() bool AppConfig::exists()
{ {
return boost::filesystem::exists(config_path()); return boost::filesystem::exists(config_path());

View File

@@ -324,9 +324,9 @@ public:
// Get the Slic3r version check url. // Get the Slic3r version check url.
// This returns a hardcoded string unless it is overriden by "version_check_url" in the ini file. // This returns a hardcoded string unless it is overriden by "version_check_url" in the ini file.
std::string version_check_url(bool stable_only = false) const; std::string version_check_url(bool stable_only = false) const;
std::string get_version_upgrade_url(bool stable_only = false);
// Get the Orca profile update url. std::string get_preset_upgrade_url();
std::string profile_update_url() const; std::string get_web_resource_upgrade_url();
// Returns the original Slic3r version found in the ini file before it was overwritten // Returns the original Slic3r version found in the ini file before it was overwritten
// by the current version // by the current version

View File

@@ -127,7 +127,7 @@ static sentry_value_t before_send(sentry_value_t event, void* hint, void* data)
void initSentryEx() void initSentryEx()
{ {
sentry_options_t* options = sentry_options_new(); sentry_options_t* options = sentry_options_new();
std::string dsn = std::string("https://c74b617c2aedc291444d3a238d23e780@o4508125599563776.ingest.us.sentry.io/4510425163956224"); std::string dsn = std::string("https://282935326eecb9758e7f84a2ad3ae0ab@o4508125599563776.ingest.us.sentry.io/4510425163956224");
{ {
sentry_options_set_dsn(options, dsn.c_str()); sentry_options_set_dsn(options, dsn.c_str());
std::string handlerDir = ""; std::string handlerDir = "";

View File

@@ -164,6 +164,8 @@ typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS2)(
#include <gtk/gtk.h> #include <gtk/gtk.h>
#endif #endif
#define UPDATE_BY_USER 1
using namespace std::literals; using namespace std::literals;
namespace pt = boost::property_tree; namespace pt = boost::property_tree;
@@ -909,44 +911,6 @@ void GUI_App::post_init()
} }
//#endif //#endif
//BBS: remove GCodeViewer as seperate APP logic
/*if (this->init_params->start_as_gcodeviewer) {
if (! this->init_params->input_files.empty())
this->plater()->load_gcode(wxString::FromUTF8(this->init_params->input_files[0].c_str()));
}
else
{
if (! this->init_params->preset_substitutions.empty())
show_substitutions_info(this->init_params->preset_substitutions);
#if 0
// Load the cummulative config over the currently active profiles.
//FIXME if multiple configs are loaded, only the last one will have an effect.
// We need to decide what to do about loading of separate presets (just print preset, just filament preset etc).
// As of now only the full configs are supported here.
if (!m_print_config.empty())
this->gui->mainframe->load_config(m_print_config);
#endif
if (! this->init_params->load_configs.empty())
// Load the last config to give it a name at the UI. The name of the preset may be later
// changed by loading an AMF or 3MF.
//FIXME this is not strictly correct, as one may pass a print/filament/printer profile here instead of a full config.
this->mainframe->load_config_file(this->init_params->load_configs.back());
// If loading a 3MF file, the config is loaded from the last one.
if (!this->init_params->input_files.empty()) {
const std::vector<size_t> res = this->plater()->load_files(this->init_params->input_files);
if (!res.empty() && this->init_params->input_files.size() == 1) {
// Update application titlebar when opening a project file
const std::string& filename = this->init_params->input_files.front();
//BBS: remove amf logic as project
if (boost::algorithm::iends_with(filename, ".3mf"))
this->plater()->set_project_filename(filename);
}
}
if (! this->init_params->extra_config.empty())
this->mainframe->load_config(this->init_params->extra_config);
}*/
// BBS: to be checked // BBS: to be checked
#if 1 #if 1
// show "Did you know" notification // show "Did you know" notification
@@ -999,19 +963,13 @@ void GUI_App::post_init()
std::string language = GUI::into_u8(current_language_code()); std::string language = GUI::into_u8(current_language_code());
std::string network_ver = Slic3r::NetworkAgent::get_version(); std::string network_ver = Slic3r::NetworkAgent::get_version();
bool sys_preset = app_config->get("sync_system_preset") == "true"; bool sys_preset = app_config->get("sync_system_preset") == "true";
this->preset_updater->sync(http_url, language, network_ver, sys_preset ? preset_bundle : nullptr); //this->preset_updater->sync(http_url, language, network_ver, sys_preset ? preset_bundle : nullptr);
this->preset_updater->sync_web_async(true);
this->check_new_version_sf(); this->check_new_version_sf(false, false);
if (is_user_login() && !app_config->get_stealth_mode()) {
// this->check_privacy_version(0);
request_user_handle(0);
}
}); });
} }
if (is_user_login())
request_user_handle(0);
if(!m_networking_need_update && m_agent) { if(!m_networking_need_update && m_agent) {
m_agent->set_on_ssdp_msg_fn( m_agent->set_on_ssdp_msg_fn(
[this](std::string json_str) { [this](std::string json_str) {
@@ -1651,37 +1609,11 @@ void GUI_App::init_networking_callbacks()
{ {
BOOST_LOG_TRIVIAL(info) << __FUNCTION__<< boost::format(": enter, m_agent=%1%")%m_agent; BOOST_LOG_TRIVIAL(info) << __FUNCTION__<< boost::format(": enter, m_agent=%1%")%m_agent;
if (m_agent) { if (m_agent) {
//set callbacks
//m_agent->set_on_user_login_fn([this](int online_login, bool login) {
// GUI::wxGetApp().request_user_handle(online_login);
// });
m_agent->set_server_callback([](std::string url, int status) { m_agent->set_server_callback([](std::string url, int status) {
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(": server_callback, url=%1%, status=%2%") % url % status; BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(": server_callback, url=%1%, status=%2%") % url % status;
//CallAfter([this]() {
// if (!m_server_error_dialog) {
// /*m_server_error_dialog->EndModal(wxCLOSE);
// m_server_error_dialog->Destroy();
// m_server_error_dialog = nullptr;*/
// m_server_error_dialog = new NetworkErrorDialog(mainframe);
// }
//
// if(plater()->get_select_machine_dialog() && plater()->get_select_machine_dialog()->IsShown()){
// return;
// }
//
// if (m_server_error_dialog->m_show_again) {
// return;
// }
//
// if (m_server_error_dialog->IsShown()) {
// return;
// }
//
// m_server_error_dialog->ShowModal();
//});
});
});
m_agent->set_on_server_connected_fn([this](int return_code, int reason_code) { m_agent->set_on_server_connected_fn([this](int return_code, int reason_code) {
if (m_is_closing) { if (m_is_closing) {
@@ -2572,17 +2504,7 @@ bool GUI_App::on_init_inner()
preset_updater = new PresetUpdater(); preset_updater = new PresetUpdater();
Bind(EVT_SLIC3R_VERSION_ONLINE, [this](const wxCommandEvent& evt) { Bind(EVT_SLIC3R_VERSION_ONLINE, [this](const wxCommandEvent& evt) {
if (this->plater_ != nullptr) { if (this->plater_ != nullptr) {
// this->plater_->get_notification_manager()->push_notification(NotificationType::NewAppAvailable);
//BBS show msg box to download new version
/* wxString tips = wxString::Format(_L("Click to download new version in default browser: %s"), version_info.version_str);
DownloadDialog dialog(this->mainframe,
tips,
_L("New version of Snapmaker Orca"),
false,
wxCENTER | wxICON_INFORMATION);
dialog.SetExtendedMessage(extmsg);*/
std::string skip_version_str = this->app_config->get("app", "skip_version"); std::string skip_version_str = this->app_config->get("app", "skip_version");
bool skip_this_version = false; bool skip_this_version = false;
if (!skip_version_str.empty()) { if (!skip_version_str.empty()) {
@@ -2599,7 +2521,6 @@ bool GUI_App::on_init_inner()
UpdateVersionDialog dialog(this->mainframe); UpdateVersionDialog dialog(this->mainframe);
wxString extmsg = wxString::FromUTF8(version_info.description); wxString extmsg = wxString::FromUTF8(version_info.description);
dialog.update_version_info(extmsg, version_info.version_str); dialog.update_version_info(extmsg, version_info.version_str);
//dialog.update_version_info(version_info.description);
if (evt.GetInt() != 0) { if (evt.GetInt() != 0) {
dialog.m_button_skip_version->Hide(); dialog.m_button_skip_version->Hide();
} }
@@ -2628,16 +2549,20 @@ bool GUI_App::on_init_inner()
false, false,
wxCENTER | wxICON_INFORMATION); wxCENTER | wxICON_INFORMATION);
dialog.SetExtendedMessage(description_text); dialog.SetExtendedMessage(description_text);
int result = dialog.ShowModal(); int result = dialog.ShowModal();
switch (result) switch (result)
{ {
case wxID_YES: case wxID_YES:
wxLaunchDefaultBrowser(download_url); wxLaunchDefaultBrowser(download_url);
wxGetApp().mainframe->Close(true);
break; break;
case wxID_NO: case wxID_NO:
wxGetApp().mainframe->Close(true); wxGetApp().mainframe->Close(true);
break; break;
case wxID_CANCEL:
wxGetApp().mainframe->Close(true);
break;
default: default:
wxGetApp().mainframe->Close(true); wxGetApp().mainframe->Close(true);
} }
@@ -2657,6 +2582,24 @@ bool GUI_App::on_init_inner()
}); });
dlg.ShowModal(); dlg.ShowModal();
}); });
Bind(EVT_NO_PRESET_UPDATE, [this](const wxCommandEvent& evt) {
wxString msg = _L("The configuration is up to date.");
InfoDialog dlg(nullptr, _L("Info"), msg);
dlg.ShowModal();
});
Bind(EVT_NO_WEB_RESOURCE_UPDATE, [this](const wxCommandEvent& evt) {
wxString msg = _L("This is the newest version.");
InfoDialog dlg(nullptr, _L("Info"), msg);
dlg.ShowModal();
});
Bind(EVT_REQUEST_SERVER_FAIL, [this](const wxCommandEvent& evt) {
wxString msg = evt.GetString();
InfoDialog dlg(nullptr, _L("Error"), msg);
dlg.ShowModal();
});
} }
else { else {
#ifdef __WXMSW__ #ifdef __WXMSW__
@@ -2670,13 +2613,6 @@ bool GUI_App::on_init_inner()
preset_bundle->backup_user_folder(); preset_bundle->backup_user_folder();
Bind(EVT_SET_SELECTED_MACHINE, &GUI_App::on_set_selected_machine, this);
Bind(EVT_UPDATE_MACHINE_LIST, &GUI_App::on_update_machine_list, this);
Bind(EVT_USER_LOGIN, &GUI_App::on_user_login, this);
Bind(EVT_USER_LOGIN_HANDLE, &GUI_App::on_user_login_handle, this);
Bind(EVT_CHECK_PRIVACY_VER, &GUI_App::on_check_privacy_update, this);
Bind(EVT_CHECK_PRIVACY_SHOW, &GUI_App::show_check_privacy_dlg, this);
Bind(EVT_SHOW_IP_DIALOG, &GUI_App::show_ip_address_enter_dialog_handler, this); Bind(EVT_SHOW_IP_DIALOG, &GUI_App::show_ip_address_enter_dialog_handler, this);
@@ -2770,26 +2706,6 @@ bool GUI_App::on_init_inner()
mainframe->Show(true); mainframe->Show(true);
BOOST_LOG_TRIVIAL(info) << "main frame firstly shown"; BOOST_LOG_TRIVIAL(info) << "main frame firstly shown";
//#if BBL_HAS_FIRST_PAGE
//BBS: set tp3DEditor firstly
/*plater_->canvas3D()->enable_render(false);
mainframe->select_tab(size_t(MainFrame::tp3DEditor));
scrn->SetText(_L("Loading Opengl resourses..."));
plater_->select_view_3D("3D");
//BBS init the opengl resource here
Size canvas_size = plater_->canvas3D()->get_canvas_size();
wxGetApp().imgui()->set_display_size(static_cast<float>(canvas_size.get_width()), static_cast<float>(canvas_size.get_height()));
wxGetApp().init_opengl();
plater_->canvas3D()->init();
wxGetApp().imgui()->new_frame();
plater_->canvas3D()->enable_render(true);
plater_->canvas3D()->render();
if (is_editor())
mainframe->select_tab(size_t(0));*/
//#else
//plater_->trigger_restore_project(1);
//#endif
obj_list()->set_min_height(); obj_list()->set_min_height();
update_mode(); // update view mode after fix of the object_list size update_mode(); // update view mode after fix of the object_list size
@@ -2865,28 +2781,6 @@ bool GUI_App::on_init_inner()
"configuration file.\nPlease note, application settings will be lost, but printer profiles will not be affected.")); "configuration file.\nPlease note, application settings will be lost, but printer profiles will not be affected."));
} }
//启动定时器,轮询进行机器发现
// m_machine_find_timer = new wxTimer(this, m_machine_find_id);
// Bind(wxEVT_TIMER, [this](wxTimerEvent& event) {
// if (!m_machine_find_engine && GUI_App::m_app_alive.load()) {
// machine_find();
// }
// }, m_machine_find_timer->GetId());
// if (!m_machine_find_engine && GUI_App::m_app_alive.load()) {
// machine_find();
// }
//#ifdef __APPLE__
// m_machine_find_timer->Start(1000 * 60 * 2);
//#elif defined(__linux__)
// m_machine_find_timer->Start(1000 * 60 * 2);
//#else
// m_machine_find_timer->Start(5000);
//#endif
return true; return true;
} }
@@ -4187,20 +4081,6 @@ bool GUI_App::check_login()
return result; return result;
} }
void GUI_App::request_user_handle(int online_login)
{
auto evt = new wxCommandEvent(EVT_USER_LOGIN_HANDLE);
evt->SetInt(online_login);
wxQueueEvent(this, evt);
}
void GUI_App::request_user_login(int online_login)
{
auto evt = new wxCommandEvent(EVT_USER_LOGIN);
evt->SetInt(online_login);
wxQueueEvent(this, evt);
}
void GUI_App::request_user_logout() void GUI_App::request_user_logout()
{ {
if (m_agent && m_agent->is_user_login()) { if (m_agent && m_agent->is_user_login()) {
@@ -4434,27 +4314,6 @@ std::string GUI_App::handle_web_request(std::string cmd)
return ""; return "";
} }
void GUI_App::handle_script_message(std::string msg)
{
try {
json j = json::parse(msg);
if (j.contains("command")) {
wxString cmd = j["command"];
if (cmd == "user_login") {
if (m_agent) {
m_agent->change_user(j.dump());
if (m_agent->is_user_login()) {
request_user_login(1);
}
}
}
}
}
catch (...) {
;
}
}
void GUI_App::request_model_download(wxString url) void GUI_App::request_model_download(wxString url)
{ {
if (plater_) { if (plater_) {
@@ -4581,54 +4440,6 @@ void GUI_App::enable_user_preset_folder(bool enable)
} }
} }
void GUI_App::on_set_selected_machine(wxCommandEvent &evt)
{
// Orca: do not connect to default device during app startup, because some of the lan machines might not online yet
// and user will be prompted by several "Connect XXX failed" error message.
return;
DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager();
if (dev) {
dev->set_selected_machine(m_agent->get_user_selected_machine());
}
}
void GUI_App::on_update_machine_list(wxCommandEvent &evt)
{
/* DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager();
if (dev) {
dev->add_user_subscribe();
}*/
}
void GUI_App::on_user_login_handle(wxCommandEvent &evt)
{
if (!m_agent) { return; }
int online_login = evt.GetInt();
m_agent->connect_server();
// get machine list
DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager();
if (!dev) return;
boost::thread update_thread = boost::thread([this, dev] {
dev->update_user_machine_list_info();
auto evt = new wxCommandEvent(EVT_SET_SELECTED_MACHINE);
wxQueueEvent(this, evt);
});
if (online_login) {
remove_user_presets();
enable_user_preset_folder(true);
preset_bundle->load_user_presets(m_agent->get_user_id(), ForwardCompatibilitySubstitutionRule::Enable);
mainframe->update_side_preset_ui();
GUI::wxGetApp().mainframe->show_sync_dialog();
}
}
void GUI_App::check_track_enable() void GUI_App::check_track_enable()
{ {
// Orca: alaways disable track event // Orca: alaways disable track event
@@ -4638,14 +4449,6 @@ void GUI_App::check_track_enable()
} }
} }
void GUI_App::on_user_login(wxCommandEvent &evt)
{
if (!m_agent) { return; }
int online_login = evt.GetInt();
// check privacy before handle
check_privacy_version(online_login);
check_track_enable();
}
bool GUI_App::is_studio_active() bool GUI_App::is_studio_active()
{ {
@@ -4662,95 +4465,6 @@ void GUI_App::reset_to_active()
last_active_point = std::chrono::system_clock::now(); last_active_point = std::chrono::system_clock::now();
} }
void GUI_App::check_update(bool show_tips, int by_user)
{
if (version_info.version_str.empty()) return;
if (version_info.url.empty()) return;
auto curr_version = Semver::parse(SLIC3R_VERSION);
auto remote_version = Semver::parse(version_info.version_str);
if (curr_version && remote_version && (*remote_version > *curr_version)) {
if (version_info.force_upgrade) {
wxGetApp().app_config->set_bool("force_upgrade", version_info.force_upgrade);
wxGetApp().app_config->set("upgrade", "force_upgrade", true);
wxGetApp().app_config->set("upgrade", "description", version_info.description);
wxGetApp().app_config->set("upgrade", "version", version_info.version_str);
wxGetApp().app_config->set("upgrade", "url", version_info.url);
GUI::wxGetApp().enter_force_upgrade();
}
else {
GUI::wxGetApp().request_new_version(by_user);
}
} else {
wxGetApp().app_config->set("upgrade", "force_upgrade", false);
if (show_tips)
this->no_new_version();
}
}
void GUI_App::check_new_version(bool show_tips, int by_user)
{
return; // orca: not used, see check_new_version_sf
std::string platform = "windows";
#ifdef __WINDOWS__
platform = "windows";
#endif
#ifdef __APPLE__
platform = "macos";
#endif
#ifdef __LINUX__
platform = "linux";
#endif
std::string query_params = (boost::format("?name=slicer&version=%1%&guide_version=%2%")
% VersionInfo::convert_full_version(SLIC3R_VERSION)
% VersionInfo::convert_full_version("0.0.0.1")
).str();
std::string url = get_http_url(app_config->get_country_code()) + query_params;
Slic3r::Http http = Slic3r::Http::get(url);
http.header("accept", "application/json")
.timeout_connect(TIMEOUT_CONNECT)
.timeout_max(TIMEOUT_RESPONSE)
.on_complete([this, show_tips, by_user](std::string body, unsigned) {
try {
json j = json::parse(body);
if (j.contains("message")) {
if (j["message"].get<std::string>() == "success") {
if (j.contains("software")) {
if (j["software"].empty() && show_tips) {
this->no_new_version();
}
else {
if (j["software"].contains("url")
&& j["software"].contains("version")
&& j["software"].contains("description")) {
version_info.url = j["software"]["url"].get<std::string>();
version_info.version_str = j["software"]["version"].get<std::string>();
version_info.description = j["software"]["description"].get<std::string>();
}
if (j["software"].contains("force_update")) {
version_info.force_upgrade = j["software"]["force_update"].get<bool>();
}
CallAfter([this, show_tips, by_user](){
this->check_update(show_tips, by_user);
});
}
}
}
}
}
catch (...) {
;
}
})
.on_error([this](std::string body, std::string error, unsigned int status) {
handle_http_error(status, body);
BOOST_LOG_TRIVIAL(error) << "check new version error" << body;
}).perform();
}
//parse the string, if it doesn't contain a valid version string, return invalid version. //parse the string, if it doesn't contain a valid version string, return invalid version.
Semver get_version(const std::string& str, const std::regex& regexp) { Semver get_version(const std::string& str, const std::regex& regexp) {
std::smatch match; std::smatch match;
@@ -5029,110 +4743,145 @@ void maybe_attach_updater_signature(Http& http, const std::string& canonical_que
} // namespace } // namespace
void GUI_App::check_new_version_sf(bool show_tips, int by_user) void GUI_App::check_web_version()
{ {
if (preset_updater != nullptr)
preset_updater->sync_web_async();
}
void GUI_App::check_preset_version()
{
if (preset_updater != nullptr)
preset_updater->sync_config_async();
}
void GUI_App::check_new_version_sf(bool show_tips, bool by_user)
{
std::string update_url = app_config->get_version_upgrade_url();
AppConfig* app_config = wxGetApp().app_config; AppConfig* app_config = wxGetApp().app_config;
bool check_stable_only = app_config->get_bool("check_stable_update_only");
auto version_check_url = app_config->version_check_url(check_stable_only); Http::get(update_url)
Http::get(version_check_url) .on_error([&, by_user](std::string body, std::string error, unsigned http_status) {
.on_error([&](std::string body, std::string error, unsigned http_status) {
(void)body; (void)body;
wxCommandEvent* evt = new wxCommandEvent(EVT_REQUEST_SERVER_FAIL);
wxString errorMsg = wxString::Format(_L("request to server update soft fail with body:%s,error:%s,status:%d"), body,
error, http_status);
evt->SetString(errorMsg);
if(by_user)
GUI::wxGetApp().QueueEvent(evt);
BOOST_LOG_TRIVIAL(error) << format("Error getting: `%1%`: HTTP %2%, %3%", "check_new_version_sf", http_status, BOOST_LOG_TRIVIAL(error) << format("Error getting: `%1%`: HTTP %2%, %3%", "check_new_version_sf", http_status,
error); error);
}) })
.timeout_connect(1) .timeout_connect(TIMEOUT_CONNECT)
.on_complete([this,by_user, check_stable_only](std::string body, unsigned http_status) { .on_complete([this,by_user](std::string body, unsigned http_status) {
// Http response OK // Http response OK
if (http_status != 200) if (http_status != 200) {
BOOST_LOG_TRIVIAL(error) << format("status not 200 with: `%1%`: HTTP %2%", "check_new_version_sf", http_status);
return; return;
try { }
boost::trim(body); try {
// Orca: parse github release, inspired by SS json jsonObj = json::parse(body);
boost::property_tree::ptree root; auto errCode = jsonObj["code"];
std::stringstream json_stream(body); if (errCode != 200)
boost::property_tree::read_json(json_stream, root); return;
// at least two number, use '.' as separator. can be followed by -Az23 for prereleased and +Az42 for auto dataObj = jsonObj.value("data", json::object());
// metadata auto isFullUpgrade = dataObj.value("is_full_upgrade", true);
std::regex matcher("[0-9]+\\.[0-9]+(\\.[0-9]+)*(-[A-Za-z0-9]+)?(\\+[A-Za-z0-9]+)?"); auto isForceUpgrade = dataObj.value("is_force_upgrade", false);
version_info.force_upgrade = isForceUpgrade;
Semver current_version = get_version(Snapmaker_VERSION, matcher); version_info.version_str = dataObj.value("version", "");
Semver best_pre(0, 0, 0); auto releaseType = dataObj.value("release_type", "");
Semver best_release(0, 0, 0); auto platformType = dataObj.value("platform_type", "");
std::string best_pre_url; int fileSize = 0;
std::string best_release_url; std::string fileMd5 = "";
std::string best_release_content; std::string fileSha256 = "";
std::string best_pre_content; std::string reservedData = "";
const std::regex reg_num("([0-9]+)"); std::string reservedData2 = "";
if (check_stable_only) {
std::string tag = root.get<std::string>("tag_name"); // win x86_x64, mac arm/x86_x64 universal
if (tag[0] == 'v') auto fullObj = dataObj.value("full", json::object());
tag.erase(0, 1); auto defaultObj = fullObj.value("default", json::object());
for (std::regex_iterator it = std::sregex_iterator(tag.begin(), tag.end(), reg_num); it != std::sregex_iterator(); ++it) {} auto armObj = fullObj.value("arm", json::object());
Semver tag_version = get_version(tag, matcher); auto intelObj = fullObj.value("intel", json::object());
if (root.get<bool>("prerelease")) { version_info.description = fullObj.value("file_describe", "");
if (best_pre < tag_version) {
best_pre = tag_version; if (platformType == "win") {
best_pre_url = root.get<std::string>("html_url"); fileSize = defaultObj.value("file_size", 0);
best_pre_content = root.get<std::string>("body"); fileMd5 = defaultObj.value("file_md5", "");
best_pre.set_prerelease("Preview"); fileSha256 = defaultObj.value("file_sha256", "");
} version_info.url = defaultObj.value("file_url", "");
} else {
if (best_release < tag_version) { reservedData = defaultObj.value("reserved_1", "");
best_release = tag_version; reservedData2 = defaultObj.value("reserved_2", "");
best_release_url = root.get<std::string>("html_url"); }
best_release_content = root.get<std::string>("body"); else if (platformType == "mac")
{
bool isArm64 = false;
#if defined(__aarch64__) || defined(__arm64__) || defined(_M_ARM64)
isArm64 = true;
#else
isArm64 = false;
#endif
json platformObj = defaultObj;
if (isArm64) {
if (!armObj.empty()) {
platformObj = armObj;
} }
} }
} else { else
for (auto json_version : root) { {
std::string tag = json_version.second.get<std::string>("tag_name"); if (!intelObj.empty()) {
if (tag[0] == 'v') platformObj = intelObj;
tag.erase(0, 1);
for (std::regex_iterator it = std::sregex_iterator(tag.begin(), tag.end(), reg_num); it != std::sregex_iterator();
++it) {}
Semver tag_version = get_version(tag, matcher);
if (json_version.second.get<bool>("prerelease")) {
if (best_pre < tag_version) {
best_pre = tag_version;
best_pre_url = json_version.second.get<std::string>("html_url");
best_pre_content = json_version.second.get<std::string>("body");
best_pre.set_prerelease("Preview");
}
} else {
if (best_release < tag_version) {
best_release = tag_version;
best_release_url = json_version.second.get<std::string>("html_url");
best_release_content = json_version.second.get<std::string>("body");
}
} }
} }
}
// if release is more recent than beta, use release anyway fileSize = platformObj.value("file_size", 0);
if (best_pre < best_release) { fileMd5 = platformObj.value("file_md5", "");
best_pre = best_release; fileSha256 = platformObj.value("file_sha256", "");
best_pre_url = best_release_url; version_info.url = platformObj.value("file_url", "");
best_pre_content = best_release_content;
reservedData = platformObj.value("reserved_1", "");
reservedData2 = platformObj.value("reserved_2", "");
} }
// if we're the most recent, don't do anything else
if ((check_stable_only ? best_release : best_pre) <= current_version) { {
if (by_user != 0) BOOST_LOG_TRIVIAL(warning) << "don't support linux upgrade";
this->no_new_version();
return; return;
} }
version_info.url = check_stable_only ? best_release_url : best_pre_url; std::regex matcher("[0-9]+\\.[0-9]+(\\.[0-9]+)*(-[A-Za-z0-9]+)?(\\+[A-Za-z0-9]+)?");
version_info.version_str = check_stable_only ? best_release.to_string_sf() : best_pre.to_string_sf(); Semver current_version = get_version(Snapmaker_VERSION, matcher);
version_info.description = check_stable_only ? best_release_content : best_pre_content;
version_info.force_upgrade = false; Semver server_version = get_version(version_info.version_str, matcher);
if (current_version >= server_version && by_user) {
this->no_new_version();
return;
}
//if (true)
if (isForceUpgrade)
{
wxGetApp().app_config->set_bool("force_upgrade", version_info.force_upgrade);
wxGetApp().app_config->set("upgrade", "force_upgrade", true);
wxGetApp().app_config->set("upgrade", "description", version_info.description);
wxGetApp().app_config->set("upgrade", "version", version_info.version_str);
wxGetApp().app_config->set("upgrade", "url", version_info.url);
GUI::wxGetApp().enter_force_upgrade();
return;
}
wxCommandEvent* evt = new wxCommandEvent(EVT_SLIC3R_VERSION_ONLINE); wxCommandEvent* evt = new wxCommandEvent(EVT_SLIC3R_VERSION_ONLINE);
evt->SetString((check_stable_only ? best_release : best_pre).to_string()); evt->SetString(version_info.url);
if (by_user)
evt->SetInt(UPDATE_BY_USER);
GUI::wxGetApp().QueueEvent(evt); GUI::wxGetApp().QueueEvent(evt);
} catch (...) {} } catch (...) {}
}) })
.perform(); .perform_sync();
} }
void GUI_App::process_network_msg(std::string dev_id, std::string msg) void GUI_App::process_network_msg(std::string dev_id, std::string msg)
{ {
@@ -5141,15 +4890,6 @@ void GUI_App::process_network_msg(std::string dev_id, std::string msg)
} }
} }
//BBS pop up a dialog and download files
void GUI_App::request_new_version(int by_user)
{
wxCommandEvent* evt = new wxCommandEvent(EVT_SLIC3R_VERSION_ONLINE);
evt->SetString(GUI::from_u8(version_info.version_str));
evt->SetInt(by_user);
GUI::wxGetApp().QueueEvent(evt);
}
void GUI_App::enter_force_upgrade() void GUI_App::enter_force_upgrade()
{ {
wxCommandEvent *evt = new wxCommandEvent(EVT_ENTER_FORCE_UPGRADE); wxCommandEvent *evt = new wxCommandEvent(EVT_ENTER_FORCE_UPGRADE);
@@ -5166,33 +4906,6 @@ void GUI_App::set_skip_version(bool skip)
} }
} }
void GUI_App::show_check_privacy_dlg(wxCommandEvent& evt)
{
int online_login = evt.GetInt();
PrivacyUpdateDialog privacy_dlg(this->mainframe, wxID_ANY, _L("Privacy Policy Update"));
privacy_dlg.Bind(EVT_PRIVACY_UPDATE_CONFIRM, [this, online_login](wxCommandEvent &e) {
app_config->set("privacy_version", privacy_version_info.version_str);
app_config->set_bool("privacy_update_checked", true);
request_user_handle(online_login);
});
privacy_dlg.Bind(EVT_PRIVACY_UPDATE_CANCEL, [this](wxCommandEvent &e) {
app_config->set_bool("privacy_update_checked", false);
if (m_agent) {
m_agent->user_logout();
}
});
privacy_dlg.set_text(privacy_version_info.description);
privacy_dlg.on_show();
}
void GUI_App::on_show_check_privacy_dlg(int online_login)
{
auto evt = new wxCommandEvent(EVT_CHECK_PRIVACY_SHOW);
evt->SetInt(online_login);
wxQueueEvent(this, evt);
}
bool GUI_App::check_privacy_update() bool GUI_App::check_privacy_update()
{ {
if (privacy_version_info.version_str.empty() || privacy_version_info.description.empty() if (privacy_version_info.version_str.empty() || privacy_version_info.description.empty()
@@ -5211,66 +4924,6 @@ bool GUI_App::check_privacy_update()
return false; return false;
} }
void GUI_App::on_check_privacy_update(wxCommandEvent& evt)
{
int online_login = evt.GetInt();
bool result = check_privacy_update();
if (result)
on_show_check_privacy_dlg(online_login);
else
request_user_handle(online_login);
}
void GUI_App::check_privacy_version(int online_login)
{
update_http_extra_header();
std::string query_params = "?policy/privacy=00.00.00.00";
std::string url = get_http_url(app_config->get_country_code()) + query_params;
Slic3r::Http http = Slic3r::Http::get(url);
http.header("accept", "application/json")
.timeout_connect(TIMEOUT_CONNECT)
.timeout_max(TIMEOUT_RESPONSE)
.on_complete([this, online_login](std::string body, unsigned) {
try {
json j = json::parse(body);
if (j.contains("message")) {
if (j["message"].get<std::string>() == "success") {
if (j.contains("resources")) {
for (auto it = j["resources"].begin(); it != j["resources"].end(); it++) {
if (it->contains("type")) {
if ((*it)["type"] == std::string("policy/privacy")
&& it->contains("version")
&& it->contains("description")
&& it->contains("url")
&& it->contains("force_update")) {
privacy_version_info.version_str = (*it)["version"].get<std::string>();
privacy_version_info.description = (*it)["description"].get<std::string>();
privacy_version_info.url = (*it)["url"].get<std::string>();
privacy_version_info.force_upgrade = (*it)["force_update"].get<bool>();
break;
}
}
}
CallAfter([this, online_login]() {
auto evt = new wxCommandEvent(EVT_CHECK_PRIVACY_VER);
evt->SetInt(online_login);
wxQueueEvent(this, evt);
});
}
}
}
}
catch (...) {
request_user_handle(online_login);
}
})
.on_error([this, online_login](std::string body, std::string error, unsigned int status) {
request_user_handle(online_login);
BOOST_LOG_TRIVIAL(error) << "check privacy version error" << body;
}).perform();
}
void GUI_App::no_new_version() void GUI_App::no_new_version()
{ {
wxCommandEvent* evt = new wxCommandEvent(EVT_SHOW_NO_NEW_VERSION); wxCommandEvent* evt = new wxCommandEvent(EVT_SHOW_NO_NEW_VERSION);
@@ -7345,8 +6998,7 @@ void GUI_App::check_updates(const bool verbose)
m_app_conf_exists = true; m_app_conf_exists = true;
} }
else if (verbose && updater_result == PresetUpdater::R_NOOP) { else if (verbose && updater_result == PresetUpdater::R_NOOP) {
MsgNoUpdates dlg;
dlg.ShowModal();
} }
} }
catch (const std::exception & ex) { catch (const std::exception & ex) {

View File

@@ -557,13 +557,10 @@ private:
void sm_request_login(bool show_user_info = false); void sm_request_login(bool show_user_info = false);
void sm_ShowUserLogin(bool show = true); void sm_ShowUserLogin(bool show = true);
void sm_request_user_logout(); void sm_request_user_logout();
void request_user_login(int online_login = 0);
void request_user_handle(int online_login = 0);
void request_user_logout(); void request_user_logout();
int request_user_unbind(std::string dev_id); int request_user_unbind(std::string dev_id);
std::string handle_web_request(std::string cmd); std::string handle_web_request(std::string cmd);
void handle_script_message(std::string msg);
void request_model_download(wxString url); void request_model_download(wxString url);
void download_project(std::string project_id); void download_project(std::string project_id);
void request_project_download(std::string project_id); void request_project_download(std::string project_id);
@@ -573,10 +570,6 @@ private:
void handle_http_error(unsigned int status, std::string body); void handle_http_error(unsigned int status, std::string body);
void on_http_error(wxCommandEvent &evt); void on_http_error(wxCommandEvent &evt);
void on_set_selected_machine(wxCommandEvent& evt);
void on_update_machine_list(wxCommandEvent& evt);
void on_user_login(wxCommandEvent &evt);
void on_user_login_handle(wxCommandEvent& evt);
void enable_user_preset_folder(bool enable); void enable_user_preset_folder(bool enable);
// BBS // BBS
@@ -585,11 +578,10 @@ private:
bool m_studio_active = true; bool m_studio_active = true;
std::chrono::system_clock::time_point last_active_point; std::chrono::system_clock::time_point last_active_point;
void check_update(bool show_tips, int by_user); void check_web_version();
void check_new_version(bool show_tips = false, int by_user = 0); void check_preset_version();
void check_new_version_sf(bool show_tips = false, int by_user = 0); void check_new_version_sf(bool show_tips = false, bool by_user = false);
void process_network_msg(std::string dev_id, std::string msg); void process_network_msg(std::string dev_id, std::string msg);
void request_new_version(int by_user);
void enter_force_upgrade(); void enter_force_upgrade();
void set_skip_version(bool skip = true); void set_skip_version(bool skip = true);
void no_new_version(); void no_new_version();
@@ -609,12 +601,8 @@ private:
void start_page_http_server(); void start_page_http_server();
void stop_page_http_server(); void stop_page_http_server();
void switch_staff_pick(bool on); void switch_staff_pick(bool on);
void on_show_check_privacy_dlg(int online_login = 0);
void show_check_privacy_dlg(wxCommandEvent& evt);
void on_check_privacy_update(wxCommandEvent &evt);
bool check_privacy_update(); bool check_privacy_update();
void check_privacy_version(int online_login = 0);
void check_track_enable(); void check_track_enable();
static bool catch_error(std::function<void()> cb, const std::string& err); static bool catch_error(std::function<void()> cb, const std::string& err);
@@ -794,7 +782,7 @@ private:
bool check_networking_version(); bool check_networking_version();
void cancel_networking_install(); void cancel_networking_install();
void restart_networking(); void restart_networking();
void check_config_updates_from_updater() { check_updates(false); } void check_config_updates_from_updater(bool updateByuser = false) { check_updates(updateByuser); }
private: private:
int updating_bambu_networking(); int updating_bambu_networking();

View File

@@ -676,7 +676,7 @@ std::shared_ptr<HttpServer::Response> HttpServer::bbl_auth_handle_request(const
j["data"]["user"]["avatar"] = user_avatar; j["data"]["user"]["avatar"] = user_avatar;
agent->change_user(j.dump()); agent->change_user(j.dump());
if (agent->is_user_login()) { if (agent->is_user_login()) {
wxGetApp().request_user_login(1); //wxGetApp().request_user_login(1);
} }
GUI::wxGetApp().CallAfter([] { wxGetApp().ShowUserLogin(false); }); GUI::wxGetApp().CallAfter([] { wxGetApp().ShowUserLogin(false); });
std::string location_str = (boost::format("%1%?result=success") % redirect_url).str(); std::string location_str = (boost::format("%1%?result=success") % redirect_url).str();

View File

@@ -77,17 +77,15 @@
#include "sentry_wrapper/SentryWrapper.hpp" #include "sentry_wrapper/SentryWrapper.hpp"
#define UPDATE_BUSER true
#define UPDATE_BUAUTO false
namespace Slic3r { namespace Slic3r {
namespace GUI { namespace GUI {
wxDEFINE_EVENT(EVT_SELECT_TAB, wxCommandEvent); wxDEFINE_EVENT(EVT_SELECT_TAB, wxCommandEvent);
wxDEFINE_EVENT(EVT_HTTP_ERROR, wxCommandEvent); wxDEFINE_EVENT(EVT_HTTP_ERROR, wxCommandEvent);
wxDEFINE_EVENT(EVT_USER_LOGIN, wxCommandEvent);
wxDEFINE_EVENT(EVT_USER_LOGIN_HANDLE, wxCommandEvent);
wxDEFINE_EVENT(EVT_CHECK_PRIVACY_VER, wxCommandEvent);
wxDEFINE_EVENT(EVT_CHECK_PRIVACY_SHOW, wxCommandEvent);
wxDEFINE_EVENT(EVT_SHOW_IP_DIALOG, wxCommandEvent); wxDEFINE_EVENT(EVT_SHOW_IP_DIALOG, wxCommandEvent);
wxDEFINE_EVENT(EVT_SET_SELECTED_MACHINE, wxCommandEvent);
wxDEFINE_EVENT(EVT_UPDATE_MACHINE_LIST, wxCommandEvent); wxDEFINE_EVENT(EVT_UPDATE_MACHINE_LIST, wxCommandEvent);
wxDEFINE_EVENT(EVT_UPDATE_PRESET_CB, SimpleEvent); wxDEFINE_EVENT(EVT_UPDATE_PRESET_CB, SimpleEvent);
@@ -2294,11 +2292,26 @@ static wxMenu* generate_help_menu()
// Check New Version // Check New Version
append_menu_item(helpMenu, wxID_ANY, _L("Check for Update"), _L("Check for Update"), append_menu_item(helpMenu, wxID_ANY, _L("Check for Update"), _L("Check for Update"),
[](wxCommandEvent&) { [](wxCommandEvent&) {
wxGetApp().check_new_version_sf(true, 1); wxGetApp().check_new_version_sf(true, UPDATE_BUSER);
}, "", nullptr, []() { }, "", nullptr, []() {
return true; return true;
}); });
append_menu_item(
helpMenu, wxID_ANY, _L("Check for Process Preset Updates"), _L("Check for Process Preset Updates"),
[](wxCommandEvent&) {
wxGetApp().check_preset_version();
},
"", nullptr, []() { return true; });
append_menu_item(
helpMenu, wxID_ANY, _L("Check for Web ResourceUpdates"), _L("Check for Web ResourceUpdates"),
[](wxCommandEvent&) {
wxGetApp().check_web_version();
},
"", nullptr, []() { return true; });
append_menu_item(helpMenu, wxID_ANY, _L("Import Profile"), _L("Import Profile"), [](wxCommandEvent&) { append_menu_item(helpMenu, wxID_ANY, _L("Import Profile"), _L("Import Profile"), [](wxCommandEvent&) {
wxGetApp().import_presets(); wxGetApp().import_presets();
}); });

View File

@@ -417,12 +417,7 @@ public:
}; };
wxDECLARE_EVENT(EVT_HTTP_ERROR, wxCommandEvent); wxDECLARE_EVENT(EVT_HTTP_ERROR, wxCommandEvent);
wxDECLARE_EVENT(EVT_USER_LOGIN, wxCommandEvent);
wxDECLARE_EVENT(EVT_USER_LOGIN_HANDLE, wxCommandEvent);
wxDECLARE_EVENT(EVT_CHECK_PRIVACY_VER, wxCommandEvent);
wxDECLARE_EVENT(EVT_CHECK_PRIVACY_SHOW, wxCommandEvent);
wxDECLARE_EVENT(EVT_SHOW_IP_DIALOG, wxCommandEvent); wxDECLARE_EVENT(EVT_SHOW_IP_DIALOG, wxCommandEvent);
wxDECLARE_EVENT(EVT_SET_SELECTED_MACHINE, wxCommandEvent);
wxDECLARE_EVENT(EVT_UPDATE_MACHINE_LIST, wxCommandEvent); wxDECLARE_EVENT(EVT_UPDATE_MACHINE_LIST, wxCommandEvent);
wxDECLARE_EVENT(EVT_UPDATE_PRESET_CB, SimpleEvent); wxDECLARE_EVENT(EVT_UPDATE_PRESET_CB, SimpleEvent);

View File

@@ -441,7 +441,7 @@ DownloadDialog::DownloadDialog(wxWindow *parent, const wxString &msg, const wxSt
: MsgDialog(parent, title, msg, style), msg(msg) : MsgDialog(parent, title, msg, style), msg(msg)
{ {
add_button(wxID_YES, true, _L("Download")); add_button(wxID_YES, true, _L("Download"));
add_button(wxID_CANCEL, true, _L("Skip")); //add_button(wxID_CANCEL, true, _L("Skip"));
finalize(); finalize();
} }

View File

@@ -1198,7 +1198,7 @@ wxWindow* PreferencesDialog::create_general_page()
app_config->save(); app_config->save();
auto item_check_stable_version_only = create_item_checkbox(_L("Check for stable updates only"), page, _L("Check for stable updates only"), 50, "check_stable_update_only"); //auto item_check_stable_version_only = create_item_checkbox(_L("Check for stable updates only"), page, _L("Check for stable updates only"), 50, "check_stable_update_only");
std::vector<wxString> Units = {_L("Metric") + " (mm, g)", _L("Imperial") + " (in, oz)"}; std::vector<wxString> Units = {_L("Metric") + " (mm, g)", _L("Imperial") + " (in, oz)"};
auto item_currency = create_item_combobox(_L("Units"), page, _L("Units"), "use_inches", Units); auto item_currency = create_item_combobox(_L("Units"), page, _L("Units"), "use_inches", Units);
@@ -1233,7 +1233,7 @@ wxWindow* PreferencesDialog::create_general_page()
auto item_multi_machine = create_item_checkbox(_L("Multi-device Management (Take effect after restarting Snapmaker Orca)."), page, _L("With this option enabled, you can send a task to multiple devices at the same time and manage multiple devices."), 50, "enable_multi_machine"); auto item_multi_machine = create_item_checkbox(_L("Multi-device Management (Take effect after restarting Snapmaker Orca)."), page, _L("With this option enabled, you can send a task to multiple devices at the same time and manage multiple devices."), 50, "enable_multi_machine");
auto item_auto_arrange = create_item_checkbox(_L("Auto arrange plate after cloning"), page, _L("Auto arrange plate after object cloning"), 50, "auto_arrange"); auto item_auto_arrange = create_item_checkbox(_L("Auto arrange plate after cloning"), page, _L("Auto arrange plate after object cloning"), 50, "auto_arrange");
auto title_presets = create_item_title(_L("Presets"), page, _L("Presets")); auto title_presets = create_item_title(_L("Presets"), page, _L("Presets"));
auto title_network = create_item_title(_L("Network"), page, _L("Network")); //auto title_network = create_item_title(_L("Network"), page, _L("Network"));
auto item_user_sync = create_item_checkbox(_L("Auto sync user presets (Printer/Filament/Process)"), page, _L("User Sync"), 50, "sync_user_preset"); auto item_user_sync = create_item_checkbox(_L("Auto sync user presets (Printer/Filament/Process)"), page, _L("User Sync"), 50, "sync_user_preset");
auto item_system_sync = create_item_checkbox(_L("Update built-in Presets automatically."), page, _L("System Sync"), 50, "sync_system_preset"); auto item_system_sync = create_item_checkbox(_L("Update built-in Presets automatically."), page, _L("System Sync"), 50, "sync_system_preset");
auto item_save_presets = create_item_button(_L("Clear my choice on the unsaved presets."), _L("Clear"), page, L"", _L("Clear my choice on the unsaved presets."), []() { auto item_save_presets = create_item_button(_L("Clear my choice on the unsaved presets."), _L("Clear"), page, L"", _L("Clear my choice on the unsaved presets."), []() {
@@ -1338,8 +1338,8 @@ wxWindow* PreferencesDialog::create_general_page()
sizer_page->Add(item_system_sync, 0, wxTOP, FromDIP(3)); sizer_page->Add(item_system_sync, 0, wxTOP, FromDIP(3));
sizer_page->Add(item_remember_printer_config, 0, wxTOP, FromDIP(3)); sizer_page->Add(item_remember_printer_config, 0, wxTOP, FromDIP(3));
sizer_page->Add(item_save_presets, 0, wxTOP, FromDIP(3)); sizer_page->Add(item_save_presets, 0, wxTOP, FromDIP(3));
sizer_page->Add(title_network, 0, wxTOP | wxEXPAND, FromDIP(20)); //sizer_page->Add(title_network, 0, wxTOP | wxEXPAND, FromDIP(20));
sizer_page->Add(item_check_stable_version_only, 0, wxTOP, FromDIP(3)); //sizer_page->Add(item_check_stable_version_only, 0, wxTOP, FromDIP(3));
// SM Beta: temporarily open the item_stealth_mode and close the network plugin // SM Beta: temporarily open the item_stealth_mode and close the network plugin

View File

@@ -96,7 +96,6 @@ ReleaseNoteDialog::ReleaseNoteDialog(Plater *plater /*= nullptr*/)
ReleaseNoteDialog::~ReleaseNoteDialog() {} ReleaseNoteDialog::~ReleaseNoteDialog() {}
void ReleaseNoteDialog::on_dpi_changed(const wxRect &suggested_rect) void ReleaseNoteDialog::on_dpi_changed(const wxRect &suggested_rect)
{ {
} }
@@ -129,19 +128,14 @@ UpdatePluginDialog::UpdatePluginDialog(wxWindow* parent /*= nullptr*/)
m_sizer_main->Add(0, 0, 0, wxTOP, FromDIP(30)); m_sizer_main->Add(0, 0, 0, wxTOP, FromDIP(30));
wxBoxSizer* m_sizer_body = new wxBoxSizer(wxHORIZONTAL); wxBoxSizer* m_sizer_body = new wxBoxSizer(wxHORIZONTAL);
auto sm = create_scaled_bitmap("Snapmaker_Orca", nullptr, 55); auto sm = create_scaled_bitmap("Snapmaker_Orca", nullptr, 55);
auto brand = new wxStaticBitmap(this, wxID_ANY, sm, wxDefaultPosition, wxSize(FromDIP(55), FromDIP(55))); auto brand = new wxStaticBitmap(this, wxID_ANY, sm, wxDefaultPosition, wxSize(FromDIP(55), FromDIP(55)));
wxBoxSizer* m_sizer_right = new wxBoxSizer(wxVERTICAL); wxBoxSizer* m_sizer_right = new wxBoxSizer(wxVERTICAL);
m_text_up_info = new Label(this, Label::Head_13, wxEmptyString, LB_AUTO_WRAP); m_text_up_info = new Label(this, Label::Head_13, wxEmptyString, LB_AUTO_WRAP);
m_text_up_info->SetMaxSize(wxSize(FromDIP(260), -1)); m_text_up_info->SetMaxSize(wxSize(FromDIP(260), -1));
m_text_up_info->SetForegroundColour(wxColour(0x26, 0x2E, 0x30)); m_text_up_info->SetForegroundColour(wxColour(0x26, 0x2E, 0x30));
operation_tips = new ::Label(this, Label::Body_12, _L("Click OK to update the Network plug-in when Snapmaker Orca launches next time."), LB_AUTO_WRAP); operation_tips = new ::Label(this, Label::Body_12, _L("Click OK to update the Network plug-in when Snapmaker Orca launches next time."), LB_AUTO_WRAP);
operation_tips->SetMinSize(wxSize(FromDIP(260), -1)); operation_tips->SetMinSize(wxSize(FromDIP(260), -1));
operation_tips->SetMaxSize(wxSize(FromDIP(260), -1)); operation_tips->SetMaxSize(wxSize(FromDIP(260), -1));
@@ -213,7 +207,6 @@ UpdatePluginDialog::UpdatePluginDialog(wxWindow* parent /*= nullptr*/)
UpdatePluginDialog::~UpdatePluginDialog() {} UpdatePluginDialog::~UpdatePluginDialog() {}
void UpdatePluginDialog::on_dpi_changed(const wxRect& suggested_rect) void UpdatePluginDialog::on_dpi_changed(const wxRect& suggested_rect)
{ {
} }
@@ -269,18 +262,11 @@ UpdateVersionDialog::UpdateVersionDialog(wxWindow *parent)
auto m_line_top = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(-1, 1)); auto m_line_top = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(-1, 1));
m_line_top->SetBackgroundColour(wxColour(166, 169, 170)); m_line_top->SetBackgroundColour(wxColour(166, 169, 170));
wxBoxSizer *m_sizer_body = new wxBoxSizer(wxHORIZONTAL);
wxBoxSizer *m_sizer_body = new wxBoxSizer(wxHORIZONTAL);
auto sm = create_scaled_bitmap("Snapmaker_Orca", nullptr, 70); auto sm = create_scaled_bitmap("Snapmaker_Orca", nullptr, 70);
m_brand = new wxStaticBitmap(this, wxID_ANY, sm, wxDefaultPosition, wxSize(FromDIP(70), FromDIP(70))); m_brand = new wxStaticBitmap(this, wxID_ANY, sm, wxDefaultPosition, wxSize(FromDIP(70), FromDIP(70)));
wxBoxSizer *m_sizer_right = new wxBoxSizer(wxVERTICAL); wxBoxSizer *m_sizer_right = new wxBoxSizer(wxVERTICAL);
m_text_up_info = new Label(this, Label::Head_14, wxEmptyString, LB_AUTO_WRAP); m_text_up_info = new Label(this, Label::Head_14, wxEmptyString, LB_AUTO_WRAP);
m_text_up_info->SetForegroundColour(wxColour(0x26, 0x2E, 0x30)); m_text_up_info->SetForegroundColour(wxColour(0x26, 0x2E, 0x30));
@@ -424,7 +410,6 @@ UpdateVersionDialog::UpdateVersionDialog(wxWindow *parent)
UpdateVersionDialog::~UpdateVersionDialog() {} UpdateVersionDialog::~UpdateVersionDialog() {}
wxWebView* UpdateVersionDialog::CreateTipView(wxWindow* parent) wxWebView* UpdateVersionDialog::CreateTipView(wxWindow* parent)
{ {
wxWebView* tipView = WebView::CreateWebView(parent, ""); wxWebView* tipView = WebView::CreateWebView(parent, "");

View File

@@ -1905,7 +1905,7 @@ void SSWCP_MachineFind_Instance::sw_StopMachineFind()
void SSWCP_MachineFind_Instance::add_machine_to_list(const json& machine_info) void SSWCP_MachineFind_Instance::add_machine_to_list(const json& machine_info)
{ {
try { try {
BOOST_LOG_TRIVIAL(info) << "TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT" << machine_info.dump(); BOOST_LOG_TRIVIAL(info) << "check the machine list on json: " << machine_info.dump();
for (const auto& [key, value] : machine_info.items()) { for (const auto& [key, value] : machine_info.items()) {
std::string sn = value["sn"].get<std::string>(); std::string sn = value["sn"].get<std::string>();
bool need_send = false; bool need_send = false;
@@ -1928,7 +1928,7 @@ void SSWCP_MachineFind_Instance::add_machine_to_list(const json& machine_info)
m_res_data[key]["connected"] = true; m_res_data[key]["connected"] = true;
} }
std::string ip = value["ip"].get<std::string>(); std::string ip = value["ip"].get<std::string>();
if (info.ip != ip && info.link_mode != "wan") { if (0) {
info.ip = ip; info.ip = ip;
wxGetApp().app_config->save_device_info(info); wxGetApp().app_config->save_device_info(info);

View File

@@ -92,8 +92,6 @@ bool MsgUpdateSlic3r::disable_version_check() const
return true; return true;
} }
// MsgUpdateConfig
MsgUpdateConfig::MsgUpdateConfig(const std::vector<Update> &updates, bool force_before_wizard /* = false*/) MsgUpdateConfig::MsgUpdateConfig(const std::vector<Update> &updates, bool force_before_wizard /* = false*/)
: DPIDialog(wxGetApp().mainframe, wxID_ANY, _L("Configuration update"), wxDefaultPosition, wxDefaultSize, wxCAPTION) : DPIDialog(wxGetApp().mainframe, wxID_ANY, _L("Configuration update"), wxDefaultPosition, wxDefaultSize, wxCAPTION)
{ {
@@ -123,7 +121,6 @@ MsgUpdateConfig::MsgUpdateConfig(const std::vector<Update> &updates, bool force_
wxBoxSizer *m_sizer_right = new wxBoxSizer(wxVERTICAL); wxBoxSizer *m_sizer_right = new wxBoxSizer(wxVERTICAL);
auto m_text_up_info = new wxStaticText(this, wxID_ANY, _L("A new configuration package is available. Do you want to install it?"), wxDefaultPosition, wxDefaultSize, 0); auto m_text_up_info = new wxStaticText(this, wxID_ANY, _L("A new configuration package is available. Do you want to install it?"), wxDefaultPosition, wxDefaultSize, 0);
m_text_up_info->SetFont(::Label::Head_14); m_text_up_info->SetFont(::Label::Head_14);
m_text_up_info->SetForegroundColour(wxColour(0x26, 0x2E, 0x30)); m_text_up_info->SetForegroundColour(wxColour(0x26, 0x2E, 0x30));
@@ -179,17 +176,12 @@ MsgUpdateConfig::MsgUpdateConfig(const std::vector<Update> &updates, bool force_
wxBoxSizer *content_sizer = new wxBoxSizer(wxVERTICAL); wxBoxSizer *content_sizer = new wxBoxSizer(wxVERTICAL);
const auto lang_code = wxGetApp().current_language_code_safe().ToStdString(); const auto lang_code = wxGetApp().current_language_code_safe().ToStdString();
auto *versions = new wxBoxSizer(wxVERTICAL); auto *versions = new wxBoxSizer(wxVERTICAL);
// BBS: use changelog string instead of url // BBS: use changelog string instead of url
wxStaticText *changelog_textctrl = new wxStaticText(m_scrollwindw_release_note, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(FromDIP(560), -1)); wxStaticText *changelog_textctrl = new wxStaticText(m_scrollwindw_release_note, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(FromDIP(560), -1));
for (const auto &update : updates) { for (const auto &update : updates) {
auto* versions = new wxBoxSizer(wxVERTICAL); auto* versions = new wxBoxSizer(wxVERTICAL);
wxStaticText* changelog_textctrl = new wxStaticText(m_scrollwindw_release_note, wxID_ANY, wxEmptyString, wxDefaultPosition, wxStaticText* changelog_textctrl = new wxStaticText(m_scrollwindw_release_note, wxID_ANY, wxEmptyString, wxDefaultPosition,
@@ -214,12 +206,8 @@ MsgUpdateConfig::MsgUpdateConfig(const std::vector<Update> &updates, bool force_
versions->Add(flex); versions->Add(flex);
//auto change_log = new wxStaticText(m_scrollwindw_release_note, wxID_ANY, from_u8(update.change_log), wxDefaultPosition, wxDefaultSize);
changelog_textctrl->SetLabel(changelog_textctrl->GetLabel() + wxString::Format("%s\n", from_u8(update.change_log)));
// BBS: use changelog string instead of url
//auto change_log = new wxStaticText(m_scrollwindw_release_note, wxID_ANY, from_u8(update.change_log), wxDefaultPosition, wxDefaultSize);
changelog_textctrl->SetLabel(changelog_textctrl->GetLabel() + wxString::Format("%s\n", from_u8(update.change_log)));
content_sizer->Add(versions); content_sizer->Add(versions);
@@ -227,16 +215,13 @@ MsgUpdateConfig::MsgUpdateConfig(const std::vector<Update> &updates, bool force_
if (changelog_textctrl) if (changelog_textctrl)
content_sizer->Add(changelog_textctrl, 1, wxEXPAND | wxTOP, FromDIP(30)); content_sizer->Add(changelog_textctrl, 1, wxEXPAND | wxTOP, FromDIP(30));
} }
m_butto_ok->Bind(wxEVT_BUTTON, [this](const wxCommandEvent &) { EndModal(wxID_OK); }); m_butto_ok->Bind(wxEVT_BUTTON, [this](const wxCommandEvent &) { EndModal(wxID_OK); });
m_button_cancel->Bind(wxEVT_BUTTON, [this](const wxCommandEvent &) { EndModal(wxID_CLOSE); }); m_button_cancel->Bind(wxEVT_BUTTON, [this](const wxCommandEvent &) { EndModal(wxID_CLOSE); });
m_scrollwindw_release_note->SetSizer(content_sizer); m_scrollwindw_release_note->SetSizer(content_sizer);
m_scrollwindw_release_note->Layout(); m_scrollwindw_release_note->Layout();
SetSizer(m_sizer_main); SetSizer(m_sizer_main);
Layout(); Layout();
m_sizer_main->Fit(this); m_sizer_main->Fit(this);

View File

@@ -61,10 +61,6 @@ public:
// force_before_wizard - indicates that check of updated is forced before ConfigWizard opening // force_before_wizard - indicates that check of updated is forced before ConfigWizard opening
MsgUpdateConfig(const std::vector<Update> &updates, bool force_before_wizard = false); MsgUpdateConfig(const std::vector<Update> &updates, bool force_before_wizard = false);
void on_dpi_changed(const wxRect &suggested_rect); void on_dpi_changed(const wxRect &suggested_rect);
// MsgUpdateConfig(MsgUpdateConfig &&) = delete;
//MsgUpdateConfig(const MsgUpdateConfig &) = delete;
//MsgUpdateConfig &operator=(MsgUpdateConfig &&) = delete;
//MsgUpdateConfig &operator=(const MsgUpdateConfig &) = delete;
~MsgUpdateConfig(); ~MsgUpdateConfig();
}; };

View File

@@ -91,7 +91,7 @@ SMUserLogin::SMUserLogin(bool isLogout) : wxDialog((wxWindow *) (wxGetApp().main
Bind(wxEVT_WEBVIEW_NEWWINDOW, &SMUserLogin::OnNewWindow, this, m_browser->GetId()); Bind(wxEVT_WEBVIEW_NEWWINDOW, &SMUserLogin::OnNewWindow, this, m_browser->GetId());
Bind(wxEVT_WEBVIEW_TITLE_CHANGED, &SMUserLogin::OnTitleChanged, this, m_browser->GetId()); Bind(wxEVT_WEBVIEW_TITLE_CHANGED, &SMUserLogin::OnTitleChanged, this, m_browser->GetId());
Bind(wxEVT_WEBVIEW_FULLSCREEN_CHANGED, &SMUserLogin::OnFullScreenChanged, this, m_browser->GetId()); Bind(wxEVT_WEBVIEW_FULLSCREEN_CHANGED, &SMUserLogin::OnFullScreenChanged, this, m_browser->GetId());
Bind(wxEVT_WEBVIEW_SCRIPT_MESSAGE_RECEIVED, &SMUserLogin::OnScriptMessage, this, m_browser->GetId()); //Bind(wxEVT_WEBVIEW_SCRIPT_MESSAGE_RECEIVED, &SMUserLogin::OnScriptMessage, this, m_browser->GetId());
// Connect the idle events // Connect the idle events
// Bind(wxEVT_IDLE, &SMUserLogin::OnIdle, this); // Bind(wxEVT_IDLE, &SMUserLogin::OnIdle, this);
@@ -305,7 +305,6 @@ void SMUserLogin::OnScriptMessage(wxWebViewEvent &evt)
} }
if (strCmd == "user_login") { if (strCmd == "user_login") {
j["data"]["autotest_token"] = m_AutotestToken; j["data"]["autotest_token"] = m_AutotestToken;
wxGetApp().handle_script_message(j.dump());
Close(); Close();
} }
else if (strCmd == "get_localhost_url") { else if (strCmd == "get_localhost_url") {

View File

@@ -279,7 +279,6 @@ void ZUserLogin::OnScriptMessage(wxWebViewEvent &evt)
} }
if (strCmd == "user_login") { if (strCmd == "user_login") {
j["data"]["autotest_token"] = m_AutotestToken; j["data"]["autotest_token"] = m_AutotestToken;
wxGetApp().handle_script_message(j.dump());
Close(); Close();
} }
else if (strCmd == "get_localhost_url") { else if (strCmd == "get_localhost_url") {

View File

@@ -181,7 +181,9 @@ struct Updates
std::vector<Update> updates; std::vector<Update> updates;
}; };
wxDEFINE_EVENT(EVT_REQUEST_SERVER_FAIL, wxCommandEvent);
wxDEFINE_EVENT(EVT_NO_WEB_RESOURCE_UPDATE, wxCommandEvent);
wxDEFINE_EVENT(EVT_NO_PRESET_UPDATE, wxCommandEvent);
wxDEFINE_EVENT(EVT_SLIC3R_VERSION_ONLINE, wxCommandEvent); wxDEFINE_EVENT(EVT_SLIC3R_VERSION_ONLINE, wxCommandEvent);
wxDEFINE_EVENT(EVT_SLIC3R_EXPERIMENTAL_VERSION_ONLINE, wxCommandEvent); wxDEFINE_EVENT(EVT_SLIC3R_EXPERIMENTAL_VERSION_ONLINE, wxCommandEvent);
@@ -201,6 +203,8 @@ struct PresetUpdater::priv
bool cancel; bool cancel;
std::thread thread; std::thread thread;
bool m_web_thread_cancel;
std::thread m_web_resource_thread;
bool has_waiting_updates { false }; bool has_waiting_updates { false };
Updates waiting_updates; Updates waiting_updates;
bool has_waiting_printer_updates { false }; bool has_waiting_printer_updates { false };
@@ -226,7 +230,9 @@ struct PresetUpdater::priv
void sync_version() const; void sync_version() const;
void parse_version_string(const std::string& body) const; void parse_version_string(const std::string& body) const;
void sync_resources(std::string http_url, std::map<std::string, Resource> &resources, bool check_patch = false, std::string current_version="", std::string changelog_file=""); void sync_resources(std::string http_url, std::map<std::string, Resource> &resources, bool check_patch = false, std::string current_version="", std::string changelog_file="");
void sync_config(); void sync_config(bool isAuto_check = true);
void sync_update_flutter_resource(bool isAuto_check = true);
bool download_file(const std::string& url, const std::string& target_path, int timeout_sec = 30, bool* cancel_flag = nullptr);
void sync_tooltip(std::string http_url, std::string language); void sync_tooltip(std::string http_url, std::string language);
void sync_plugins(std::string http_url, std::string plugin_version); void sync_plugins(std::string http_url, std::string plugin_version);
void sync_printer_config(std::string http_url); void sync_printer_config(std::string http_url);
@@ -263,7 +269,7 @@ void PresetUpdater::priv::set_download_prefs(AppConfig *app_config)
{ {
version_check_url = app_config->version_check_url(); version_check_url = app_config->version_check_url();
auto profile_update_url = app_config->profile_update_url(); auto profile_update_url = app_config->get_preset_upgrade_url();
if (!profile_update_url.empty()) if (!profile_update_url.empty())
enabled_config_update = true; enabled_config_update = true;
else else
@@ -649,123 +655,271 @@ void PresetUpdater::priv::sync_resources(std::string http_url, std::map<std::str
} }
} }
} }
bool PresetUpdater::priv::download_file(const std::string& url,
// Orca: sync config update for currect App version const std::string& target_path,
void PresetUpdater::priv::sync_config() int timeout_sec,
bool* cancel_flag )
{ {
auto cache_profile_path = cache_path; bool res = false;
auto cache_profile_update_file = cache_path / "profiles_update.json";
std::string asset_name;
if (fs::exists(cache_profile_update_file)) {
try {
boost::nowide::ifstream f(cache_profile_update_file.string());
json data = json::parse(f);
if (data.contains("name"))
asset_name = data["name"].get<std::string>();
f.close();
} catch (const std::exception& ex) {
BOOST_LOG_TRIVIAL(error) << "[Orca Updater]: failed to read profiles_update.json when sync_config: " << ex.what() << std::endl;
} catch (...) {
// catch any other errors (that we have no information about)
BOOST_LOG_TRIVIAL(error) << "[Orca Updater]: unknown failure when reading profiles_update.json in sync_config" << std::endl;
}
}
AppConfig *app_config = GUI::wxGetApp().app_config;
// auto profile_update_url = app_config->profile_update_url() + "/" + Snapmaker_VERSION; fs::path tmp_path = target_path + ".tmp";
auto profile_update_url = app_config->profile_update_url();
// parse the assets section and get the latest asset by comparing the name
Http::get(profile_update_url) BOOST_LOG_TRIVIAL(info) << "Downloading file from: " << url << " to: " << target_path;
.on_error([cache_profile_path, cache_profile_update_file](std::string body, std::string error, unsigned http_status) {
// Orca: we check the response body to see if it's "Not Found", if so, it means for the current Orca version we don't have OTA Slic3r::Http::get(url)
// updates, we can delete the cache file .on_progress([cancel_flag](Slic3r::Http::Progress progress, bool& cancel_http) {
if (!body.empty()) { // BOOST_LOG_TRIVIAL(debug) << "Download progress: " << progress.dlnow << "/" << progress.dltotal;
try { if (cancel_flag && *cancel_flag) {
json j = json::parse(body); cancel_http = true;
if (j.contains("message") && j["message"].get<std::string>() == "Not Found") {
// The current Orca version does not have any OTA updates, delete the cache file
if (fs::exists(cache_profile_path / "profiles"))
fs::remove_all(cache_profile_path / "profiles");
if (fs::exists(cache_profile_update_file))
fs::remove(cache_profile_update_file);
}
} catch (...) {}
} }
BOOST_LOG_TRIVIAL(info) << format("Error getting: `%1%`: HTTP %2%, %3%", "sync_config_orca", http_status, error);
}) })
.timeout_connect(5) .on_error([&url](std::string body, std::string error, unsigned http_status) {
.on_complete([this, asset_name, cache_profile_path, cache_profile_update_file](std::string body, unsigned http_status) { BOOST_LOG_TRIVIAL(error) << "Download failed: " << url << ", HTTP status: " << http_status << ", error: " << error;
})
.on_complete([&](std::string body, unsigned http_status) {
if (http_status != 200) {
BOOST_LOG_TRIVIAL(error) << "Download failed with HTTP status: " << http_status;
return;
}
fs::path target(target_path);
if (!fs::exists(target.parent_path())) {
fs::create_directories(target.parent_path());
}
fs::fstream file(tmp_path, std::ios::out | std::ios::binary | std::ios::trunc);
if (!file.is_open()) {
BOOST_LOG_TRIVIAL(error) << "Failed to open file for writing: " << tmp_path;
return;
}
file.write(body.c_str(), body.size());
file.close();
boost::system::error_code ec;
fs::rename(tmp_path, target_path, ec);
if (ec) {
BOOST_LOG_TRIVIAL(error) << "Failed to rename temp file: " << ec.message();
return;
}
extract_file(target_path, "../ota/profiles/");
BOOST_LOG_TRIVIAL(info) << "Download completed: " << target_path;
res = true;
})
.timeout_max(timeout_sec)
.perform_sync();
if (fs::exists(tmp_path)) {
fs::remove(tmp_path);
}
return res;
}
void PresetUpdater::priv::sync_update_flutter_resource(bool isAuto_check)
{
auto cache_profile_path = cache_path;
AppConfig* app_config = GUI::wxGetApp().app_config;
auto preset_update_url = app_config->get_web_resource_upgrade_url();
Http::get(preset_update_url)
.on_error([cache_profile_path, isAuto_check](std::string body, std::string error, unsigned http_status) {
wxCommandEvent* evt = new wxCommandEvent(EVT_REQUEST_SERVER_FAIL);
wxString errorMsg = wxString::Format(_L("request to server update web resource fail with body:%s,error:%s,status:%d"), body, error, http_status);
evt->SetString(errorMsg);
if (!isAuto_check)
GUI::wxGetApp().QueueEvent(evt);
BOOST_LOG_TRIVIAL(info) << format("Error getting: `%1%`: HTTP %2%, %3%", "sync_update_flutter_resource", http_status, error);
})
.timeout_connect(TIMEOUT_CONNECT)
.on_complete([this, cache_profile_path, isAuto_check](std::string body, unsigned http_status) {
// Http response OK // Http response OK
if (http_status != 200) if (http_status != 200)
return; return;
try { try {
json j = json::parse(body); json jsonObj = json::parse(body);
auto errCode = jsonObj["code"];
struct update if (errCode != 200)
{
std::string url;
std::string name;
int ver = -9999;
} latest_update;
if (!(j.contains("message") && j["message"].get<std::string>() == "Not Found")) {
json assets = j.at("assets");
if (assets.is_array()) {
for (auto asset : assets) {
std::string name = asset["name"].get<std::string>();
int versionNumber = -1;
std::regex regexPattern("Snapmaker_Orca-profiles_ota_.*\\.([0-9]+)\\.zip$");
std::smatch matches;
if (std::regex_search(name, matches, regexPattern) && matches.size() > 1) {
versionNumber = std::stoi(matches[1].str());
}
if (versionNumber > 0 && versionNumber > latest_update.ver) {
latest_update.url = asset["browser_download_url"].get<std::string>();
latest_update.name = name;
latest_update.ver = versionNumber;
}
}
}
}
if (cancel)
return; return;
if (latest_update.ver > 0) { auto dataObj = jsonObj.value("data", json::object());
if (latest_update.name == asset_name) auto buildNumer = dataObj.value("build_number", "");
return; auto minSupportPcVersion = dataObj.value("min_support_pc_version", "");
if (fs::exists(cache_profile_path / "profiles")) auto maxSupportPcVersion = dataObj.value("max_support_pc_version", "");
fs::remove_all(cache_profile_path / "profiles");
fs::create_directories(cache_profile_path / "profiles");
// download the file
std::string download_url = latest_update.url;
std::string download_file = (cache_path / (latest_update.name + TMP_EXTENSION)).string();
if (!get_file(download_url, download_file)) {
return;
}
// extract the file downloaded auto isForceUpgrade = dataObj.value("is_force_upgrade", false);
BOOST_LOG_TRIVIAL(info) << "[Orca Updater]start to unzip the downloaded file " << download_file; auto fileVersion = dataObj.value("file_version", "");
if (!extract_file(download_file, cache_profile_path)) { auto fileSize = dataObj.value("file_size", 0);
BOOST_LOG_TRIVIAL(warning) << "[Orca Updater]extract downloaded file" auto fileMd5 = dataObj.value("file_md5", "");
<< " failed, path: " << download_file; auto fileSha256 = dataObj.value("file_sha256", "");
return; auto fileUrl = dataObj.value("file_url", "");
auto description = dataObj.value("file_describe", "");
auto reservedData = dataObj.value("reserved_1", "");
auto reservedData2 = dataObj.value("reserved_2", "");
auto localProfilesjson = cache_path / "flutter_web/version.json";
std::string json_path = data_dir() + "/web/flutter_web/version.json";
std::string fileName = cache_profile_path.string() + "/flutter_web.zip";
Semver currentPresetVersion = get_version_from_json(json_path);
Semver remoteVersion(fileVersion);
Semver minSpVersion(minSupportPcVersion);
Semver maxSpVersion(maxSupportPcVersion);
std::regex matcher("[0-9]+\\.[0-9]+(\\.[0-9]+)*(-[A-Za-z0-9]+)?(\\+[A-Za-z0-9]+)?");
auto get_version = [this](const std::string& str, const std::regex& regexp)
{
std::smatch match;
if (std::regex_match(str, match, regexp)) {
std::string version_cleaned = match[0];
const boost::optional<Semver> version = Semver::parse(version_cleaned);
if (version.has_value()) {
return *version;
}
} }
BOOST_LOG_TRIVIAL(info) << "[Orca Updater]finished unzip the downloaded file " << download_file; return Semver::invalid();
boost::nowide::ofstream f(cache_profile_update_file.string()); };
json data;
data["name"] = latest_update.name; Semver currentSoftVersion = get_version(Snapmaker_VERSION, matcher);
f << data << std::endl;
f.close(); if (fileVersion.empty())
} else { {
// The current Orca version does not have any OTA updates, delete the cache file if (!isAuto_check) {
if (fs::exists(cache_profile_path / "profiles")) wxCommandEvent* evt = new wxCommandEvent(EVT_NO_WEB_RESOURCE_UPDATE);
fs::remove_all(cache_profile_path / "profiles"); GUI::wxGetApp().QueueEvent(evt);
if (fs::exists(cache_profile_update_file))
fs::remove(cache_profile_update_file); BOOST_LOG_TRIVIAL(info) << format("use check the web update.");
}
return;
} }
if (currentSoftVersion > maxSpVersion || currentSoftVersion < minSpVersion) {
if (!isAuto_check) {
wxCommandEvent* evt = new wxCommandEvent(EVT_NO_PRESET_UPDATE);
GUI::wxGetApp().QueueEvent(evt);
BOOST_LOG_TRIVIAL(info) << format("use check the web update.");
}
return;
}
if (currentPresetVersion < remoteVersion)
download_file(fileUrl, fileName);
else {
if (!isAuto_check) {
wxCommandEvent* evt = new wxCommandEvent(EVT_NO_WEB_RESOURCE_UPDATE);
GUI::wxGetApp().QueueEvent(evt);
BOOST_LOG_TRIVIAL(info) << format("use check the web update local no profiles.");
}
}
} catch (...) {}
})
.perform_sync();
}
// Orca: sync config update for currect App version
void PresetUpdater::priv::sync_config(bool isAuto_check)
{
auto cache_profile_path = cache_path;
AppConfig *app_config = GUI::wxGetApp().app_config;
auto profile_update_url = app_config->get_preset_upgrade_url();
// parse the assets section and get the latest asset by comparing the name
Http::get(profile_update_url)
.on_error([cache_profile_path, isAuto_check](std::string body, std::string error, unsigned http_status) {
// Orca: we check the response body to see if it's "Not Found", if so, it means for the current Orca version we don't have OTA
// updates, we can delete the cache file
wxCommandEvent* evt = new wxCommandEvent(EVT_REQUEST_SERVER_FAIL);
wxString errorMsg = wxString::Format(_L("request to server update preset resource fail with body:%s,error:%s,status:%d"), body,error, http_status);
evt->SetString(errorMsg);
if (!isAuto_check)
GUI::wxGetApp().QueueEvent(evt);
BOOST_LOG_TRIVIAL(info) << format("Error getting: `%1%`: HTTP %2%, %3%", "sync_config_orca", http_status, error);
})
.timeout_connect(TIMEOUT_CONNECT)
.on_complete([this, cache_profile_path, isAuto_check](std::string body, unsigned http_status) {
// Http response OK
if (http_status != 200)
return;
try {
json jsonObj = json::parse(body);
auto errCode = jsonObj["code"];
if (errCode != 200)
return;
auto dataObj = jsonObj.value("data", json::object());
auto isForceUpgrade = dataObj.value("is_force_upgrade", false);
auto minSupportPcVersion = dataObj.value("min_support_pc_version", "");
auto maxSupportPcVersion = dataObj.value("max_support_pc_version", "");
auto fileVersion = dataObj.value("file_version", "");
auto fileSize = dataObj.value("file_size", 0);
auto fileMd5 = dataObj.value("file_md5", "");
auto fileSha256 = dataObj.value("file_sha256", "");
auto fileUrl = dataObj.value("file_url", "");
auto description = dataObj.value("file_describe", "");
auto reservedData = dataObj.value("reserved_1", "");
auto reservedData2 = dataObj.value("reserved_2", "");
auto localProfilesjson = cache_path / "profiles/Snapmaker.json";
std::string json_path = data_dir() + "/system/Snapmaker.json";
std::string fileName = cache_profile_path.string() + "/profiles.zip";
Semver currentPresetVersion = get_version_from_json(json_path);
Semver remoteVersion(fileVersion);
Semver minSpVersion(minSupportPcVersion);
Semver maxSpVersion(maxSupportPcVersion);
std::regex matcher("[0-9]+\\.[0-9]+(\\.[0-9]+)*(-[A-Za-z0-9]+)?(\\+[A-Za-z0-9]+)?");
auto get_version = [this](const std::string& str, const std::regex& regexp) {
std::smatch match;
if (std::regex_match(str, match, regexp)) {
std::string version_cleaned = match[0];
const boost::optional<Semver> version = Semver::parse(version_cleaned);
if (version.has_value()) {
return *version;
}
}
return Semver::invalid();
};
Semver currentSoftVersion = get_version(Snapmaker_VERSION, matcher);
if (fileVersion.empty()) {
if (!isAuto_check) {
wxCommandEvent* evt = new wxCommandEvent(EVT_NO_PRESET_UPDATE);
GUI::wxGetApp().QueueEvent(evt);
BOOST_LOG_TRIVIAL(info) << format("use check the web update.");
}
return;
}
if (currentSoftVersion > maxSpVersion || currentSoftVersion < minSpVersion)
{
if (!isAuto_check) {
wxCommandEvent* evt = new wxCommandEvent(EVT_NO_PRESET_UPDATE);
GUI::wxGetApp().QueueEvent(evt);
BOOST_LOG_TRIVIAL(info) << format("use check the web update.");
}
return;
}
if (currentPresetVersion < remoteVersion)
download_file(fileUrl, fileName);
else {
if (!isAuto_check) {
wxCommandEvent* evt = new wxCommandEvent(EVT_NO_PRESET_UPDATE);
GUI::wxGetApp().QueueEvent(evt);
BOOST_LOG_TRIVIAL(info) << format("use check the preset update local no profiles.");
}
}
} catch (...) {} } catch (...) {}
}) })
.perform_sync(); .perform_sync();
@@ -1384,6 +1538,12 @@ PresetUpdater::~PresetUpdater()
p->cancel = true; p->cancel = true;
p->thread.join(); p->thread.join();
} }
if (p && p->m_web_resource_thread.joinable())
{
p->m_web_thread_cancel = true;
p->m_web_resource_thread.join();
}
} }
//BBS: change directories by design //BBS: change directories by design
@@ -1543,6 +1703,45 @@ bool PresetUpdater::install_bundles_rsrc(std::vector<std::string> bundles, bool
return p->install_bundles_rsrc(bundles, snapshot); return p->install_bundles_rsrc(bundles, snapshot);
} }
void PresetUpdater::sync_web_async(bool isAutoUpdata)
{
if (p->m_web_resource_thread.joinable()) {
p->m_web_thread_cancel = true;
p->m_web_resource_thread.join();
}
p->m_web_thread_cancel = false;
p->m_web_resource_thread = std::thread([this, isAutoUpdata]() {
BOOST_LOG_TRIVIAL(debug) << "[Orca Updater] sync_web_async started";
this->p->sync_update_flutter_resource(isAutoUpdata);
GUI::wxGetApp().CallAfter([this] {
std::string zipfilepath = this->p->cache_path.string() + "/flutter_web.zip";
BOOST_LOG_TRIVIAL(debug) << "[Orca Updater] sync_web_async completed, checking updates...";
load_lutter_web(zipfilepath, true);
});
});
}
void PresetUpdater::sync_config_async()
{
if (p->thread.joinable()) {
p->cancel = true;
p->thread.join();
}
p->cancel = false;
p->thread = std::thread([this]() {
BOOST_LOG_TRIVIAL(debug) << "[Orca Updater] sync_config_async started";
this->p->sync_config(false);
GUI::wxGetApp().CallAfter([] {
BOOST_LOG_TRIVIAL(debug) << "[Orca Updater] sync_config_async completed, checking updates...";
GUI::wxGetApp().check_config_updates_from_updater(true);
});
});
}
void PresetUpdater::on_update_notification_confirm() void PresetUpdater::on_update_notification_confirm()
{ {
if (!p->has_waiting_updates) if (!p->has_waiting_updates)
@@ -1602,31 +1801,21 @@ bool PresetUpdater::version_check_enabled() const
return p->enabled_version_check; return p->enabled_version_check;
} }
void PresetUpdater::import_flutter_web()
void PresetUpdater::load_lutter_web(const std::string& zip_file, bool serverUpdate)
{ {
// 1. 弹出文件选择框
wxFileDialog dialog(nullptr, _L("Please choose a web resource package file:"), "", "", "resource packages (*.zip)|*.zip",
wxFD_OPEN | wxFD_FILE_MUST_EXIST);
if (dialog.ShowModal() != wxID_OK)
return;
std::string zip_file = dialog.GetPath().ToUTF8().data();
// 2. 创建临时目录用于解压
boost::filesystem::path temp_path = boost::filesystem::temp_directory_path() / "orca_temp_flutter_import"; boost::filesystem::path temp_path = boost::filesystem::temp_directory_path() / "orca_temp_flutter_import";
try { try {
if (boost::filesystem::exists(temp_path)) if (boost::filesystem::exists(temp_path))
boost::filesystem::remove_all(temp_path); boost::filesystem::remove_all(temp_path);
boost::filesystem::create_directories(temp_path); boost::filesystem::create_directories(temp_path);
// 3. 解压zip文件到临时目录
if (!p->extract_file(zip_file, temp_path.string())) { if (!p->extract_file(zip_file, temp_path.string())) {
GUI::MessageDialog(nullptr, _L("Import Failed")).ShowModal(); if (!serverUpdate)
GUI::MessageDialog(nullptr, _L("Import Failed")).ShowModal();
return; return;
} }
// 4. 检查版本并导入
std::vector<std::string> outdated_presets; std::vector<std::string> outdated_presets;
Updates updates; Updates updates;
@@ -1635,40 +1824,33 @@ void PresetUpdater::import_flutter_web()
GUI::MessageDialog(nullptr, _L("Import Failed")).ShowModal(); GUI::MessageDialog(nullptr, _L("Import Failed")).ShowModal();
} }
// 读取当前flutter资源包版本 std::string ori_version_str = "0";
std::string ori_version_str = "0";
std::string ori_build_number_str = "0"; std::string ori_build_number_str = "0";
auto ori_version_file = boost::filesystem::path(data_dir()) / "web" / "flutter_web" / "version.json"; auto ori_version_file = boost::filesystem::path(data_dir()) / "web" / "flutter_web" / "version.json";
boost::property_tree::ptree ori_config; boost::property_tree::ptree ori_config;
boost::property_tree::read_json(ori_version_file.string(), ori_config); boost::property_tree::read_json(ori_version_file.string(), ori_config);
ori_version_str = ori_config.get<std::string>("version", "0"); ori_version_str = ori_config.get<std::string>("version", "0");
ori_build_number_str = ori_config.get<std::string>("build_number", "0"); ori_build_number_str = ori_config.get<std::string>("build_number", "0");
// 遍历解压的文件夹
for (auto& dir_entry : boost::filesystem::directory_iterator(temp_path / "flutter_web")) { for (auto& dir_entry : boost::filesystem::directory_iterator(temp_path / "flutter_web")) {
if (dir_entry.path().filename() == "version.json") { if (dir_entry.path().filename() == "version.json") {
try { try {
// 读取json文件获取版本信息
boost::property_tree::ptree config; boost::property_tree::ptree config;
boost::property_tree::read_json(dir_entry.path().string(), config); boost::property_tree::read_json(dir_entry.path().string(), config);
std::string version_str = config.get<std::string>("version", "0"); std::string version_str = config.get<std::string>("version", "0");
std::string build_number_str = config.get<std::string>("build_number", "0"); std::string build_number_str = config.get<std::string>("build_number", "0");
// std::string vendor = dir_entry.path().stem().string();
// 使用 Semver 进行版本比较
Semver online_version = version_str; Semver online_version = version_str;
Semver current_version = ori_version_str; Semver current_version = ori_version_str;
if (/* current_version < online_version && */ori_build_number_str < build_number_str) { if (/* current_version < online_version && */ ori_build_number_str < build_number_str) {
auto source_folder_path = fs::path(dir_entry.path().parent_path()); auto source_folder_path = fs::path(dir_entry.path().parent_path());
auto target_folder_path = (boost::filesystem::path(data_dir()) / "web" / "flutter_web"); auto target_folder_path = (boost::filesystem::path(data_dir()) / "web" / "flutter_web");
// 创建Version对象
Version version; Version version;
version.config_version = online_version; // 将Semver赋值给Version的config_version version.config_version = online_version;
// changelog // changelog
std::string changelog = ""; std::string changelog = "";
@@ -1679,16 +1861,14 @@ void PresetUpdater::import_flutter_web()
oss << ifs.rdbuf(); oss << ifs.rdbuf();
changelog = oss.str(); changelog = oss.str();
ifs.close(); ifs.close();
// 替换所有的 \\n 为 \n
size_t pos = 0; size_t pos = 0;
while ((pos = changelog.find("\\n", pos)) != std::string::npos) { while ((pos = changelog.find("\\n", pos)) != std::string::npos) {
changelog.replace(pos, 2, "\n"); changelog.replace(pos, 2, "\n");
pos += 1; // 移动到下一个可能的位置 pos += 1;
} }
} }
// 检查最小要求软件版本 Semver min_ver = get_min_version_from_json(dir_entry.path().string());
Semver min_ver = get_min_version_from_json(dir_entry.path().string());
Semver soft_ver = Semver(std::string(Snapmaker_VERSION)); Semver soft_ver = Semver(std::string(Snapmaker_VERSION));
bool legal = true; bool legal = true;
@@ -1699,13 +1879,10 @@ void PresetUpdater::import_flutter_web()
.ToStdString(); .ToStdString();
} }
// 版本较新且兼容,添加到更新列表 updates.updates.emplace_back(std::move(source_folder_path), std::move(target_folder_path), version, "flutter_web",
changelog, "", false, true, legal);
updates.updates.emplace_back(std::move(source_folder_path), std::move(target_folder_path), version, "flutter_web", changelog, "",
false, true, legal);
} else { } else {
// 版本较旧或不兼容,添加到提示列表
outdated_presets.push_back("flutter_web"); outdated_presets.push_back("flutter_web");
} }
} catch (std::exception& e) { } catch (std::exception& e) {
@@ -1715,7 +1892,6 @@ void PresetUpdater::import_flutter_web()
} }
} }
// 5. 执行更新并提示结果
bool need_restart = false; bool need_restart = false;
if (!updates.updates.empty()) { if (!updates.updates.empty()) {
std::vector<GUI::MsgUpdateConfig::Update> updates_msg; std::vector<GUI::MsgUpdateConfig::Update> updates_msg;
@@ -1744,7 +1920,7 @@ void PresetUpdater::import_flutter_web()
} }
wxString message; wxString message;
if (!outdated_presets.empty()) { if (!outdated_presets.empty() && !serverUpdate) {
message = _L("This web resouce could not be imported due to outdated versions.") + "\n"; message = _L("This web resouce could not be imported due to outdated versions.") + "\n";
for (const auto& preset : outdated_presets) { for (const auto& preset : outdated_presets) {
message += "" + preset + "\n"; message += "" + preset + "\n";
@@ -1752,8 +1928,6 @@ void PresetUpdater::import_flutter_web()
GUI::MessageDialog(nullptr, message).ShowModal(); GUI::MessageDialog(nullptr, message).ShowModal();
} }
if (need_restart) { if (need_restart) {
GUI::MessageDialog msg_wingow(nullptr, GUI::MessageDialog msg_wingow(nullptr,
_L("Updating the web resources requires application restart.") + "\n" + _L("Updating the web resources requires application restart.") + "\n" +
@@ -1765,17 +1939,29 @@ void PresetUpdater::import_flutter_web()
app->recreate_GUI(_L("Update web resources")); app->recreate_GUI(_L("Update web resources"));
} }
} catch (std::exception& e) { } catch (std::exception& e) {
BOOST_LOG_TRIVIAL(error) << "Failed to importweb resources: " << e.what(); BOOST_LOG_TRIVIAL(error) << "Failed to importweb resources: " << e.what();
GUI::MessageDialog(nullptr, _L("Import Failed")).ShowModal(); GUI::MessageDialog(nullptr, _L("Import Failed")).ShowModal();
} }
// 6. 清理临时目录
boost::filesystem::remove_all(temp_path); boost::filesystem::remove_all(temp_path);
} }
void PresetUpdater::import_flutter_web()
{
wxFileDialog dialog(nullptr, _L("Please choose a web resource package file:"), "", "", "resource packages (*.zip)|*.zip",
wxFD_OPEN | wxFD_FILE_MUST_EXIST);
if (dialog.ShowModal() != wxID_OK)
return;
std::string zip_file = dialog.GetPath().ToUTF8().data();
load_lutter_web(zip_file);
}
void PresetUpdater::import_system_profile() void PresetUpdater::import_system_profile()
{ {
// 1. 弹出文件选择框 // 1. 弹出文件选择框
@@ -1810,7 +1996,7 @@ void PresetUpdater::import_system_profile()
} }
// 遍历解压的文件夹 // 遍历解压的文件夹
for (auto& dir_entry : boost::filesystem::directory_iterator(temp_path / "profiles")) { for (auto& dir_entry : boost::filesystem::directory_iterator(temp_path)) {
if (dir_entry.path().extension() == ".json") { if (dir_entry.path().extension() == ".json") {
try { try {
// 读取json文件获取版本信息 // 读取json文件获取版本信息

View File

@@ -65,11 +65,18 @@ public:
void import_flutter_web(); void import_flutter_web();
void load_lutter_web(const std::string& zip_file,bool serverUpdate = false);
void sync_config_async();
void sync_web_async(bool isAutoUpdata = false);
public: public:
struct priv; struct priv;
std::unique_ptr<priv> p; std::unique_ptr<priv> p;
}; };
wxDECLARE_EVENT(EVT_REQUEST_SERVER_FAIL, wxCommandEvent);
wxDECLARE_EVENT(EVT_NO_WEB_RESOURCE_UPDATE, wxCommandEvent);
wxDECLARE_EVENT(EVT_NO_PRESET_UPDATE, wxCommandEvent);
wxDECLARE_EVENT(EVT_SLIC3R_VERSION_ONLINE, wxCommandEvent); wxDECLARE_EVENT(EVT_SLIC3R_VERSION_ONLINE, wxCommandEvent);
wxDECLARE_EVENT(EVT_SLIC3R_EXPERIMENTAL_VERSION_ONLINE, wxCommandEvent); wxDECLARE_EVENT(EVT_SLIC3R_EXPERIMENTAL_VERSION_ONLINE, wxCommandEvent);