diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 1478bc3596..36e9bb2a2f 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -1241,13 +1241,14 @@ int GUI_App::download_plugin(std::string name, std::string package_name, Install // get_url std::string url = get_plugin_url(name, app_config->get_country_code()); std::string download_url; + std::string online_version; Slic3r::Http http_url = Slic3r::Http::get(url); BOOST_LOG_TRIVIAL(info) << "[download_plugin]: check the plugin from " << url; http_url.timeout_connect(TIMEOUT_CONNECT) .timeout_max(TIMEOUT_RESPONSE) .header("X-BBL-OS-Type", os_type) .on_complete( - [&download_url](std::string body, unsigned status) { + [&download_url, &online_version](std::string body, unsigned status) { try { json j = json::parse(body); std::string message = j["message"].get(); @@ -1257,6 +1258,7 @@ int GUI_App::download_plugin(std::string name, std::string package_name, Install if (resource.is_array()) { for (auto iter = resource.begin(); iter != resource.end(); iter++) { Semver version; + std::string version_str; std::string url; std::string type; std::string vendor; @@ -1267,7 +1269,8 @@ int GUI_App::download_plugin(std::string name, std::string package_name, Install BOOST_LOG_TRIVIAL(info) << "[download_plugin]: get version of settings's type, " << sub_iter.value(); } else if (boost::iequals(sub_iter.key(), "version")) { - version = *(Semver::parse(sub_iter.value())); + version_str = sub_iter.value(); + version = *(Semver::parse(version_str)); } else if (boost::iequals(sub_iter.key(), "description")) { description = sub_iter.value(); @@ -1278,6 +1281,7 @@ int GUI_App::download_plugin(std::string name, std::string package_name, Install } BOOST_LOG_TRIVIAL(info) << "[download_plugin 1]: get type " << type << ", version " << version.to_string() << ", url " << url; download_url = url; + online_version = version_str; } } } @@ -1367,6 +1371,26 @@ int GUI_App::download_plugin(std::string name, std::string package_name, Install result = -1; }); http.perform_sync(); + + // The cloud endpoint serves the newest build of the requested series, which may be + // newer than the configured version. Adopt the actual downloaded version so that + // install_plugin() names the library after what it really contains - otherwise the + // post-load config sync (on_init_network) points at a file name that does not exist + // and the plugin is "lost" on the following launch. Legacy mode is left untouched: + // is_legacy_version() matches exactly and drives the legacy struct layout. + if (result >= 0 && name == "plugins" && !online_version.empty() && !use_legacy_network_plugin()) { + std::string configured = app_config->get_network_plugin_version(); + if (configured.empty()) + configured = get_latest_network_version(); + if (configured != online_version + && configured.size() >= 8 && online_version.size() >= 8 + && configured.compare(0, 8, online_version, 0, 8) == 0) { + BOOST_LOG_TRIVIAL(info) << "[download_plugin] server returned " << online_version + << " for configured " << configured << ", adopting it"; + app_config->set_network_plugin_version(online_version); + } + } + j["result"] = result < 0 ? "failed" : "success"; j["error_msg"] = err_msg; return result; @@ -3270,7 +3294,7 @@ void GUI_App::copy_network_if_available() std::string data_dir_str = data_dir(); boost::filesystem::path data_dir_path(data_dir_str); auto plugin_folder = data_dir_path / "plugins"; - auto cache_folder = data_dir_path / "ota"; + auto cache_folder = data_dir_path / "ota" / "plugins"; std::string changelog_file = cache_folder.string() + "/network_plugins.json"; std::string cached_version; @@ -3364,8 +3388,13 @@ void GUI_App::copy_network_if_available() fs::remove(live555_library); BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": Copying live555 library from " << live555_library << " to " << live555_library_dst << " successfully."; } - if (boost::filesystem::exists(changelog_file)) - fs::remove(changelog_file); + // All cached files consumed - drop the whole ota/plugins cache folder. + try { + if (boost::filesystem::exists(cache_folder)) + fs::remove_all(cache_folder); + } catch (...) { + BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ": failed to remove the plugin cache folder " << cache_folder.string(); + } app_config->set("update_network_plugin", "false"); } diff --git a/src/slic3r/GUI/ReleaseNote.cpp b/src/slic3r/GUI/ReleaseNote.cpp index 7ff9637ee0..ef1a7ebe96 100644 --- a/src/slic3r/GUI/ReleaseNote.cpp +++ b/src/slic3r/GUI/ReleaseNote.cpp @@ -202,34 +202,45 @@ void UpdatePluginDialog::update_info(std::string json_path) wxString version; wxString description; + // Parse defensively: a missing or malformed changelog must never leave the + // dialog blank, so fall back to a generic prompt instead of returning early. try { boost::nowide::ifstream ifs(json_path); json j; ifs >> j; - version_str = j["version"]; - description_str = j["description"]; + if (j.contains("version")) + version_str = j["version"]; + if (j.contains("description")) + description_str = j["description"]; } - catch (nlohmann::detail::parse_error& err) { - BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ": parse " << json_path << " got a nlohmann::detail::parse_error, reason = " << err.what(); - return; + catch (std::exception& err) { + BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ": parse " << json_path << " failed, reason = " << err.what(); } version = from_u8(version_str); description = from_u8(description_str); - m_text_up_info->SetLabel(wxString::Format(_L("A new Network plug-in (%s) is available. Do you want to install it?"), version)); + if (version.IsEmpty()) + m_text_up_info->SetLabel(_L("A new Network plug-in is available. Do you want to install it?")); + else + m_text_up_info->SetLabel(wxString::Format(_L("A new Network plug-in (%s) is available. Do you want to install it?"), version)); m_text_up_info->SetMinSize(wxSize(FromDIP(260), -1)); m_text_up_info->SetMaxSize(wxSize(FromDIP(260), -1)); - wxBoxSizer* sizer_text_release_note = new wxBoxSizer(wxVERTICAL); - auto m_text_label = new ::Label(m_vebview_release_note, Label::Body_13, description, LB_AUTO_WRAP); - m_text_label->SetMinSize(wxSize(FromDIP(235), -1)); - m_text_label->SetMaxSize(wxSize(FromDIP(235), -1)); - sizer_text_release_note->Add(m_text_label, 0, wxALL, 5); - m_vebview_release_note->SetSizer(sizer_text_release_note); - m_vebview_release_note->Layout(); - m_vebview_release_note->Fit(); + if (description.IsEmpty()) { + m_vebview_release_note->Hide(); + } else { + wxBoxSizer* sizer_text_release_note = new wxBoxSizer(wxVERTICAL); + auto m_text_label = new ::Label(m_vebview_release_note, Label::Body_13, description, LB_AUTO_WRAP); + m_text_label->SetMinSize(wxSize(FromDIP(235), -1)); + m_text_label->SetMaxSize(wxSize(FromDIP(235), -1)); + + sizer_text_release_note->Add(m_text_label, 0, wxALL, 5); + m_vebview_release_note->SetSizer(sizer_text_release_note); + m_vebview_release_note->Layout(); + m_vebview_release_note->Fit(); + } wxGetApp().UpdateDlgDarkUI(this); Layout(); Fit(); diff --git a/src/slic3r/Utils/PresetUpdater.cpp b/src/slic3r/Utils/PresetUpdater.cpp index 540cbaafdd..9ec57fd653 100644 --- a/src/slic3r/Utils/PresetUpdater.cpp +++ b/src/slic3r/Utils/PresetUpdater.cpp @@ -782,9 +782,9 @@ void PresetUpdater::priv::sync_tooltip(std::string http_url, std::string languag // return true means there are plugins files bool PresetUpdater::priv::get_cached_plugins_version(std::string& cached_version, bool &force) { - std::string data_dir_str = data_dir(); - boost::filesystem::path data_dir_path(data_dir_str); - auto cache_folder = data_dir_path / "ota"; + // The OTA plugin cache lives in its own ota/plugins subfolder; the update dialog + // (Plater::priv::update_plugin_when_launch) reads the changelog from the same place. + auto cache_folder = cache_path / "plugins"; std::string network_library, player_library, live555_library; bool has_plugins = false; @@ -838,6 +838,25 @@ void PresetUpdater::priv::sync_plugins(std::string http_url, std::string plugin_ } std::string curr_version = GUI::wxGetApp().use_legacy_network_plugin() ? BAMBU_NETWORK_AGENT_VERSION_LEGACY : get_latest_network_version(); std::string using_version = curr_version.substr(0, 9) + "00"; + auto cache_plugin_folder = cache_path / "plugins"; + + // Orca: drop leftovers from the old flat ota/ cache layout (pre ota/plugins) so the + // stale files cannot linger forever after this layout migration. + { +#if defined(_MSC_VER) || defined(_WIN32) + const char* legacy_names[] = {"bambu_networking.dll", "BambuSource.dll", "live555.dll", "network_plugins.json"}; +#elif defined(__WXMAC__) + const char* legacy_names[] = {"libbambu_networking.dylib", "libBambuSource.dylib", "liblive555.dylib", "network_plugins.json"}; +#else + const char* legacy_names[] = {"libbambu_networking.so", "libBambuSource.so", "liblive555.so", "network_plugins.json"}; +#endif + for (const char* name : legacy_names) { + boost::system::error_code ec; + auto legacy_file = cache_path / name; + if (boost::filesystem::exists(legacy_file, ec)) + boost::filesystem::remove(legacy_file, ec); + } + } std::string cached_version; bool force_upgrade = false; @@ -868,64 +887,11 @@ void PresetUpdater::priv::sync_plugins(std::string http_url, std::string plugin_ } if (need_delete_cache) { - std::string data_dir_str = data_dir(); - boost::filesystem::path data_dir_path(data_dir_str); - auto cache_folder = data_dir_path / "ota"; - -#if defined(_MSC_VER) || defined(_WIN32) - auto network_library = cache_folder / "bambu_networking.dll"; - auto player_library = cache_folder / "BambuSource.dll"; - auto live555_library = cache_folder / "live555.dll"; -#elif defined(__WXMAC__) - auto network_library = cache_folder / "libbambu_networking.dylib"; - auto player_library = cache_folder / "libBambuSource.dylib"; - auto live555_library = cache_folder / "liblive555.dylib"; -#else - auto network_library = cache_folder / "libbambu_networking.so"; - auto player_library = cache_folder / "libBambuSource.so"; - auto live555_library = cache_folder / "liblive555.so"; -#endif - auto changelog_file = cache_folder / "network_plugins.json"; - - if (boost::filesystem::exists(network_library)) - { - - BOOST_LOG_TRIVIAL(info) << "[remove_old_networking_plugins] remove the file "< resources { - {"slicer/plugins/cloud", { using_version, "", "", false, cache_path.string(), {"plugins"}}} + {"slicer/plugins/cloud", { using_version, "", "", false, cache_plugin_folder.string()}} }; sync_resources(http_url, resources, true, plugin_version, "network_plugins.json"); }