feat(balance): show a "catching up — funds are safe" strip while syncing
A syncing node skips the balance RPC, so the balance card paints a bare 0.00000000 / $-.-- that reads as lost funds after an update (a documented support trap). Add one shared notice at the top of the Balance tab — above every layout — shown only for the normal catching-up case (connected, network tip known, still verifying, not a rescan/witness rebuild). Offline, no-peers, a busy node and rescans stay the node-status banner's job, so the two never stack. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -205,6 +205,39 @@ void RenderBalanceTab(App* app)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Shared "still catching up" strip, above whichever layout renders, so a syncing node's 0 / stale
|
||||||
|
// balance is never mistaken for lost funds (the documented "my coins vanished after an update"
|
||||||
|
// trap). Scoped to the NORMAL catching-up case — connected, a network tip is known, still verifying
|
||||||
|
// blocks, and not in a rescan / witness rebuild. Offline, no-peers, a busy node and rescans are
|
||||||
|
// already surfaced by the node-status banner, so this never stacks a second banner on them.
|
||||||
|
{
|
||||||
|
namespace m = material;
|
||||||
|
const auto& st = app->state();
|
||||||
|
if (st.connected && st.sync.tip_known && st.sync.syncing &&
|
||||||
|
!st.sync.building_witnesses && !st.sync.rescanning) {
|
||||||
|
ImFont* ico = m::Type().iconSmall();
|
||||||
|
ImFont* txt = m::Type().body2();
|
||||||
|
const float padX = ui::Layout::spacingMd();
|
||||||
|
const float padY = ui::Layout::spacingSm();
|
||||||
|
const float availW = ImGui::GetContentRegionAvail().x;
|
||||||
|
char line[192];
|
||||||
|
snprintf(line, sizeof(line), TR("balance_catchup_notice"),
|
||||||
|
static_cast<float>(st.sync.verification_progress) * 100.0f);
|
||||||
|
const float iconW = ico->LegacySize + padX * 0.5f;
|
||||||
|
const float wrapW = std::max(1.0f, availW - padX * 2.0f - iconW);
|
||||||
|
ImVec2 tsz = txt->CalcTextSizeA(txt->LegacySize, FLT_MAX, wrapW, line);
|
||||||
|
const float h = std::max(ico->LegacySize, tsz.y) + padY * 2.0f;
|
||||||
|
ImVec2 p0 = ImGui::GetCursorScreenPos();
|
||||||
|
ImDrawList* dl = ImGui::GetWindowDrawList();
|
||||||
|
dl->AddRectFilled(p0, ImVec2(p0.x + availW, p0.y + h),
|
||||||
|
m::WithAlphaF(m::Warning(), 0.13f), ui::Layout::glassRounding());
|
||||||
|
dl->AddText(ico, ico->LegacySize, ImVec2(p0.x + padX, p0.y + padY), m::Warning(), ICON_MD_SYNC);
|
||||||
|
dl->AddText(txt, txt->LegacySize, ImVec2(p0.x + padX + iconW, p0.y + padY),
|
||||||
|
m::OnSurfaceMedium(), line, nullptr, wrapW);
|
||||||
|
ImGui::Dummy(ImVec2(availW, h + ui::Layout::spacingSm()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Dispatch by string ID
|
// Dispatch by string ID
|
||||||
for (const auto& entry : s_layoutDispatch) {
|
for (const auto& entry : s_layoutDispatch) {
|
||||||
if (layoutId == entry.id) {
|
if (layoutId == entry.id) {
|
||||||
|
|||||||
@@ -1237,6 +1237,7 @@ void I18n::loadBuiltinEnglish()
|
|||||||
strings_["balance_shielded_fmt"] = "Shielded: %.8f";
|
strings_["balance_shielded_fmt"] = "Shielded: %.8f";
|
||||||
strings_["total_balance_label"] = "Total Balance";
|
strings_["total_balance_label"] = "Total Balance";
|
||||||
strings_["balance_syncing_pct"] = "Syncing %.1f%%";
|
strings_["balance_syncing_pct"] = "Syncing %.1f%%";
|
||||||
|
strings_["balance_catchup_notice"] = "Catching up to the network (%.0f%%) — your balance will finish updating when sync completes. Your funds are safe.";
|
||||||
strings_["balance_mining_rate"] = "Mining %s";
|
strings_["balance_mining_rate"] = "Mining %s";
|
||||||
strings_["balance_layout_switched"] = "Layout: %s";
|
strings_["balance_layout_switched"] = "Layout: %s";
|
||||||
strings_["byte_count_fmt"] = "%zu / %zu bytes";
|
strings_["byte_count_fmt"] = "%zu / %zu bytes";
|
||||||
|
|||||||
Reference in New Issue
Block a user