mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-07-19 17:02:08 +00:00
Merge remote-tracking branch 'upstream/main' into belt/baseChanges
This commit is contained in:
@@ -109,7 +109,7 @@ var LangText = {
|
||||
orca1: "Edit Project Info",
|
||||
orca2: "No model information",
|
||||
orca3: "Stealth Mode",
|
||||
orca4: "This stops the transmission of data to Bambu's cloud services. Users who don't use BBL machines or use LAN mode only can safely turn on this function.",
|
||||
orca4: "This disables all cloud features, including Orca Cloud profile syncing. Users who prefer to work entirely offline can enable this option.",
|
||||
orca5: "Enable Stealth Mode.",
|
||||
orca6: "Bambu Cloud",
|
||||
orca7: "Orca Cloud Account",
|
||||
@@ -117,6 +117,7 @@ var LangText = {
|
||||
orca9: "Bambu Cloud Account",
|
||||
orca10: "Not connected",
|
||||
orca11: "Connected",
|
||||
orca12: "Note: When Stealth Mode is enabled, your user profiles will not be backed up to Orca Cloud.",
|
||||
},
|
||||
ca_ES: {
|
||||
t1: "Benvingut a Orca Slicer",
|
||||
@@ -343,7 +344,6 @@ var LangText = {
|
||||
orca1: "Editar información del proyecto",
|
||||
orca2: "No hay información sobre el modelo",
|
||||
orca3: "Modo sigiloso",
|
||||
orca4: "Esta función detiene la transmisión de datos a los servicios en la nube de Bambu. Los usuarios que no utilicen máquinas BBL o que solo usen el modo LAN pueden activar esta función con seguridad.",
|
||||
orca5: "Activar modo sigiloso.",
|
||||
orca6: "Bambu Cloud",
|
||||
orca7: "Orca Cloud Account",
|
||||
@@ -461,7 +461,6 @@ var LangText = {
|
||||
orca1: "Modifica informazioni progetto",
|
||||
orca2: "Nessuna informazione sul modello",
|
||||
orca3: "Modalità invisibile",
|
||||
orca4: "Con questa modalità, la trasmissione dei dati ai servizi cloud di Bambu sarà interrotta. Gli utenti che non utilizzano macchine BBL o che usano solo la modalità LAN possono attivare questa funzione in modo sicuro.",
|
||||
orca5: "Abilita la modalità invisibile.",
|
||||
orca6: "Bambu Cloud",
|
||||
orca7: "Orca Cloud Account",
|
||||
@@ -1169,7 +1168,6 @@ var LangText = {
|
||||
orca1: "Изменить информацию",
|
||||
orca2: "Информация отсутствует",
|
||||
orca3: "Режим конфиденциальности",
|
||||
orca4: "Это остановит передачу данных в облачные сервисы Bambu. Помешает только владельцам Bambu Lab, не использующим режим «Только LAN».",
|
||||
orca5: "Включить режим конфиденциальности",
|
||||
orca6: "Bambu Cloud",
|
||||
orca7: "Orca Cloud Account",
|
||||
@@ -1386,7 +1384,6 @@ var LangText = {
|
||||
orca1: "Proje Bilgilerini Düzenle",
|
||||
orca2: "Model bilgisi yok",
|
||||
orca3: "Gizli Mod",
|
||||
orca4: "Bu, Bambu'nun bulut hizmetlerine veri iletimini durdurur. BBL makinelerini kullanmayan veya yalnızca LAN modunu kullanan kullanıcılar bu işlevi güvenle açabilir.",
|
||||
orca5: "Gizli Modu etkinleştirin.",
|
||||
orca6: "Bambu Cloud",
|
||||
orca7: "Orca Cloud Account",
|
||||
@@ -1505,7 +1502,6 @@ var LangText = {
|
||||
orca1: "Edytuj informacje o projekcie",
|
||||
orca2: "Brak informacji o modelu",
|
||||
orca3: "Tryb «Niewidzialny»",
|
||||
orca4: "To wyłączy przesyłanie danych do usług chmurowych Bambu. Użytkownicy, którzy nie korzystają z maszyn BBL lub używają tylko trybu LAN, mogą bez obaw włączyć tę opcję.",
|
||||
orca5: "Włącz tryb «Niewidzialny»",
|
||||
orca6: "Bambu Cloud",
|
||||
orca7: "Orca Cloud Account",
|
||||
@@ -1624,7 +1620,6 @@ var LangText = {
|
||||
orca1: "Editar Info do Projeto",
|
||||
orca2: "Sem informação do modelo",
|
||||
orca3: "Modo Furtivo",
|
||||
orca4: "Isso interrompe a transmissão de dados para os serviços de nuvem da Bambu. Usuários que não usam máquinas BBL ou usam somente o modo LAN podem ativar essa função com segurança.",
|
||||
orca5: "Habilita Modo Furtivo.",
|
||||
orca6: "Bambu Cloud",
|
||||
orca7: "Orca Cloud Account",
|
||||
@@ -1742,7 +1737,6 @@ var LangText = {
|
||||
orca1: "Redaguoti projekto informaciją",
|
||||
orca2: "Nėra informacijos apie modelį",
|
||||
orca3: "Slaptas režimas",
|
||||
orca4: "Tai sustabdo duomenų perdavimą į Bambu debesijos paslaugas. Vartotojai, kurie nenaudoja BBL mašinų arba naudoja tik LAN režimą, gali drąsiai įjungti šią funkciją.",
|
||||
orca5: "Įjungti slaptą režimą.",
|
||||
orca6: "Bambu Cloud",
|
||||
orca7: "Orca Cloud Account",
|
||||
|
||||
@@ -22,7 +22,9 @@
|
||||
<div id="Content">
|
||||
|
||||
<div id="FeatureText">
|
||||
<div><a tid="orca4" class="trans TextS1">This stops the transmission of data to Bambu's cloud services. Users who don't use BBL machines or use LAN mode only can safely turn on this function.</a></div>
|
||||
<div><a tid="orca4" class="trans TextS1">This disables all cloud features, including Orca Cloud profile syncing. Users who prefer to work entirely offline can enable this option.</a></div>
|
||||
<br/>
|
||||
<div><a tid="orca12" class="trans TextS2">Note: When Stealth Mode is enabled, your user profiles will not be backed up to Orca Cloud.</a></div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
@@ -93,6 +93,11 @@ bool AppConfig::get_stealth_mode()
|
||||
return get_bool("stealth_mode");
|
||||
}
|
||||
|
||||
bool AppConfig::get_hide_login_side_panel()
|
||||
{
|
||||
return get_bool("hide_login_side_panel");
|
||||
}
|
||||
|
||||
void AppConfig::reset()
|
||||
{
|
||||
m_storage.clear();
|
||||
@@ -347,6 +352,9 @@ void AppConfig::set_defaults()
|
||||
if (get("stealth_mode").empty()) {
|
||||
set_bool("stealth_mode", false);
|
||||
}
|
||||
if (get("hide_login_side_panel").empty()) {
|
||||
set_bool("hide_login_side_panel", false);
|
||||
}
|
||||
if (get("allow_abnormal_storage").empty()) {
|
||||
set_bool("allow_abnormal_storage", false);
|
||||
}
|
||||
|
||||
@@ -85,6 +85,7 @@ public:
|
||||
std::string get_language_code();
|
||||
std::string get_hms_host();
|
||||
bool get_stealth_mode();
|
||||
bool get_hide_login_side_panel();
|
||||
|
||||
// Clear and reset to defaults.
|
||||
void reset();
|
||||
|
||||
@@ -3211,18 +3211,24 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
||||
if (is_bbl_printers) {
|
||||
this->_print_first_layer_extruder_temperatures(file, print, machine_start_gcode, initial_extruder_id, true);
|
||||
}
|
||||
// Orca: when activate_air_filtration is set on any extruder, find and set the highest during_print_exhaust_fan_speed
|
||||
bool activate_air_filtration_during_print = false;
|
||||
int during_print_exhaust_fan_speed = 0;
|
||||
for (const auto &extruder : m_writer->extruders()) {
|
||||
if (m_config.activate_air_filtration.get_at(extruder.id()) && m_config.activate_air_filtration_during_print.get_at(extruder.id())) {
|
||||
activate_air_filtration_during_print = true;
|
||||
during_print_exhaust_fan_speed = std::max(during_print_exhaust_fan_speed,
|
||||
m_config.during_print_exhaust_fan_speed.get_at(extruder.id()));
|
||||
|
||||
// Orca: when air filtration is supported, check if it needs to be activated during printing and set the exhaust fan speed accordingly
|
||||
if (m_config.support_air_filtration.value) {
|
||||
bool activate_air_filtration_during_print = false;
|
||||
int during_print_exhaust_fan_speed = 0;
|
||||
|
||||
// Orca: when activate_air_filtration is set on any extruder, find and set the highest during_print_exhaust_fan_speed
|
||||
for (const auto &extruder : m_writer->extruders()) {
|
||||
if (m_config.activate_air_filtration.get_at(extruder.id()) && m_config.activate_air_filtration_during_print.get_at(extruder.id())) {
|
||||
activate_air_filtration_during_print = true;
|
||||
during_print_exhaust_fan_speed = std::max(during_print_exhaust_fan_speed,
|
||||
m_config.during_print_exhaust_fan_speed.get_at(extruder.id()));
|
||||
}
|
||||
}
|
||||
|
||||
if (activate_air_filtration_during_print)
|
||||
file.write(m_writer->set_exhaust_fan(during_print_exhaust_fan_speed));
|
||||
}
|
||||
if (activate_air_filtration_during_print)
|
||||
file.write(m_writer->set_exhaust_fan(during_print_exhaust_fan_speed, true));
|
||||
|
||||
print.throw_if_canceled();
|
||||
|
||||
@@ -3523,16 +3529,23 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
||||
if (activate_chamber_temp_control && max_chamber_temp > 0)
|
||||
file.write(m_writer->set_chamber_temperature(0, false)); //close chamber_temperature
|
||||
|
||||
bool activate_air_filtration_on_completion = false;
|
||||
int complete_print_exhaust_fan_speed = 0;
|
||||
for (const auto& extruder : m_writer->extruders()) {
|
||||
if (m_config.activate_air_filtration.get_at(extruder.id()) && m_config.activate_air_filtration_on_completion.get_at(extruder.id())) {
|
||||
activate_air_filtration_on_completion = true;
|
||||
complete_print_exhaust_fan_speed = std::max(complete_print_exhaust_fan_speed, m_config.complete_print_exhaust_fan_speed.get_at(extruder.id()));
|
||||
// Orca: when air filtration is supported, check if it needs to be activated after print completion and set the exhaust fan speed accordingly
|
||||
if (m_config.support_air_filtration.value) {
|
||||
bool activate_air_filtration_on_completion = false;
|
||||
int complete_print_exhaust_fan_speed = 0;
|
||||
|
||||
// Orca: when activate_air_filtration is set on any extruder, find and set the highest complete_print_exhaust_fan_speed
|
||||
for (const auto& extruder : m_writer->extruders()) {
|
||||
if (m_config.activate_air_filtration.get_at(extruder.id()) && m_config.activate_air_filtration_on_completion.get_at(extruder.id())) {
|
||||
activate_air_filtration_on_completion = true;
|
||||
complete_print_exhaust_fan_speed = std::max(complete_print_exhaust_fan_speed, m_config.complete_print_exhaust_fan_speed.get_at(extruder.id()));
|
||||
}
|
||||
}
|
||||
|
||||
if (activate_air_filtration_on_completion)
|
||||
file.write(m_writer->set_exhaust_fan(complete_print_exhaust_fan_speed));
|
||||
}
|
||||
if (activate_air_filtration_on_completion)
|
||||
file.write(m_writer->set_exhaust_fan(complete_print_exhaust_fan_speed, true));
|
||||
|
||||
// adds tags for time estimators
|
||||
file.write_format(";%s\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Last_Line_M73_Placeholder).c_str());
|
||||
file.write_format("; EXECUTABLE_BLOCK_END\n\n");
|
||||
|
||||
@@ -1206,13 +1206,19 @@ std::string GCodeWriter::set_additional_fan(unsigned int speed)
|
||||
return gcode.str();
|
||||
}
|
||||
|
||||
std::string GCodeWriter::set_exhaust_fan( int speed,bool add_eol)
|
||||
std::string GCodeWriter::set_exhaust_fan(int speed)
|
||||
{
|
||||
std::ostringstream gcode;
|
||||
gcode << "M106" << " P3" << " S" << (int)(speed / 100.0 * 255);
|
||||
|
||||
if(add_eol)
|
||||
gcode << "\n";
|
||||
if (GCodeWriter::full_gcode_comment) {
|
||||
if (speed == 0)
|
||||
gcode << " ; disable exhaust fan ";
|
||||
else
|
||||
gcode << " ; enable exhaust fan ";
|
||||
}
|
||||
|
||||
gcode << "\n";
|
||||
return gcode.str();
|
||||
}
|
||||
|
||||
|
||||
@@ -106,7 +106,7 @@ public:
|
||||
std::string set_fan(unsigned int speed) const;
|
||||
//BBS: set additional fan speed for BBS machine only
|
||||
static std::string set_additional_fan(unsigned int speed);
|
||||
static std::string set_exhaust_fan(int speed,bool add_eol);
|
||||
static std::string set_exhaust_fan(int speed);
|
||||
//BBS
|
||||
void set_object_start_str(std::string start_string) { m_gcode_label_objects_start = start_string; }
|
||||
bool is_object_start_str_empty() { return m_gcode_label_objects_start.empty(); }
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <boost/chrono/duration.hpp>
|
||||
#include <boost/log/detail/native_typeof.hpp>
|
||||
#include <libslic3r/Config.hpp>
|
||||
#include <mutex>
|
||||
#include <wx/event.h>
|
||||
|
||||
// Localization headers: include libslic3r version first so everything in this file
|
||||
@@ -4508,21 +4509,46 @@ std::string GUI_App::handle_web_request(std::string cmd)
|
||||
boost::optional<std::string> command = root.get_optional<std::string>("command");
|
||||
if (command.has_value()) {
|
||||
std::string command_str = command.value();
|
||||
static const std::unordered_set<std::string> stealth_blocked_commands = {
|
||||
static const std::unordered_set<std::string> stealth_blocked_info_commands = {
|
||||
"get_login_info",
|
||||
"get_orca_login_info",
|
||||
"get_bambu_login_info",
|
||||
};
|
||||
static const std::unordered_set<std::string> stealth_blocked_login_commands = {
|
||||
"homepage_login_or_register",
|
||||
"homepage_orca_login_or_register",
|
||||
"homepage_bambu_login_or_register",
|
||||
};
|
||||
if (app_config->get_stealth_mode() && stealth_blocked_commands.count(command_str)) {
|
||||
if (app_config->get_stealth_mode() && stealth_blocked_info_commands.count(command_str)) {
|
||||
CallAfter([this] {
|
||||
if (mainframe && mainframe->m_webview)
|
||||
mainframe->m_webview->SendCloudProvidersInfo();
|
||||
});
|
||||
return "";
|
||||
}
|
||||
if (app_config->get_stealth_mode() && stealth_blocked_login_commands.count(command_str)) {
|
||||
CallAfter([this, command_str] {
|
||||
MessageDialog dlg(mainframe,
|
||||
_L("You are currently in Stealth Mode. To log into the Cloud, you need to disable Stealth Mode first."),
|
||||
_L("Stealth Mode"),
|
||||
wxOK | wxCANCEL | wxCENTRE);
|
||||
dlg.SetButtonLabel(wxID_OK, _L("Quit Stealth Mode"));
|
||||
if (dlg.ShowModal() == wxID_OK) {
|
||||
app_config->set_bool("stealth_mode", false);
|
||||
app_config->save();
|
||||
if (mainframe && mainframe->m_webview)
|
||||
mainframe->m_webview->SendCloudProvidersInfo();
|
||||
// Continue with login
|
||||
if (command_str == "homepage_login_or_register")
|
||||
this->request_login(true);
|
||||
else if (command_str == "homepage_orca_login_or_register")
|
||||
this->request_login(true, ORCA_CLOUD_PROVIDER);
|
||||
else if (command_str == "homepage_bambu_login_or_register")
|
||||
this->request_login(true, BBL_CLOUD_PROVIDER);
|
||||
}
|
||||
});
|
||||
return "";
|
||||
}
|
||||
if (command_str.compare("request_project_download") == 0) {
|
||||
if (root.get_child_optional("data") != boost::none) {
|
||||
pt::ptree data_node = root.get_child("data");
|
||||
@@ -4812,6 +4838,8 @@ void GUI_App::handle_http_error(unsigned int status, std::string body, const std
|
||||
wxQueueEvent(this, evt);
|
||||
}
|
||||
|
||||
static std::mutex conflict_ids_mutex;
|
||||
|
||||
void GUI_App::on_http_error(wxCommandEvent &evt)
|
||||
{
|
||||
int status = evt.GetInt();
|
||||
@@ -4887,32 +4915,62 @@ void GUI_App::on_http_error(wxCommandEvent &evt)
|
||||
return;
|
||||
}
|
||||
|
||||
static bool m_is_error_shown = false;
|
||||
if (status == 409 && provider == ORCA_CLOUD_PROVIDER) {
|
||||
BOOST_LOG_TRIVIAL(info) << "Http error 409.";
|
||||
// Parse the conflict body to extract the error code and server profile id
|
||||
int conflict_code = 0;
|
||||
std::string conflict_setting_id;
|
||||
try {
|
||||
json conflict_body = json::parse(body_str);
|
||||
if (conflict_body.contains("code"))
|
||||
conflict_code = conflict_body["code"].get<int>();
|
||||
if (conflict_body.contains("server_profile") && conflict_body["server_profile"].contains("id")
|
||||
&& conflict_body["server_profile"]["id"].is_string())
|
||||
conflict_setting_id = conflict_body["server_profile"]["id"].get<std::string>();
|
||||
} catch (...) {
|
||||
BOOST_LOG_TRIVIAL(warning) << "Failed to parse 409 conflict body.";
|
||||
}
|
||||
auto* plater = wxGetApp().plater();
|
||||
if (plater != nullptr && wxGetApp().imgui()->display_initialized()) {
|
||||
std::string text;
|
||||
if (conflict_code == -1) {
|
||||
text = _u8L("Cloud sync conflict: this preset has a newer version in OrcaCloud.\n"
|
||||
"Pull downloads the cloud copy. Force push overwrites it with your local preset.");
|
||||
} else {
|
||||
text = _u8L("Cloud sync conflict: a preset with this name already exists in OrcaCloud.\n"
|
||||
"Pull downloads the cloud copy. Force push overwrites it with your local preset.");
|
||||
}
|
||||
plater->get_notification_manager()->push_orca_sync_conflict_notification(
|
||||
text,
|
||||
[this](wxEvtHandler*) {
|
||||
// Runs on the GUI thread (on_http_error is a queued wx event); restart_sync_user_preset()
|
||||
// already joins the old sync thread off the UI thread, so no extra thread is needed here.
|
||||
if (is_closing() || !m_agent || !preset_bundle)
|
||||
return false;
|
||||
BOOST_LOG_TRIVIAL(info) << "Pulling Orca Cloud settings to resolve sync conflict.";
|
||||
restart_sync_user_preset();
|
||||
return true;
|
||||
},
|
||||
[this, conflict_setting_id](wxEvtHandler*) {
|
||||
if (mainframe == nullptr)
|
||||
return false;
|
||||
MessageDialog
|
||||
dlg(mainframe,
|
||||
_L("Force push will overwrite the cloud copy with your local preset changes.\nDo you want to continue?"),
|
||||
_L("Resolve cloud sync conflict"), wxCENTER | wxYES_NO | wxNO_DEFAULT | wxICON_WARNING);
|
||||
if (dlg.ShowModal() != wxID_YES)
|
||||
return false;
|
||||
|
||||
force_push_conflicting_preset(conflict_setting_id);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Show general error notification for Orca Cloud API failures (not Bambu)
|
||||
if (provider == ORCA_CLOUD_PROVIDER && status >= 400 && code != HttpErrorVersionLimited) {
|
||||
wxString msg;
|
||||
if (!error.empty()) {
|
||||
msg = wxString::Format(_L("Failed to connect to OrcaCloud.\nPlease check your network connectivity\n(HTTP %u): %s"), status, wxString::FromUTF8(error));
|
||||
} else {
|
||||
msg = wxString::Format(_L("Failed to connect to OrcaCloud.\nPlease check your network connectivity\n(HTTP %u)"), status);
|
||||
}
|
||||
|
||||
if (app_config->get_bool("developer_mode")) {
|
||||
// Use notification manager if ImGui is ready; fall back to wxMessageBox on Linux
|
||||
// where ImGui may not be initialized until the user switches to the Prepare tab.
|
||||
if (wxGetApp().plater() != nullptr && wxGetApp().imgui()->display_initialized()) {
|
||||
wxGetApp()
|
||||
.plater()
|
||||
->get_notification_manager()
|
||||
->push_notification(NotificationType::PlaterError, NotificationManager::NotificationLevel::WarningNotificationLevel,
|
||||
msg.ToUTF8().data());
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_is_error_shown) {
|
||||
m_is_error_shown = true;
|
||||
wxMessageBox(msg, _L("Cloud Error"), wxOK | wxICON_ERROR, wxGetApp().mainframe);
|
||||
}
|
||||
BOOST_LOG_TRIVIAL(warning) << "API call to OrcaCloud failed with status=" << status;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6181,13 +6239,14 @@ void GUI_App::load_pending_vendors()
|
||||
need_add_filaments.clear();
|
||||
}
|
||||
|
||||
void GUI_App::sync_preset(Preset* preset)
|
||||
void GUI_App::sync_preset(Preset* preset, bool force)
|
||||
{
|
||||
int result = -1;
|
||||
unsigned int http_code = 200;
|
||||
std::string updated_info;
|
||||
long long update_time = 0;
|
||||
// only sync user's preset
|
||||
if (!m_agent) return;
|
||||
if (!preset->is_user()) return;
|
||||
|
||||
auto setting_id = preset->setting_id;
|
||||
@@ -6259,9 +6318,9 @@ void GUI_App::sync_preset(Preset* preset)
|
||||
result = 0;
|
||||
}
|
||||
else {
|
||||
result = m_agent->put_setting(setting_id, preset->name, &values_map, &http_code);
|
||||
result = m_agent->put_setting(setting_id, preset->name, &values_map, &http_code, ORCA_CLOUD_PROVIDER, force);
|
||||
if (http_code >= 400) {
|
||||
result = 0;
|
||||
result = 0;
|
||||
updated_info = "hold";
|
||||
BOOST_LOG_TRIVIAL(error) << "[sync_preset] put setting_id = " << setting_id << " failed, http_code = " << http_code;
|
||||
} else {
|
||||
@@ -6722,7 +6781,8 @@ void GUI_App::start_sync_user_preset(bool with_progress_dlg)
|
||||
// Sync once immediately, then every 60 seconds.
|
||||
while (!t.expired()) {
|
||||
++tick_tock;
|
||||
if (tick_tock % 120 == 0) {
|
||||
// Sync once immediately, then every 60s, or right away when a force-push asked for it.
|
||||
if (tick_tock % 120 == 0 || m_sync_user_presets_now.exchange(false, std::memory_order_acq_rel)) {
|
||||
tick_tock = 0;
|
||||
if (m_agent) {
|
||||
if (!m_agent->is_user_login()) {
|
||||
@@ -6733,9 +6793,24 @@ void GUI_App::start_sync_user_preset(bool with_progress_dlg)
|
||||
|
||||
int total_count = 0;
|
||||
sync_count = preset_bundle->prints.get_user_presets(preset_bundle, presets_to_sync);
|
||||
|
||||
auto sync_with_lock = [this](Preset& preset) {
|
||||
bool force = false;
|
||||
{
|
||||
std::scoped_lock lock(conflict_ids_mutex);
|
||||
auto it = std::find_if(m_pending_conflict_setting_ids.begin(), m_pending_conflict_setting_ids.end(),
|
||||
[&preset](const std::string& id) { return id == preset.setting_id; });
|
||||
if (it != m_pending_conflict_setting_ids.end()) {
|
||||
force = true;
|
||||
m_pending_conflict_setting_ids.erase(it);
|
||||
}
|
||||
}
|
||||
sync_preset(&preset, force);
|
||||
};
|
||||
|
||||
if (sync_count > 0) {
|
||||
for (Preset& preset : presets_to_sync) {
|
||||
sync_preset(&preset);
|
||||
sync_with_lock(preset);
|
||||
boost::this_thread::sleep_for(boost::chrono::milliseconds(100));
|
||||
}
|
||||
}
|
||||
@@ -6744,7 +6819,7 @@ void GUI_App::start_sync_user_preset(bool with_progress_dlg)
|
||||
sync_count = preset_bundle->filaments.get_user_presets(preset_bundle, presets_to_sync);
|
||||
if (sync_count > 0) {
|
||||
for (Preset& preset : presets_to_sync) {
|
||||
sync_preset(&preset);
|
||||
sync_with_lock(preset);
|
||||
boost::this_thread::sleep_for(boost::chrono::milliseconds(100));
|
||||
}
|
||||
}
|
||||
@@ -6753,7 +6828,7 @@ void GUI_App::start_sync_user_preset(bool with_progress_dlg)
|
||||
sync_count = preset_bundle->printers.get_user_presets(preset_bundle, presets_to_sync);
|
||||
if (sync_count > 0) {
|
||||
for (Preset& preset : presets_to_sync) {
|
||||
sync_preset(&preset);
|
||||
sync_with_lock(preset);
|
||||
boost::this_thread::sleep_for(boost::chrono::milliseconds(100));
|
||||
}
|
||||
}
|
||||
@@ -6930,6 +7005,35 @@ void GUI_App::restart_sync_user_preset()
|
||||
}).detach();
|
||||
}
|
||||
|
||||
void GUI_App::force_push_conflicting_preset(const std::string& setting_id)
|
||||
{
|
||||
if (setting_id.empty() || !preset_bundle)
|
||||
return;
|
||||
|
||||
// Queue the id so the next push-sync re-uploads this preset with force=true.
|
||||
{
|
||||
std::scoped_lock lock(conflict_ids_mutex);
|
||||
m_pending_conflict_setting_ids.push_back(setting_id);
|
||||
}
|
||||
|
||||
// The 409 left this preset on "hold", which get_user_presets() skips. Restore it to
|
||||
// "update" so the next push-sync re-includes it and consumes the queued force flag.
|
||||
// (We must NOT pull from the cloud here as the Pull path does — that would overwrite
|
||||
// the local changes the user is trying to force-push.)
|
||||
PresetCollection* collections[] = {&preset_bundle->prints, &preset_bundle->filaments, &preset_bundle->printers};
|
||||
for (PresetCollection* coll : collections) {
|
||||
for (const Preset& preset : coll->get_presets()) {
|
||||
if (preset.setting_id == setting_id && preset.sync_info == "hold") {
|
||||
coll->set_sync_info_and_save(preset.name, preset.setting_id, "update", 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Nudge the sync loop to push on its next tick instead of waiting for the 60s cadence.
|
||||
m_sync_user_presets_now.store(true, std::memory_order_release);
|
||||
}
|
||||
|
||||
void GUI_App::on_stealth_mode_enter()
|
||||
{
|
||||
stop_sync_user_preset();
|
||||
|
||||
@@ -297,6 +297,7 @@ private:
|
||||
NetworkAgent* m_agent { nullptr };
|
||||
std::map<std::string, std::string> need_delete_presets; // store setting ids of preset
|
||||
std::vector<bool> m_create_preset_blocked { false, false, false, false, false, false }; // excceed limit
|
||||
std::vector<std::string> m_pending_conflict_setting_ids; // setting_id from the most recent 409 conflict
|
||||
bool m_networking_compatible { false };
|
||||
bool m_networking_need_update { false };
|
||||
bool m_networking_cancel_update { false };
|
||||
@@ -322,6 +323,7 @@ private:
|
||||
boost::thread m_sync_update_thread;
|
||||
std::shared_ptr<int> m_user_sync_token;
|
||||
std::atomic<bool> m_restart_sync_pending {false};
|
||||
std::atomic<bool> m_sync_user_presets_now {false}; // request the sync loop to push user presets on its next tick
|
||||
bool m_is_dark_mode{ false };
|
||||
bool m_adding_script_handler { false };
|
||||
bool m_side_popup_status{false};
|
||||
@@ -529,10 +531,13 @@ public:
|
||||
void add_pending_vendor_preset(const std::pair<std::string, std::map<std::string, std::string>>& preset_data);
|
||||
void load_pending_vendors();
|
||||
|
||||
void sync_preset(Preset* preset);
|
||||
void sync_preset(Preset* preset, bool force = false);
|
||||
void start_sync_user_preset(bool with_progress_dlg = false);
|
||||
void stop_sync_user_preset();
|
||||
void restart_sync_user_preset();
|
||||
// Resolve a cloud sync 409 by force-pushing the conflicting preset: clears the "hold"
|
||||
// state the conflict left behind and queues it to be re-uploaded with force=true.
|
||||
void force_push_conflicting_preset(const std::string& setting_id);
|
||||
void on_stealth_mode_enter();
|
||||
|
||||
// Bundle subscription sync
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "DeviceManager.hpp"
|
||||
#include "DeviceCore/DevManager.h"
|
||||
#include "DeviceCore/DevUtil.h"
|
||||
#include "libslic3r/AppConfig.hpp"
|
||||
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
||||
@@ -13,6 +14,14 @@ static const char* HMS_LOCAL_IMG_PATH = "hms/local_image";
|
||||
// the local HMS info
|
||||
static unordered_set<string> package_dev_id_types {"094", "239", "093", "22E"};
|
||||
|
||||
// HMS should be disabled when stealth mode is on or networking is not installed
|
||||
static bool should_disable_hms()
|
||||
{
|
||||
Slic3r::AppConfig* config = Slic3r::GUI::wxGetApp().app_config;
|
||||
if (!config) return true;
|
||||
return config->get_stealth_mode() || !config->get_bool("installed_networking");
|
||||
}
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
@@ -21,7 +30,7 @@ int get_hms_info_version(std::string& version)
|
||||
AppConfig* config = wxGetApp().app_config;
|
||||
if (!config)
|
||||
return -1;
|
||||
if (config->get_stealth_mode())
|
||||
if (should_disable_hms())
|
||||
return -1;
|
||||
std::string hms_host = config->get_hms_host();
|
||||
if(hms_host.empty()) {
|
||||
@@ -61,7 +70,7 @@ int HMSQuery::download_hms_related(const std::string& hms_type, const std::strin
|
||||
|
||||
AppConfig* config = wxGetApp().app_config;
|
||||
if (!config) return -1;
|
||||
if (config->get_stealth_mode()) return -1;
|
||||
if (should_disable_hms()) return -1;
|
||||
|
||||
std::string hms_host = wxGetApp().app_config->get_hms_host();
|
||||
std::string lang;
|
||||
@@ -546,7 +555,7 @@ wxString HMSQuery::query_print_image_action(const MachineObject* obj, int print_
|
||||
::sprintf(buf, "%08X", print_error);
|
||||
//The first three digits of SN number
|
||||
const auto result = _query_error_image_action(get_dev_id_type(obj),std::string(buf), button_action);
|
||||
if (wxGetApp().app_config->get_stealth_mode() && result.Contains("http")) {
|
||||
if (should_disable_hms() && result.Contains("http")) {
|
||||
return wxEmptyString;
|
||||
}
|
||||
return result;
|
||||
@@ -637,7 +646,7 @@ std::string get_hms_wiki_url(std::string error_code)
|
||||
{
|
||||
AppConfig* config = wxGetApp().app_config;
|
||||
if (!config) return "";
|
||||
if (config->get_stealth_mode()) return "";
|
||||
if (should_disable_hms()) return "";
|
||||
|
||||
std::string hms_host = wxGetApp().app_config->get_hms_host();
|
||||
std::string lang_code = HMSQuery::hms_language_code();
|
||||
@@ -663,7 +672,7 @@ std::string get_hms_wiki_url(std::string error_code)
|
||||
|
||||
std::string get_error_message(int error_code)
|
||||
{
|
||||
if (wxGetApp().app_config->get_stealth_mode()) return "";
|
||||
if (should_disable_hms()) return "";
|
||||
|
||||
char buf[64];
|
||||
std::string result_str = "";
|
||||
|
||||
@@ -791,6 +791,42 @@ void NotificationManager::PopNotification::render_hypertext(ImGuiWrapper& imgui,
|
||||
|
||||
}
|
||||
|
||||
void NotificationManager::PopNotification::render_hyperlink_action(ImGuiWrapper& imgui, float text_x, float text_y,
|
||||
const std::string& text, const char* button_id, const std::function<void()>& on_click)
|
||||
{
|
||||
// Invisible button over the label
|
||||
ImVec2 part_size = ImGui::CalcTextSize(text.c_str());
|
||||
ImGui::SetCursorPosX(text_x - 4);
|
||||
ImGui::SetCursorPosY(text_y - 5);
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(.0f, .0f, .0f, .0f));
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(.0f, .0f, .0f, .0f));
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(.0f, .0f, .0f, .0f));
|
||||
if (imgui.button(button_id, part_size.x + 6, part_size.y + 10) && on_click)
|
||||
on_click();
|
||||
ImGui::PopStyleColor(3);
|
||||
|
||||
// Hover color
|
||||
ImVec4 color = m_HyperTextColor;
|
||||
if (ImGui::IsItemHovered(ImGuiHoveredFlags_RectOnly))
|
||||
color = m_HyperTextColorHover;
|
||||
|
||||
// Text
|
||||
push_style_color(ImGuiCol_Text, color, m_state == EState::FadingOut, m_current_fade_opacity);
|
||||
ImGui::SetCursorPosX(text_x);
|
||||
ImGui::SetCursorPosY(text_y);
|
||||
imgui.text(text.c_str());
|
||||
ImGui::PopStyleColor();
|
||||
|
||||
// Underline
|
||||
ImVec2 lineEnd = ImGui::GetItemRectMax();
|
||||
lineEnd.y -= 2;
|
||||
ImVec2 lineStart = lineEnd;
|
||||
lineStart.x = ImGui::GetItemRectMin().x;
|
||||
ImGui::GetWindowDrawList()->AddLine(lineStart, lineEnd,
|
||||
IM_COL32((int)(color.x * 255), (int)(color.y * 255), (int)(color.z * 255),
|
||||
(int)(color.w * 255.f * (m_state == EState::FadingOut ? m_current_fade_opacity : 1.f))));
|
||||
}
|
||||
|
||||
void NotificationManager::PopNotification::render_close_button(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y)
|
||||
{
|
||||
ensure_ui_inited();
|
||||
@@ -2346,40 +2382,49 @@ bool NotificationManager::SharedProfilesNotification::on_text_click()
|
||||
void NotificationManager::SharedProfilesNotification::render_hypertext(ImGuiWrapper& imgui,
|
||||
const float text_x, const float text_y, const std::string text, bool more)
|
||||
{
|
||||
// Invisible button
|
||||
ImVec2 part_size = ImGui::CalcTextSize(text.c_str());
|
||||
ImGui::SetCursorPosX(text_x - 4);
|
||||
ImGui::SetCursorPosY(text_y - 5);
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(.0f, .0f, .0f, .0f));
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(.0f, .0f, .0f, .0f));
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(.0f, .0f, .0f, .0f));
|
||||
if (imgui.button("##browse_btn", part_size.x + 6, part_size.y + 10)) {
|
||||
if (on_text_click()) {
|
||||
close();
|
||||
render_hyperlink_action(imgui, text_x, text_y, text, "##browse_btn",
|
||||
[this] { if (on_text_click()) close(); });
|
||||
}
|
||||
|
||||
void NotificationManager::OrcaSyncConflictNotification::init()
|
||||
{
|
||||
PopNotification::init();
|
||||
// Reserve a dedicated action row for the two conflict-resolution links.
|
||||
m_lines_count = m_lines_count + 1;
|
||||
}
|
||||
|
||||
void NotificationManager::OrcaSyncConflictNotification::render_text(ImGuiWrapper& imgui,
|
||||
const float win_size_x, const float win_size_y,
|
||||
const float win_pos_x, const float win_pos_y)
|
||||
{
|
||||
float x_offset = m_left_indentation;
|
||||
float shift_y = m_line_height;
|
||||
float starting_y = m_line_height / 2;
|
||||
|
||||
int last_end = 0;
|
||||
std::string line;
|
||||
for (size_t i = 0; i < m_endlines.size(); i++) {
|
||||
if (m_text1.size() >= m_endlines[i]) {
|
||||
line = m_text1.substr(last_end, m_endlines[i] - last_end);
|
||||
last_end = m_endlines[i];
|
||||
if (m_text1.size() > m_endlines[i])
|
||||
last_end += (m_text1[m_endlines[i]] == '\n' || m_text1[m_endlines[i]] == ' ' ? 1 : 0);
|
||||
ImGui::SetCursorPosX(x_offset);
|
||||
ImGui::SetCursorPosY(starting_y + i * shift_y);
|
||||
imgui.text(line.c_str());
|
||||
}
|
||||
}
|
||||
ImGui::PopStyleColor(3);
|
||||
|
||||
// Hover color
|
||||
ImVec4 HyperColor = m_HyperTextColor;
|
||||
if (ImGui::IsItemHovered(ImGuiHoveredFlags_RectOnly))
|
||||
HyperColor = m_HyperTextColorHover;
|
||||
|
||||
// Text
|
||||
push_style_color(ImGuiCol_Text, HyperColor, m_state == EState::FadingOut, m_current_fade_opacity);
|
||||
ImGui::SetCursorPosX(text_x);
|
||||
ImGui::SetCursorPosY(text_y);
|
||||
imgui.text(text.c_str());
|
||||
ImGui::PopStyleColor();
|
||||
|
||||
// Underline
|
||||
ImVec2 lineEnd = ImGui::GetItemRectMax();
|
||||
lineEnd.y -= 2;
|
||||
ImVec2 lineStart = lineEnd;
|
||||
lineStart.x = ImGui::GetItemRectMin().x;
|
||||
ImGui::GetWindowDrawList()->AddLine(lineStart, lineEnd,
|
||||
IM_COL32((int)(HyperColor.x * 255), (int)(HyperColor.y * 255), (int)(HyperColor.z * 255),
|
||||
(int)(HyperColor.w * 255.f * (m_state == EState::FadingOut ? m_current_fade_opacity : 1.f))));
|
||||
const float action_y = starting_y + m_endlines.size() * shift_y;
|
||||
const std::string pull_text = _u8L("Pull");
|
||||
render_hyperlink_action(imgui, x_offset, action_y, pull_text, "##orca_sync_pull",
|
||||
[this] { if (m_pull_callback && m_pull_callback(m_evt_handler)) close(); });
|
||||
if (m_force_push_callback) {
|
||||
const std::string force_push_text = _u8L("Force push");
|
||||
const float force_x = x_offset + ImGui::CalcTextSize((pull_text + " ").c_str()).x;
|
||||
render_hyperlink_action(imgui, force_x, action_y, force_push_text, "##orca_sync_force_push",
|
||||
[this] { if (m_force_push_callback && m_force_push_callback(m_evt_handler)) close(); });
|
||||
}
|
||||
}
|
||||
|
||||
void NotificationManager::push_shared_profiles_notification(const std::string& explore_url)
|
||||
@@ -2391,6 +2436,16 @@ void NotificationManager::push_shared_profiles_notification(const std::string& e
|
||||
push_notification_data(std::make_unique<NotificationManager::SharedProfilesNotification>(data, m_id_provider, m_evt_handler, explore_url), 0);
|
||||
}
|
||||
|
||||
void NotificationManager::push_orca_sync_conflict_notification(const std::string& text,
|
||||
std::function<bool(wxEvtHandler*)> pull_callback,
|
||||
std::function<bool(wxEvtHandler*)> force_push_callback)
|
||||
{
|
||||
close_notification_of_type(NotificationType::OrcaSyncConflict);
|
||||
NotificationData data{ NotificationType::OrcaSyncConflict, NotificationLevel::WarningNotificationLevel, 0, text };
|
||||
push_notification_data(std::make_unique<NotificationManager::OrcaSyncConflictNotification>(
|
||||
data, m_id_provider, m_evt_handler, std::move(pull_callback), std::move(force_push_callback)), 0);
|
||||
}
|
||||
|
||||
void NotificationManager::push_download_URL_progress_notification(size_t id, const std::string& text, std::function<bool(DownloaderUserAction, int)> user_action_callback)
|
||||
{
|
||||
// If already exists
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
#include <wx/time.h>
|
||||
|
||||
#include <string>
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
#include <unordered_set>
|
||||
@@ -162,6 +164,8 @@ enum class NotificationType
|
||||
BBLMixUsePLAAndPETG,
|
||||
BBLNozzleFilamentIncompatible,
|
||||
OrcaSharedProfilesAvailable,
|
||||
OrcaCloudAPIError,
|
||||
OrcaSyncConflict,
|
||||
NotificationTypeCount
|
||||
|
||||
};
|
||||
@@ -274,6 +278,9 @@ public:
|
||||
|
||||
// Shared profiles available for selected printer
|
||||
void push_shared_profiles_notification(const std::string& explore_url);
|
||||
void push_orca_sync_conflict_notification(const std::string& text,
|
||||
std::function<bool(wxEvtHandler*)> pull_callback,
|
||||
std::function<bool(wxEvtHandler*)> force_push_callback);
|
||||
|
||||
// Download URL progress notif
|
||||
void push_download_URL_progress_notification(size_t id, const std::string& text, std::function<bool(DownloaderUserAction, int)> user_action_callback);
|
||||
@@ -491,6 +498,11 @@ private:
|
||||
const float text_x, const float text_y,
|
||||
const std::string text,
|
||||
bool more = false);
|
||||
// Renders an underlined, hyperlink-style clickable label backed by an invisible button.
|
||||
// on_click runs when pressed; the callback itself decides whether to close().
|
||||
void render_hyperlink_action(ImGuiWrapper& imgui, float text_x, float text_y,
|
||||
const std::string& text, const char* button_id,
|
||||
const std::function<void()>& on_click);
|
||||
virtual void bbl_render_block_notif_text(ImGuiWrapper& imgui,
|
||||
const float win_size_x, const float win_size_y,
|
||||
const float win_pos_x, const float win_pos_y);
|
||||
@@ -887,6 +899,28 @@ private:
|
||||
std::string m_explore_url;
|
||||
bool m_dont_show_clicked{ false };
|
||||
};
|
||||
|
||||
class OrcaSyncConflictNotification : public PopNotification
|
||||
{
|
||||
public:
|
||||
OrcaSyncConflictNotification(const NotificationData& n, NotificationIDProvider& id_provider, wxEvtHandler* evt_handler,
|
||||
std::function<bool(wxEvtHandler*)> pull_callback,
|
||||
std::function<bool(wxEvtHandler*)> force_push_callback)
|
||||
: PopNotification(n, id_provider, evt_handler)
|
||||
, m_pull_callback(std::move(pull_callback))
|
||||
, m_force_push_callback(std::move(force_push_callback))
|
||||
{
|
||||
m_multiline = true;
|
||||
}
|
||||
protected:
|
||||
void init() override;
|
||||
void render_text(ImGuiWrapper& imgui,
|
||||
const float win_size_x, const float win_size_y,
|
||||
const float win_pos_x, const float win_pos_y) override;
|
||||
|
||||
std::function<bool(wxEvtHandler*)> m_pull_callback;
|
||||
std::function<bool(wxEvtHandler*)> m_force_push_callback;
|
||||
};
|
||||
class SlicingProgressNotification;
|
||||
|
||||
// in HintNotification.hpp
|
||||
|
||||
@@ -968,6 +968,11 @@ wxBoxSizer *PreferencesDialog::create_item_checkbox(wxString title, wxString too
|
||||
if (m_sync_user_preset_checkbox) m_sync_user_preset_checkbox->Enable(!enabled);
|
||||
if (m_bambu_cloud_checkbox) m_bambu_cloud_checkbox->Enable(!enabled);
|
||||
}
|
||||
else if (param == "hide_login_side_panel") {
|
||||
if (wxGetApp().mainframe && wxGetApp().mainframe->m_webview) {
|
||||
wxGetApp().mainframe->m_webview->SendCloudProvidersInfo();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __WXMSW__
|
||||
if (param == "associate_3mf") {
|
||||
@@ -1605,9 +1610,12 @@ void PreferencesDialog::create_items()
|
||||
auto item_region = create_item_region_combobox(_L("Login region"), "");
|
||||
g_sizer->Add(item_region);
|
||||
|
||||
auto item_stealth_mode = create_item_checkbox(_L("Stealth mode"), _L("This disables all cloud services e.g. Orca Cloud and Bambu Cloud. This stops the transmission of data to Bambu's cloud services too. Users who don't use BBL machines or use LAN mode only can safely turn on this function."), "stealth_mode");
|
||||
auto item_stealth_mode = create_item_checkbox(_L("Stealth mode"), _L("This disables all cloud features, including Orca Cloud profile syncing. Users who prefer to work entirely offline can enable this option.\nNote: When Stealth Mode is enabled, your user profiles will not be backed up to Orca Cloud."), "stealth_mode");
|
||||
g_sizer->Add(item_stealth_mode);
|
||||
|
||||
auto item_hide_login_side_panel = create_item_checkbox(_L("Hide login side panel"), _L("Hide the login side panel on the home page."), "hide_login_side_panel");
|
||||
g_sizer->Add(item_hide_login_side_panel);
|
||||
|
||||
auto item_network_test = create_item_button(_L("Network test"), _L("Test") + " " + dots, "", _L("Open Network Test"), []() {
|
||||
NetworkTestDialog dlg(wxGetApp().mainframe);
|
||||
dlg.ShowModal();
|
||||
|
||||
@@ -177,11 +177,7 @@ ZUserLogin::ZUserLogin(std::shared_ptr<ICloudServiceAgent> cloud_agent)
|
||||
wxSize pSize = FromDIP(wxSize(650, 840));
|
||||
SetSize(pSize);
|
||||
|
||||
int screenheight = wxSystemSettings::GetMetric(wxSYS_SCREEN_Y, NULL);
|
||||
int screenwidth = wxSystemSettings::GetMetric(wxSYS_SCREEN_X, NULL);
|
||||
int MaxY = (screenheight - pSize.y) > 0 ? (screenheight - pSize.y) / 2 : 0;
|
||||
wxPoint tmpPT((screenwidth - pSize.x) / 2, MaxY);
|
||||
Move(tmpPT);
|
||||
CentreOnParent();
|
||||
}
|
||||
wxGetApp().UpdateDlgDarkUI(this);
|
||||
}
|
||||
|
||||
@@ -526,7 +526,7 @@ void WebViewPanel::SendCloudProvidersInfo()
|
||||
json data;
|
||||
json provider_array = json::array();
|
||||
|
||||
if (!app_config->get_stealth_mode()) {
|
||||
if (!app_config->get_hide_login_side_panel()) {
|
||||
auto providers = app_config->get_cloud_providers();
|
||||
for (const auto& p : providers) {
|
||||
provider_array.push_back(p);
|
||||
|
||||
@@ -433,7 +433,7 @@ std::string BBLCloudServiceAgent::request_setting_id(std::string name, std::map<
|
||||
return "";
|
||||
}
|
||||
|
||||
int BBLCloudServiceAgent::put_setting(std::string setting_id, std::string name, std::map<std::string, std::string>* values_map, unsigned int* http_code)
|
||||
int BBLCloudServiceAgent::put_setting(std::string setting_id, std::string name, std::map<std::string, std::string>* values_map, unsigned int* http_code, bool force)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
|
||||
@@ -70,7 +70,7 @@ public:
|
||||
// Settings Synchronization
|
||||
int get_user_presets(std::map<std::string, std::map<std::string, std::string>>* user_presets) override;
|
||||
std::string request_setting_id(std::string name, std::map<std::string, std::string>* values_map, unsigned int* http_code) override;
|
||||
int put_setting(std::string setting_id, std::string name, std::map<std::string, std::string>* values_map, unsigned int* http_code) override;
|
||||
int put_setting(std::string setting_id, std::string name, std::map<std::string, std::string>* values_map, unsigned int* http_code, bool force = false) override;
|
||||
int get_setting_list(std::string bundle_version, ProgressFn pro_fn = nullptr, WasCancelledFn cancel_fn = nullptr) override;
|
||||
int get_setting_list2(std::string bundle_version, CheckFn chk_fn, ProgressFn pro_fn = nullptr, WasCancelledFn cancel_fn = nullptr) override;
|
||||
int delete_setting(std::string setting_id) override;
|
||||
|
||||
@@ -247,7 +247,7 @@ public:
|
||||
/**
|
||||
* Update or create a preset with a known setting_id.
|
||||
*/
|
||||
virtual int put_setting(std::string setting_id, std::string name, std::map<std::string, std::string>* values_map, unsigned int* http_code) = 0;
|
||||
virtual int put_setting(std::string setting_id, std::string name, std::map<std::string, std::string>* values_map, unsigned int* http_code, bool force = false) = 0;
|
||||
|
||||
/**
|
||||
* Trigger bulk download of user presets.
|
||||
|
||||
@@ -383,11 +383,12 @@ int NetworkAgent::put_setting(std::string setting_id,
|
||||
std::string name,
|
||||
std::map<std::string, std::string>* values_map,
|
||||
unsigned int* http_code,
|
||||
const std::string& provider)
|
||||
const std::string& provider,
|
||||
bool force)
|
||||
{
|
||||
const auto cloud_agent = get_cloud_agent(provider);
|
||||
if (cloud_agent)
|
||||
return cloud_agent->put_setting(std::move(setting_id), std::move(name), values_map, http_code);
|
||||
return cloud_agent->put_setting(std::move(setting_id), std::move(name), values_map, http_code, force);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -93,7 +93,7 @@ public:
|
||||
// NOTE: this should always call only OrcaCloud
|
||||
int get_user_presets(std::map<std::string, std::map<std::string, std::string>>* user_presets, const std::string& provider = ORCA_CLOUD_PROVIDER);
|
||||
std::string request_setting_id(std::string name, std::map<std::string, std::string>* values_map, unsigned int* http_code, const std::string& provider = ORCA_CLOUD_PROVIDER);
|
||||
int put_setting(std::string setting_id, std::string name, std::map<std::string, std::string>* values_map, unsigned int* http_code, const std::string& provider = ORCA_CLOUD_PROVIDER);
|
||||
int put_setting(std::string setting_id, std::string name, std::map<std::string, std::string>* values_map, unsigned int* http_code, const std::string& provider = ORCA_CLOUD_PROVIDER, bool force = false);
|
||||
int get_setting_list(std::string bundle_version, ProgressFn pro_fn = nullptr, WasCancelledFn cancel_fn = nullptr, const std::string& provider = ORCA_CLOUD_PROVIDER);
|
||||
int get_setting_list2(std::string bundle_version, CheckFn chk_fn, ProgressFn pro_fn = nullptr, WasCancelledFn cancel_fn = nullptr, const std::string& provider = ORCA_CLOUD_PROVIDER);
|
||||
int delete_setting(std::string setting_id, const std::string& provider = ORCA_CLOUD_PROVIDER);
|
||||
|
||||
@@ -56,6 +56,7 @@ constexpr const char* ORCA_DEFAULT_PUB_KEY = "sb_publishable_lvVe_whOi80SU9BPSxM
|
||||
constexpr const char* ORCA_HEALTH_PATH = "/api/v1/health";
|
||||
constexpr const char* ORCA_SYNC_PULL_PATH = "/api/v1/sync/pull";
|
||||
constexpr const char* ORCA_SYNC_PUSH_PATH = "/api/v1/sync/push";
|
||||
constexpr const char* ORCA_SYNC_FORCE_PUSH_PATH = "/api/v1/sync/force-push";
|
||||
constexpr const char* ORCA_SYNC_DELETE_PATH = "/api/v1/sync/delete";
|
||||
constexpr const char* ORCA_PROFILES_PATH = "/api/v1/sync/profiles";
|
||||
constexpr const char* ORCA_SUBSCRIPTIONS_PATH = "/api/v1/subscriptions";
|
||||
@@ -965,7 +966,7 @@ std::string OrcaCloudServiceAgent::request_setting_id(std::string name, std::map
|
||||
return "";
|
||||
}
|
||||
|
||||
int OrcaCloudServiceAgent::put_setting(std::string setting_id, std::string name, std::map<std::string, std::string>* values_map, unsigned int* http_code)
|
||||
int OrcaCloudServiceAgent::put_setting(std::string setting_id, std::string name, std::map<std::string, std::string>* values_map, unsigned int* http_code, bool force)
|
||||
{
|
||||
// Extract original_updated_time for Optimistic Concurrency Control
|
||||
// If present, server will verify version before update. If absent, treated as insert.
|
||||
@@ -989,7 +990,7 @@ int OrcaCloudServiceAgent::put_setting(std::string setting_id, std::string name,
|
||||
}
|
||||
}
|
||||
|
||||
auto result = sync_push(setting_id, name, content, original_updated_time);
|
||||
auto result = sync_push(setting_id, name, content, original_updated_time, force);
|
||||
if (http_code) *http_code = result.http_code;
|
||||
|
||||
if (result.success) {
|
||||
@@ -1208,11 +1209,11 @@ int OrcaCloudServiceAgent::sync_pull(
|
||||
}
|
||||
}
|
||||
|
||||
SyncPushResult OrcaCloudServiceAgent::sync_push(
|
||||
const std::string& profile_id,
|
||||
const std::string& name,
|
||||
const nlohmann::json& content,
|
||||
const std::string& original_updated_time)
|
||||
SyncPushResult OrcaCloudServiceAgent::sync_push(const std::string& profile_id,
|
||||
const std::string& name,
|
||||
const nlohmann::json& content,
|
||||
const std::string& original_updated_time,
|
||||
bool force)
|
||||
{
|
||||
SyncPushResult result;
|
||||
result.success = false;
|
||||
@@ -1243,7 +1244,7 @@ SyncPushResult OrcaCloudServiceAgent::sync_push(
|
||||
|
||||
std::string response;
|
||||
unsigned int http_code = 0;
|
||||
int http_result = http_post(ORCA_SYNC_PUSH_PATH, body_str, &response, &http_code);
|
||||
int http_result = http_post(force ? ORCA_SYNC_FORCE_PUSH_PATH : ORCA_SYNC_PUSH_PATH, body_str, &response, &http_code);
|
||||
|
||||
result.http_code = http_code;
|
||||
|
||||
@@ -1888,7 +1889,7 @@ int OrcaCloudServiceAgent::http_post(const std::string& path, const std::string&
|
||||
.on_error([&](std::string resp_body, std::string error, unsigned resp_status) {
|
||||
result.success = false;
|
||||
result.status = resp_status == 0 ? 404 : resp_status;
|
||||
result.body = body;
|
||||
result.body = resp_body;
|
||||
BOOST_LOG_TRIVIAL(error) << "OrcaCloudServiceAgent: HTTP error - " << error;
|
||||
})
|
||||
.timeout_max(30)
|
||||
|
||||
@@ -176,7 +176,12 @@ public:
|
||||
// ========================================================================
|
||||
int get_user_presets(std::map<std::string, std::map<std::string, std::string>>* user_presets) override;
|
||||
std::string request_setting_id(std::string name, std::map<std::string, std::string>* values_map, unsigned int* http_code) override;
|
||||
int put_setting(std::string setting_id, std::string name, std::map<std::string, std::string>* values_map, unsigned int* http_code) override;
|
||||
int put_setting(std::string setting_id, std::string name, std::map<std::string, std::string>* values_map, unsigned int* http_code, bool force = false) override;
|
||||
SyncPushResult sync_push(const std::string& profile_id,
|
||||
const std::string& name,
|
||||
const nlohmann::json& content,
|
||||
const std::string& original_updated_time = "",
|
||||
bool force = false);
|
||||
int get_setting_list(std::string bundle_version, ProgressFn pro_fn = nullptr, WasCancelledFn cancel_fn = nullptr) override;
|
||||
int get_setting_list2(std::string bundle_version, CheckFn chk_fn, ProgressFn pro_fn = nullptr, WasCancelledFn cancel_fn = nullptr) override;
|
||||
int delete_setting(std::string setting_id) override;
|
||||
@@ -294,13 +299,6 @@ private:
|
||||
std::function<void(int http_code, const std::string& error)> on_error
|
||||
);
|
||||
|
||||
SyncPushResult sync_push(
|
||||
const std::string& profile_id,
|
||||
const std::string& name,
|
||||
const nlohmann::json& content,
|
||||
const std::string& original_updated_time = ""
|
||||
);
|
||||
|
||||
// HTTP request helpers
|
||||
int http_get(const std::string& path, std::string* response_body, unsigned int* http_code);
|
||||
int http_post(const std::string& path, const std::string& body, std::string* response_body, unsigned int* http_code);
|
||||
|
||||
Reference in New Issue
Block a user