fix(ui): show real data and consistent values across tabs

- Market chart now plots the real accumulated price_history instead of a
  rand()-generated curve; the hover tooltip no longer claims a specific "Xh ago"
  price and the x-axis only labels the truthful "Now" point. Falls back to the
  existing empty state until there are >=2 real samples.
- Transactions summary cards exclude autoshield legs (same txid send + receive-to-z)
  so a shield isn't double-counted into both Sent and Received, matching the list.
- Send/Receive sync banners use verification_progress like every other surface,
  instead of the blocks/headers ratio that over-reports during early sync.
- Fix printf format/type mismatches: %.0f<-int (market % shielded), %d<-size_t
  (peer counts), %ld<-int64_t (peer byte counters, wrong on Windows).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-07 14:17:42 -05:00
parent 53a10e149d
commit 3799330bb0
5 changed files with 62 additions and 39 deletions

View File

@@ -29,8 +29,7 @@ namespace ui {
using namespace material;
// ---- Market tab persistent state ----
static std::vector<double> s_price_history;
static std::vector<double> s_time_history;
static std::vector<double> s_price_history; // mirror of WalletState market.price_history
static bool s_history_initialized = false;
static double s_last_refresh_time = 0.0;
@@ -322,18 +321,11 @@ void RenderMarketTab(App* app)
// PRICE CHART — Custom drawn inside glass panel (matches app design)
// ================================================================
{
// Initialize history with simulated data if not set
if (!s_history_initialized && market.price_usd > 0) {
s_price_history.clear();
s_time_history.clear();
double base = market.price_usd;
for (int i = 0; i < 24; i++) {
double variance = ((rand() % 1000) - 500) / 10000.0 * base;
s_price_history.push_back(base + variance);
s_time_history.push_back(static_cast<double>(i));
}
s_history_initialized = true;
}
// Plot the REAL accumulated price history (one point per refresh, oldest→newest).
// No synthetic data: until at least two real samples exist, the empty-state below
// ("not enough history yet") is shown rather than inventing a price curve.
s_price_history = market.price_history;
s_history_initialized = true;
// Chart height from schema
float chartH = std::max(60.0f, chartElem.height * vs);
@@ -411,19 +403,14 @@ void RenderMarketTab(App* app)
dl->AddCircleFilled(points[i], dotR, dotCol);
}
// X-axis labels
const int xlabels[] = {0, 6, 12, 18, 23};
const char* xlabelText[] = {TR("market_24h"), TR("market_18h"), TR("market_12h"), TR("market_6h"), TR("market_now")};
for (int xi = 0; xi < 5; xi++) {
int idx = xlabels[xi];
float t = (float)idx / (float)(n - 1);
float x = plotLeft + t * plotW;
ImVec2 lblSz = capFont->CalcTextSizeA(capFont->LegacySize, FLT_MAX, 0, xlabelText[xi]);
float lx = x - lblSz.x * 0.5f;
if (lx < plotLeft) lx = plotLeft;
if (lx + lblSz.x > plotRight) lx = plotRight - lblSz.x;
// X-axis: samples are per-refresh, not hourly-timestamped, so only the most
// recent point can be labelled truthfully ("Now"). The series simply runs
// older→newer, left→right. (Avoids the old fake "24h…6h" hourly gradations.)
{
const char* nowText = TR("market_now");
ImVec2 lblSz = capFont->CalcTextSizeA(capFont->LegacySize, FLT_MAX, 0, nowText);
dl->AddText(capFont, capFont->LegacySize,
ImVec2(lx, plotBottom + 2), OnSurfaceDisabled(), xlabelText[xi]);
ImVec2(plotRight - lblSz.x, plotBottom + 2), OnSurfaceDisabled(), nowText);
}
// Hover crosshair + tooltip
@@ -450,8 +437,9 @@ void RenderMarketTab(App* app)
dl->AddCircleFilled(ImVec2(px, py), hoverDotR, dotCol);
dl->AddCircle(ImVec2(px, py), hoverRingR, IM_COL32(255, 255, 255, 80), 0, 1.5f);
snprintf(buf, sizeof(buf), "%dh ago: %s",
24 - idx, FormatPrice(s_price_history[idx]).c_str());
// Samples are per-refresh, not timestamped, so we don't claim a specific
// "Xh ago" — just show the price at the hovered point.
snprintf(buf, sizeof(buf), "%s", FormatPrice(s_price_history[idx]).c_str());
ImVec2 tipSz = capFont->CalcTextSizeA(capFont->LegacySize, FLT_MAX, 0, buf);
float tipPad = Layout::spacingSm() + Layout::spacingXs();
float tipX = px + 10;
@@ -843,8 +831,10 @@ void RenderMarketTab(App* app)
WithAlpha(Warning(), 200),
shieldedW > 0.5f ? ImDrawFlags_RoundCornersRight : ImDrawFlags_RoundCornersAll, 3.0f);
int pct = (int)(shieldedRatio * 100.0f + 0.5f);
snprintf(buf, sizeof(buf), TR("market_pct_shielded"), pct);
// market_pct_shielded is "%.0f%% Shielded" — pass a double, not an int (passing
// an int to a %f conversion is UB and renders garbage on x86-64).
snprintf(buf, sizeof(buf), TR("market_pct_shielded"),
static_cast<double>(shieldedRatio) * 100.0);
dl->AddText(capFont, capFont->LegacySize,
ImVec2(cx, cy + barH + 2), OnSurfaceDisabled(), buf);
}