feat(wallet): richer detail in the wallet-switch progress modal
The switch modal now shows more than a bare phase line:
- The title carries the target wallet ("Switching wallet — savings") and a
"from <previous>" caption for context (names prettified: wallet.dat → "Default
wallet", wallet-<name>.dat → "<name>", in-place links → "External wallet").
- During the Reconnecting phase — the ~30-60s where the node loads the block
index, verifies, and rescans — it surfaces the node's LIVE init stage
(state_.warmup_status/description via the existing translateWarmup mapping:
"Loading blockchain data…", "Verifying blockchain…", "Scanning for
transactions…") instead of a static "Reconnecting…".
- An elapsed timer (m:ss) so the wait visibly progresses.
i18n: from/elapsed/default-wallet/external-wallet labels (EN + 8 languages,
additive; no new CJK glyphs). No switch-flow logic change.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1295,7 +1295,11 @@
|
||||
"sweep_toggle": "In meine Wallet fegen (Schlüssel nicht behalten)",
|
||||
"sweep_tx": "Transaktion:",
|
||||
"switch_progress_background": "Im Hintergrund fortsetzen",
|
||||
"switch_progress_default_wallet": "Standard-Wallet",
|
||||
"switch_progress_elapsed": "Vergangen",
|
||||
"switch_progress_external_wallet": "Externe Wallet",
|
||||
"switch_progress_failed_title": "Wallet-Wechsel fehlgeschlagen",
|
||||
"switch_progress_from_label": "von",
|
||||
"switch_progress_hint": "Ein sauberes Herunterfahren kann bis zu einer Minute dauern.",
|
||||
"switch_progress_reconnecting": "Neu verbinden",
|
||||
"switch_progress_starting": "Knoten wird mit der neuen Wallet gestartet",
|
||||
|
||||
@@ -1295,7 +1295,11 @@
|
||||
"sweep_toggle": "Barrer a mi monedero (no conservar la clave)",
|
||||
"sweep_tx": "Transacción:",
|
||||
"switch_progress_background": "Continuar en segundo plano",
|
||||
"switch_progress_default_wallet": "Cartera predeterminada",
|
||||
"switch_progress_elapsed": "Transcurrido",
|
||||
"switch_progress_external_wallet": "Cartera externa",
|
||||
"switch_progress_failed_title": "Error al cambiar de cartera",
|
||||
"switch_progress_from_label": "desde",
|
||||
"switch_progress_hint": "Un apagado ordenado puede tardar hasta un minuto.",
|
||||
"switch_progress_reconnecting": "Reconectando",
|
||||
"switch_progress_starting": "Iniciando el nodo con la nueva cartera",
|
||||
|
||||
@@ -1295,7 +1295,11 @@
|
||||
"sweep_toggle": "Balayer vers mon portefeuille (ne pas conserver la clé)",
|
||||
"sweep_tx": "Transaction :",
|
||||
"switch_progress_background": "Continuer en arrière-plan",
|
||||
"switch_progress_default_wallet": "Portefeuille par défaut",
|
||||
"switch_progress_elapsed": "Écoulé",
|
||||
"switch_progress_external_wallet": "Portefeuille externe",
|
||||
"switch_progress_failed_title": "Échec du changement de portefeuille",
|
||||
"switch_progress_from_label": "depuis",
|
||||
"switch_progress_hint": "Un arrêt propre peut prendre jusqu'à une minute.",
|
||||
"switch_progress_reconnecting": "Reconnexion",
|
||||
"switch_progress_starting": "Démarrage du nœud sur le nouveau portefeuille",
|
||||
|
||||
@@ -1295,7 +1295,11 @@
|
||||
"sweep_toggle": "ウォレットに集約(鍵は保持しない)",
|
||||
"sweep_tx": "取引:",
|
||||
"switch_progress_background": "バックグラウンドで続行",
|
||||
"switch_progress_default_wallet": "既定のウォレット",
|
||||
"switch_progress_elapsed": "経過",
|
||||
"switch_progress_external_wallet": "外部ウォレット",
|
||||
"switch_progress_failed_title": "ウォレットの切り替えに失敗しました",
|
||||
"switch_progress_from_label": "元:",
|
||||
"switch_progress_hint": "正常なシャットダウンには最大1分かかることがあります。",
|
||||
"switch_progress_reconnecting": "再接続しています",
|
||||
"switch_progress_starting": "新しいウォレットでノードを起動しています",
|
||||
|
||||
@@ -1295,7 +1295,11 @@
|
||||
"sweep_toggle": "내 지갑으로 쓸어담기 (키 보관 안 함)",
|
||||
"sweep_tx": "거래:",
|
||||
"switch_progress_background": "백그라운드에서 계속",
|
||||
"switch_progress_default_wallet": "기본 지갑",
|
||||
"switch_progress_elapsed": "경과",
|
||||
"switch_progress_external_wallet": "외부 지갑",
|
||||
"switch_progress_failed_title": "지갑 전환 실패",
|
||||
"switch_progress_from_label": "이전:",
|
||||
"switch_progress_hint": "정상 종료에는 최대 1분이 걸릴 수 있습니다.",
|
||||
"switch_progress_reconnecting": "다시 연결하는 중",
|
||||
"switch_progress_starting": "새 지갑으로 노드를 시작하는 중",
|
||||
|
||||
@@ -1295,7 +1295,11 @@
|
||||
"sweep_toggle": "Varrer para minha carteira (não manter a chave)",
|
||||
"sweep_tx": "Transação:",
|
||||
"switch_progress_background": "Continuar em segundo plano",
|
||||
"switch_progress_default_wallet": "Carteira padrão",
|
||||
"switch_progress_elapsed": "Decorrido",
|
||||
"switch_progress_external_wallet": "Carteira externa",
|
||||
"switch_progress_failed_title": "Falha ao trocar de carteira",
|
||||
"switch_progress_from_label": "de",
|
||||
"switch_progress_hint": "Um desligamento normal pode levar até um minuto.",
|
||||
"switch_progress_reconnecting": "Reconectando",
|
||||
"switch_progress_starting": "Iniciando o nó com a nova carteira",
|
||||
|
||||
@@ -1295,7 +1295,11 @@
|
||||
"sweep_toggle": "Перевести в мой кошелёк (не сохранять ключ)",
|
||||
"sweep_tx": "Транзакция:",
|
||||
"switch_progress_background": "Продолжить в фоне",
|
||||
"switch_progress_default_wallet": "Кошелёк по умолчанию",
|
||||
"switch_progress_elapsed": "Прошло",
|
||||
"switch_progress_external_wallet": "Внешний кошелёк",
|
||||
"switch_progress_failed_title": "Не удалось переключить кошелёк",
|
||||
"switch_progress_from_label": "из",
|
||||
"switch_progress_hint": "Корректное завершение работы может занять до минуты.",
|
||||
"switch_progress_reconnecting": "Переподключение",
|
||||
"switch_progress_starting": "Запуск узла с новым кошельком",
|
||||
|
||||
@@ -1295,7 +1295,11 @@
|
||||
"sweep_toggle": "归集到我的钱包(不保留密钥)",
|
||||
"sweep_tx": "交易:",
|
||||
"switch_progress_background": "在后台继续",
|
||||
"switch_progress_default_wallet": "默认钱包",
|
||||
"switch_progress_elapsed": "已用时",
|
||||
"switch_progress_external_wallet": "外部钱包",
|
||||
"switch_progress_failed_title": "切换钱包失败",
|
||||
"switch_progress_from_label": "来自",
|
||||
"switch_progress_hint": "正常关闭最多可能需要一分钟。",
|
||||
"switch_progress_reconnecting": "正在重新连接",
|
||||
"switch_progress_starting": "正在以新钱包启动节点",
|
||||
|
||||
65
src/app.cpp
65
src/app.cpp
@@ -3870,10 +3870,24 @@ void App::renderSwitchStopDaemonDialog()
|
||||
const auto phase = static_cast<WalletSwitchPhase>(wallet_switch_phase_.load());
|
||||
const bool failed = progress && phase == WalletSwitchPhase::Failed;
|
||||
|
||||
// Prettify a wallet filename for display (wallet.dat → "Default wallet", wallet-savings.dat → "savings").
|
||||
auto pretty = [this](const std::string& f) -> std::string {
|
||||
if (f.empty() || f == "wallet.dat") return TR("switch_progress_default_wallet");
|
||||
std::string s = f;
|
||||
if (s.size() > 4 && s.substr(s.size() - 4) == ".dat") s.resize(s.size() - 4);
|
||||
if (s.rfind("wallet-ip-", 0) == 0) return TR("switch_progress_external_wallet");
|
||||
if (s.rfind("wallet-", 0) == 0) s = s.substr(7);
|
||||
return s;
|
||||
};
|
||||
const std::string toName = pretty(settings_ ? settings_->getActiveWalletFile() : std::string());
|
||||
|
||||
// Progress title carries the target wallet ("Switching wallet — savings"); keep the string alive.
|
||||
std::string titleStr = confirm ? std::string(TR("switch_stopnode_title"))
|
||||
: failed ? std::string(TR("switch_progress_failed_title"))
|
||||
: std::string(TR("switch_progress_title")) + " — " + toName;
|
||||
|
||||
ui::material::OverlayDialogSpec ov;
|
||||
ov.title = confirm ? TR("switch_stopnode_title")
|
||||
: failed ? TR("switch_progress_failed_title")
|
||||
: TR("switch_progress_title");
|
||||
ov.title = titleStr.c_str();
|
||||
// A confirm can be dismissed via X/backdrop (= cancel); a running switch cannot (stay until it's up).
|
||||
ov.p_open = confirm ? &show_switch_stop_daemon_confirm_ : nullptr;
|
||||
ov.style = ui::material::OverlayStyle::BlurFloat;
|
||||
@@ -3911,18 +3925,43 @@ void App::renderSwitchStopDaemonDialog()
|
||||
wallet_switch_error_.clear();
|
||||
}
|
||||
} else {
|
||||
// Live progress: an animated phase line, kept redrawing by isWalletSwitchInProgress().
|
||||
const char* status =
|
||||
phase == WalletSwitchPhase::Starting ? TR("switch_progress_starting")
|
||||
: phase == WalletSwitchPhase::Reconnecting ? TR("switch_progress_reconnecting")
|
||||
: TR("switch_progress_stopping");
|
||||
ImGui::Dummy(ImVec2(0, ui::Layout::spacingSm()));
|
||||
ui::material::Type().text(ui::material::TypeStyle::Subtitle1,
|
||||
(std::string(status) + ui::material::LoadingDots()).c_str());
|
||||
// Live progress, kept redrawing by isWalletSwitchInProgress().
|
||||
// Source context (the target is already in the title).
|
||||
ImGui::PushFont(ui::material::Type().caption());
|
||||
ImGui::TextDisabled("%s %s", TR("switch_progress_from_label"), pretty(wallet_switch_prev_file_).c_str());
|
||||
ImGui::PopFont();
|
||||
ImGui::Dummy(ImVec2(0, ui::Layout::spacingMd()));
|
||||
|
||||
// Primary status + detail. During Reconnecting the node is loading the block index / verifying /
|
||||
// rescanning — surface its live init stage (state_.warmup_status/description) instead of a bare
|
||||
// "Reconnecting…", so the ~30-60s wait shows real progress.
|
||||
std::string primary, detail;
|
||||
if (phase == WalletSwitchPhase::Stopping) {
|
||||
ImGui::Dummy(ImVec2(0, ui::Layout::spacingSm()));
|
||||
ImGui::TextWrapped("%s", TR("switch_progress_hint"));
|
||||
primary = TR("switch_progress_stopping");
|
||||
detail = TR("switch_progress_hint");
|
||||
} else if (phase == WalletSwitchPhase::Starting) {
|
||||
primary = TR("switch_progress_starting");
|
||||
} else { // Reconnecting
|
||||
if (!state_.warmup_status.empty()) { primary = state_.warmup_status; detail = state_.warmup_description; }
|
||||
else primary = TR("switch_progress_reconnecting");
|
||||
}
|
||||
ui::material::Type().text(ui::material::TypeStyle::Subtitle1,
|
||||
(primary + ui::material::LoadingDots()).c_str());
|
||||
if (!detail.empty()) {
|
||||
ImGui::Dummy(ImVec2(0, ui::Layout::spacingSm()));
|
||||
ImGui::PushFont(ui::material::Type().body2());
|
||||
ImGui::TextWrapped("%s", detail.c_str());
|
||||
ImGui::PopFont();
|
||||
}
|
||||
|
||||
// Elapsed timer — captured on the first progress frame (reset per switch in switchToWallet).
|
||||
if (wallet_switch_started_time_ <= 0.0) wallet_switch_started_time_ = ImGui::GetTime();
|
||||
const int el = static_cast<int>(ImGui::GetTime() - wallet_switch_started_time_);
|
||||
ImGui::Dummy(ImVec2(0, ui::Layout::spacingSm()));
|
||||
ImGui::PushFont(ui::material::Type().caption());
|
||||
ImGui::TextDisabled("%s %d:%02d", TR("switch_progress_elapsed"), el / 60, el % 60);
|
||||
ImGui::PopFont();
|
||||
|
||||
ImGui::Dummy(ImVec2(0, ui::Layout::spacingMd()));
|
||||
// Escape hatch — the switch keeps running in the background (a toast reports the result).
|
||||
if (ui::material::TactileButton(TR("switch_progress_background"), ImVec2(220.0f * dp, 0)))
|
||||
|
||||
@@ -779,6 +779,7 @@ private:
|
||||
std::atomic<int> wallet_switch_phase_{0};
|
||||
std::atomic<bool> wallet_switch_dialog_open_{false};
|
||||
std::string wallet_switch_error_;
|
||||
double wallet_switch_started_time_ = 0.0; // ImGui::GetTime() captured on first progress frame (elapsed)
|
||||
|
||||
// Set by the deleteBlockchainData worker (item count); the main loop surfaces a completion toast
|
||||
// and resets it to -1. Atomic because the worker thread writes it and the UI thread reads/clears it.
|
||||
|
||||
@@ -1113,6 +1113,7 @@ void App::switchToWallet(const std::string& walletFile, bool stopDaemonConfirmed
|
||||
// Open the switch progress modal — it stays up through stop → wait-for-exit → start → reconnect and
|
||||
// auto-closes when the new node connects (onConnected). The worker advances the phase from here.
|
||||
wallet_switch_error_.clear();
|
||||
wallet_switch_started_time_ = 0.0; // re-captured on the first progress frame → elapsed starts fresh
|
||||
wallet_switch_phase_.store(static_cast<int>(WalletSwitchPhase::Stopping));
|
||||
wallet_switch_dialog_open_.store(true);
|
||||
|
||||
|
||||
@@ -1053,6 +1053,10 @@ void I18n::loadBuiltinEnglish()
|
||||
strings_["switch_progress_reconnecting"] = "Reconnecting";
|
||||
strings_["switch_progress_hint"] = "A graceful shutdown can take up to a minute.";
|
||||
strings_["switch_progress_background"] = "Continue in background";
|
||||
strings_["switch_progress_from_label"] = "from";
|
||||
strings_["switch_progress_elapsed"] = "Elapsed";
|
||||
strings_["switch_progress_default_wallet"] = "Default wallet";
|
||||
strings_["switch_progress_external_wallet"] = "External wallet";
|
||||
|
||||
// Receive Tab
|
||||
strings_["receiving_addresses"] = "Your Receiving Addresses";
|
||||
|
||||
Reference in New Issue
Block a user