feat(wallet): confirm before stopping an adopted node to switch wallets
When switching wallets, the node the app would restart may be one this session ADOPTED — a dragonxd already running at launch (left up by "keep node running", or started by the user). Rather than stopping it silently (or the old dead-code "stop any external dragonxd first" refusal), show a "Stop the running node?" confirmation first; switching then stops it (RPC stop + wait for the port to fully free) and relaunches on the selected wallet. - switchToWallet(walletFile, stopDaemonConfirmed=false): when the node is adopted (externalDaemonDetected) and not yet confirmed, defer to the dialog and return. - renderSwitchStopDaemonDialog(): BlurFloat overlay (house style) with a warning header; confirm re-enters switchToWallet(w, true); cancel/X aborts, node keeps running. Owned nodes (started this session) still restart silently. - i18n (EN + 8 languages, additive) + CJK subset rebuild; modal-switch-stopnode sweep surface for visual review. Gate/re-entrancy adversarially verified (no state leak; owned switches ungated; prompt reappears on a reverted switch; dead-daemon-before-confirm handled). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
37
src/app.cpp
37
src/app.cpp
@@ -2034,6 +2034,7 @@ void App::render()
|
||||
renderEncryptWalletDialog();
|
||||
renderDecryptWalletDialog();
|
||||
renderPinDialogs();
|
||||
renderSwitchStopDaemonDialog();
|
||||
|
||||
// Render notifications (toast messages)
|
||||
ui::Notifications::instance().render();
|
||||
@@ -3860,6 +3861,42 @@ void App::renderAntivirusHelpDialog()
|
||||
#endif
|
||||
}
|
||||
|
||||
void App::renderSwitchStopDaemonDialog()
|
||||
{
|
||||
if (!show_switch_stop_daemon_confirm_) return;
|
||||
|
||||
ui::material::OverlayDialogSpec ov;
|
||||
ov.title = TR("switch_stopnode_title");
|
||||
ov.p_open = &show_switch_stop_daemon_confirm_; // the X / backdrop click acts as Cancel
|
||||
ov.style = ui::material::OverlayStyle::BlurFloat;
|
||||
ov.cardWidth = 520.0f; ov.idSuffix = "switchstopnode";
|
||||
if (!ui::material::BeginOverlayDialog(ov)) {
|
||||
// Closed via X/backdrop — treat as cancel: drop the pending target.
|
||||
if (!show_switch_stop_daemon_confirm_) pending_switch_wallet_file_.clear();
|
||||
return;
|
||||
}
|
||||
const float dp = ui::Layout::dpiScale();
|
||||
|
||||
ui::material::DialogWarningHeader(TR("switch_stopnode_warn"));
|
||||
ImGui::Dummy(ImVec2(0, ui::Layout::spacingSm()));
|
||||
ImGui::TextWrapped("%s", TR("switch_stopnode_body"));
|
||||
ImGui::Dummy(ImVec2(0, ui::Layout::spacingMd()));
|
||||
|
||||
if (ui::material::TactileButton(TR("switch_stopnode_confirm"), ImVec2(200.0f * dp, 0))) {
|
||||
const std::string w = pending_switch_wallet_file_;
|
||||
pending_switch_wallet_file_.clear();
|
||||
show_switch_stop_daemon_confirm_ = false;
|
||||
switchToWallet(w, /*stopDaemonConfirmed=*/true); // now proceeds to stop + wait + restart
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ui::material::TactileButton(TR("cancel"), ImVec2(110.0f * dp, 0))) {
|
||||
pending_switch_wallet_file_.clear();
|
||||
show_switch_stop_daemon_confirm_ = false;
|
||||
}
|
||||
|
||||
ui::material::EndOverlayDialog();
|
||||
}
|
||||
|
||||
void App::refreshNow()
|
||||
{
|
||||
// Trigger immediate refresh on all categories
|
||||
|
||||
Reference in New Issue
Block a user