feat(ui): say "Node busy" instead of "Launching dragonxd"; honest quit copy

A node rebuilding note witnesses for an hour was shown as "Starting
DragonX node... Launching dragonxd", which invited closing it.

- Overlay, a new NodeBusy banner and the status bar now say what the node
  is doing (rebuilding witnesses / catching up on blocks / up but not
  answering), with the elapsed time and Phase-1 block progress. A rebuild
  during startup warm-up replaces the stale "-28 Activating best chain"
  text, and the overlay re-applies its text once a second instead of only
  on a connect attempt (30s apart while the node is busy).
- Quit prompt: elapsed time, "Keep node running & quit" is the default,
  "Stop anyway & quit" becomes "Stop node & wait" (it no longer kills).
- A reinstall skipped because the node is still running now notifies.
- Status bar: don't repeat the warm-up status on the right, and don't
  print "Connected" there in non-English locales.
- i18n: 31 new keys in all 8 languages; 10 dead force-quit/old-modal keys
  removed; CJK subset rebuilt for the new glyphs.
- Tests: chooseDaemonStatus, NodeBusy banner priority, and every new key
  present in all 8 JSONs with matching printf conversions.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-02 10:26:32 -05:00
co-authored by Claude Opus 5.5
parent 0f25c67600
commit 1215ded1a0
17 changed files with 822 additions and 133 deletions
+23 -12
View File
@@ -582,14 +582,9 @@ void I18n::loadBuiltinEnglish()
strings_["incorrect_passphrase"] = "Incorrect passphrase";
strings_["pin_not_set"] = "PIN not set. Use passphrase to unlock.";
strings_["restarting_after_encryption"] = "Restarting daemon after encryption...";
strings_["force_quit"] = "Force Quit";
strings_["force_quit_warning"] = "This will immediately kill the daemon without a clean shutdown. May require a blockchain resync.";
strings_["force_quit_confirm_title"] = "Force Quit?";
strings_["force_quit_confirm_msg"] = "This will immediately kill the daemon without a clean shutdown.\nThis may corrupt the blockchain index and require a resync.";
strings_["force_quit_yes"] = "Force Quit";
// Stopping the node on quit: deliver stop, wait, never kill unasked (translations: S10 batch)
// Stopping the node on quit: deliver stop, wait, never kill unasked
strings_["shutdown_leave_running"] = "Close wallet — leave node running";
strings_["shutdown_leave_running_tip"] = "Closes the wallet now. The node keeps running and finishes shutting down on its own; nothing is lost.";
strings_["shutdown_leave_running_tip"] = "Closes the wallet now. The node keeps running on its own and finishes what it is doing; nothing is lost.";
strings_["shutdown_kill_node"] = "Kill node (unsafe)";
strings_["shutdown_kill_node_tip"] = "Ends the node at once. Anything it has not saved is lost, and its next start replays the blocks since its last save.";
strings_["shutdown_kill_confirm_title"] = "Kill the node?";
@@ -600,6 +595,27 @@ void I18n::loadBuiltinEnglish()
strings_["shutdown_stop_delivered"] = "The node is shutting down and saving its state";
strings_["shutdown_stop_cpu_suffix"] = " · CPU %d%%";
strings_["shutdown_stop_idle"] = "No CPU or disk activity for %d min — the node may be stuck";
// The node is busy (S9): overlay, banner, status bar
strings_["node_busy_rebuild_title"] = "Node busy: rebuilding note witnesses";
strings_["node_busy_running"] = "Running for %s";
strings_["node_busy_rebuild_desc"] = "Running for %s. Large wallets can take about an hour, and the node can't answer the wallet until it finishes.";
strings_["node_busy_rebuild_reading"] = "Reading blocks: %ld / %ld";
strings_["node_busy_rebuild_extending"] = "Extending witnesses (the node reports no progress for this step).";
strings_["node_busy_replay_title"] = "Node busy: catching up on blocks";
strings_["node_busy_replay_desc"] = "Running for %s. The node is re-applying blocks it received before it last stopped.";
strings_["node_busy_rpc_title"] = "Node busy: not answering yet";
strings_["node_busy_rpc_desc"] = "The node is running but has been too busy to answer the wallet for %s, usually because of a long operation such as a witness rebuild.";
strings_["node_starting_title"] = "Starting DragonX node…";
strings_["node_starting_busy_desc"] = "The node is reachable but busy and isn't answering yet. This is normal after an update or on first launch; it can take a few minutes.";
strings_["node_starting_launch_desc"] = "Launching dragonxd and waiting for it to come online…";
strings_["sb_node_busy"] = "Node busy";
// Quit while the node is busy (S10)
strings_["stopconfirm_rebuild_title"] = "The node is rebuilding note witnesses";
strings_["stopconfirm_rebuild_body"] = "It has been running for %s, and large wallets can take about an hour. Stopping the node now either waits for the rebuild to finish or makes its next start redo the rebuild and any catch-up.\n\nRecommended: close the wallet and leave the node running. It finishes on its own.";
strings_["stopconfirm_busy_title"] = "The node is busy";
strings_["stopconfirm_busy_body"] = "It has been too busy to answer the wallet for %s, probably because of a long operation such as a witness rebuild. Stopping it now can make its next start redo that work.\n\nRecommended: close the wallet and leave the node running. It finishes on its own.";
strings_["stopconfirm_stop_wait"] = "Stop node & wait";
strings_["appx_daemon_reinstall_node_busy"] = "The node is still running, so the daemon was not reinstalled. Try again once it has stopped.";
strings_["reduce_motion"] = "Reduce Motion";
strings_["tt_reduce_motion"] = "Disable animated transitions and balance lerp for accessibility";
strings_["ago"] = "ago";
@@ -2638,10 +2654,7 @@ void I18n::loadBuiltinEnglish()
strings_["appx_restoring_your_wallet"] = "Restoring your wallet…";
strings_["appx_recovery_phrase_word_count"] = "Recovery phrase should be 24 words — you have %d.";
strings_["appx_could_not_start_restore"] = "Could not start restore";
strings_["appx_node_rebuilding_witness_cache"] = "Node is rebuilding its witness cache";
strings_["appx_stopping_node_discards_rebuild"] = "Stopping the node now discards the in-progress rebuild and restarts it (several minutes) the next time you open the wallet. You can keep the node running instead.";
strings_["appx_keep_node_running_and_quit"] = "Keep node running & quit";
strings_["appx_stop_anyway_and_quit"] = "Stop anyway & quit";
strings_["appx_cancel"] = "Cancel";
strings_["appx_last_used_wallet_not_found_prefix"] = "Your last-used wallet file (";
strings_["appx_last_used_wallet_not_found_suffix"] = ") was not found — opened the default wallet instead. If you moved it, restore it and switch back from the wallet list.";
@@ -2671,8 +2684,6 @@ void I18n::loadBuiltinEnglish()
strings_["appx_shutdown_complete"] = "Shutdown complete";
strings_["appx_n_seconds"] = "%d seconds";
strings_["appx_n_min_n_sec"] = "%d min %d sec";
strings_["appx_still_status_prefix"] = "Still \"";
strings_["appx_still_status_suffix"] = "\" — force quitting now may corrupt chain data.";
strings_["appx_rebuilding_witness_cache_blocks_left"] = "Rebuilding witness cache %.0f%% — %d blocks left";
strings_["appx_rebuilding_witness_cache_pct"] = "Rebuilding witness cache %.0f%%";
strings_["appx_setting_initial_sapling_witnesses"] = "Setting initial Sapling witnesses %.0f%%";