fix: accurate sync speed display, add missing i18n keys, native language names

- Fix blk/s calculation that was inflated ~10x due to resetting the
  time baseline every frame instead of only when blocks advanced
- Add decay when no new blocks arrive for 10s so rate doesn't stay stale
- Add 7 missing translation keys (timeout_off/1min/5min/15min/30min/1hour,
  slider_off) to all 8 language files so settings dropdowns translate
- Show language names in native script (中文, Русский, 日本語, 한국어)
This commit is contained in:
2026-04-12 15:12:36 -05:00
parent d2dccbac05
commit 6e2db50675
20 changed files with 5169 additions and 4910 deletions

View File

@@ -1081,15 +1081,16 @@ void App::render()
int fgVtxStart = fgDL->VtxBuffer.Size;
// ---------------------------------------------------------------
// Loading overlay — show only while daemon is not yet connected.
// Once connected, all tabs render normally; individual tabs show
// inline sync-progress indicators when the chain is still syncing.
// Pages that remain accessible even without a connection:
// Console, Peers, Settings
// Loading overlay — show only on tabs that truly need wallet data.
// Tabs that work without full daemon connection:
// Console, Peers, Settings, Market, Mining
// Tabs that need balance/transaction data (show overlay):
// Overview, Send, Receive, History
// ---------------------------------------------------------------
bool pageNeedsDaemon = (current_page_ != ui::NavPage::Console &&
current_page_ != ui::NavPage::Peers &&
current_page_ != ui::NavPage::Settings);
bool pageNeedsWalletData = (current_page_ == ui::NavPage::Overview ||
current_page_ == ui::NavPage::Send ||
current_page_ == ui::NavPage::Receive ||
current_page_ == ui::NavPage::History);
bool daemonReady = state_.connected && !state_.warming_up;
// Don't show lock screen while pool mining — xmrig runs independently
@@ -1098,12 +1099,12 @@ void App::render()
if (state_.isLocked() && !poolMiningActive) {
// Lock screen — covers tab content just like the loading overlay
renderLockScreen();
} else if (state_.warming_up) {
} else if (pageNeedsWalletData && state_.warming_up) {
// Daemon is reachable but still initializing — show warmup overlay
// without blocking on encryption state (getwalletinfo fails during warmup)
// only on wallet-data tabs. Other tabs render normally.
lock_screen_was_visible_ = false;
renderLoadingOverlay(contentH);
} else if (pageNeedsDaemon && (!daemonReady || (state_.connected && !state_.encryption_state_known))) {
} else if (pageNeedsWalletData && (!daemonReady || (state_.connected && !state_.encryption_state_known))) {
// Track how long we've been waiting for encryption state
if (state_.connected && !state_.encryption_state_known) {
encryption_check_timer_ += ImGui::GetIO().DeltaTime;
@@ -1484,7 +1485,11 @@ void App::renderStatusBar()
static double s_prev_time = 0.0;
static double s_blocks_per_sec = 0.0;
double now = ImGui::GetTime();
if (s_prev_time > 0.0 && state_.sync.blocks > s_prev_blocks) {
if (s_prev_time == 0.0) {
// First sample — seed baseline, don't compute rate yet
s_prev_blocks = state_.sync.blocks;
s_prev_time = now;
} else if (state_.sync.blocks > s_prev_blocks) {
double dt = now - s_prev_time;
if (dt > 0.5) {
double raw = (state_.sync.blocks - s_prev_blocks) / dt;
@@ -1495,9 +1500,10 @@ void App::renderStatusBar()
s_prev_blocks = state_.sync.blocks;
s_prev_time = now;
}
} else {
s_prev_blocks = state_.sync.blocks;
s_prev_time = now;
} else if (now - s_prev_time > 10.0) {
// No new blocks for 10s — decay the displayed rate
s_blocks_per_sec *= 0.5;
s_prev_time = now;
}
if (s_blocks_per_sec > 0.1) {
@@ -2786,6 +2792,21 @@ void App::renderLoadingOverlay(float contentH)
curY += ts.y + gap;
}
// -------------------------------------------------------------------
// 2b. Warmup description (subtitle explaining what's happening)
// -------------------------------------------------------------------
if (state_.warming_up && !state_.warmup_description.empty()) {
const char* descText = state_.warmup_description.c_str();
ImFont* capFont = Type().caption();
if (!capFont) capFont = ImGui::GetFont();
// Wrap to barW so long descriptions don't overflow
ImVec2 ts = capFont->CalcTextSizeA(capFont->LegacySize, FLT_MAX, barW, descText);
dl->AddText(capFont, capFont->LegacySize,
ImVec2(wp.x + cx - ts.x * 0.5f, curY),
IM_COL32(160, 160, 160, 200), descText, nullptr, barW);
curY += ts.y + gap;
}
// -------------------------------------------------------------------
// 3. Sync progress bar (if connected and syncing)
// -------------------------------------------------------------------