Added UI force-sync button and fixed bug that didn't sync in one case… (#13745)
* Added UI force-sync button and fixed bug that didn't sync in one case and caused orange highlight * Fix sync preset race: join old thread before starting new one --------- Co-authored-by: Mykola Nahirnyi <mnahirnyi@amcbridge.com> Co-authored-by: SoftFever <softfeverever@gmail.com>
This commit is contained in:
@@ -2259,6 +2259,10 @@ bool PresetCollection::load_user_preset(std::string name, std::map<std::string,
|
||||
if (iter->name == m_edited_preset.name && iter->is_dirty) {
|
||||
// Keep modifies when update from remote
|
||||
new_config.apply_only(m_edited_preset.config, m_edited_preset.config.diff(iter->config));
|
||||
} else if (iter->name == m_edited_preset.name) {
|
||||
// Preset is not dirty (no local unsaved changes) — also update the edited preset
|
||||
// to prevent a false "dirty" indication (orange highlight) after a silent cloud sync
|
||||
m_edited_preset.config = new_config;
|
||||
}
|
||||
iter->config = new_config;
|
||||
iter->updated_time = cloud_update_time;
|
||||
|
||||
@@ -6577,8 +6577,8 @@ void GUI_App::start_sync_user_preset(bool with_progress_dlg)
|
||||
dlg->Update(percent, _L("Loading user preset"));
|
||||
});
|
||||
};
|
||||
cancelFn = [this, dlg]() {
|
||||
return is_closing() || dlg->WasCanceled();
|
||||
cancelFn = [this, dlg, t = std::weak_ptr<int>(m_user_sync_token)]() {
|
||||
return is_closing() || dlg->WasCanceled() || t.expired();
|
||||
};
|
||||
finishFn = [this, dlg](bool) {
|
||||
CallAfter([=]{ dlg->Destroy(); });
|
||||
@@ -6586,8 +6586,8 @@ void GUI_App::start_sync_user_preset(bool with_progress_dlg)
|
||||
}
|
||||
else {
|
||||
finishFn = [](bool) {}; // reload_settings() is now triggered from the background thread
|
||||
cancelFn = [this]() {
|
||||
return is_closing();
|
||||
cancelFn = [this, t = std::weak_ptr<int>(m_user_sync_token)]() {
|
||||
return is_closing() || t.expired();
|
||||
};
|
||||
}
|
||||
|
||||
@@ -6819,6 +6819,37 @@ void GUI_App::stop_sync_user_preset()
|
||||
}
|
||||
}
|
||||
|
||||
void GUI_App::restart_sync_user_preset()
|
||||
{
|
||||
if (!m_user_sync_token) {
|
||||
// No sync running. If a restart helper is already in flight it will
|
||||
// start the new sync once the old thread is joined — don't race it.
|
||||
if (!m_restart_sync_pending)
|
||||
start_sync_user_preset(true);
|
||||
return;
|
||||
}
|
||||
|
||||
// Resetting the token signals the old thread to stop (cancelFn checks
|
||||
// t.expired(), so it exits after its current HTTP request completes).
|
||||
// A helper thread joins the old thread off the UI thread — no freeze —
|
||||
// then starts the new sync via CallAfter once the old one is fully done.
|
||||
m_user_sync_token.reset();
|
||||
m_restart_sync_pending = true;
|
||||
|
||||
auto old_thread = std::move(m_sync_update_thread);
|
||||
|
||||
std::thread([this, old_thread = std::move(old_thread)]() mutable {
|
||||
if (old_thread.joinable())
|
||||
old_thread.join();
|
||||
m_restart_sync_pending = false;
|
||||
if (!is_closing())
|
||||
CallAfter([this]() {
|
||||
if (!is_closing())
|
||||
start_sync_user_preset(true);
|
||||
});
|
||||
}).detach();
|
||||
}
|
||||
|
||||
void GUI_App::on_stealth_mode_enter()
|
||||
{
|
||||
stop_sync_user_preset();
|
||||
|
||||
@@ -321,6 +321,7 @@ private:
|
||||
|
||||
boost::thread m_sync_update_thread;
|
||||
std::shared_ptr<int> m_user_sync_token;
|
||||
std::atomic<bool> m_restart_sync_pending {false};
|
||||
bool m_is_dark_mode{ false };
|
||||
bool m_adding_script_handler { false };
|
||||
bool m_side_popup_status{false};
|
||||
@@ -530,6 +531,7 @@ public:
|
||||
void sync_preset(Preset* preset);
|
||||
void start_sync_user_preset(bool with_progress_dlg = false);
|
||||
void stop_sync_user_preset();
|
||||
void restart_sync_user_preset();
|
||||
void on_stealth_mode_enter();
|
||||
|
||||
// Bundle subscription sync
|
||||
|
||||
@@ -2780,6 +2780,24 @@ void MainFrame::init_menubar_as_editor()
|
||||
append_submenu(fileMenu, export_menu, wxID_ANY, _L("Export"), "");
|
||||
|
||||
fileMenu->AppendSeparator();
|
||||
append_menu_item(fileMenu, wxID_ANY, _L("Sync Presets"), _L("Pull and apply the latest presets from OrcaCloud"),
|
||||
[this](wxCommandEvent&) {
|
||||
if (!wxGetApp().is_user_login()) {
|
||||
MessageDialog info_dlg(this, _L("You must be logged in to sync presets from cloud."),
|
||||
_L("Sync Presets"), wxOK | wxICON_INFORMATION);
|
||||
info_dlg.ShowModal();
|
||||
return;
|
||||
}
|
||||
if (m_plater)
|
||||
m_plater->get_notification_manager()->push_notification(
|
||||
into_u8(_L("Syncing presets from cloud\u2026")));
|
||||
wxGetApp().restart_sync_user_preset();
|
||||
}, "", nullptr,
|
||||
[this]() {
|
||||
return wxGetApp().is_user_login() && !wxGetApp().app_config->get_stealth_mode();
|
||||
}, this);
|
||||
|
||||
fileMenu->AppendSeparator();
|
||||
|
||||
#ifndef __APPLE__
|
||||
append_menu_item(fileMenu, wxID_EXIT, _L("Quit"), wxString::Format(_L("Quit")),
|
||||
|
||||
Reference in New Issue
Block a user