feat(market): rework tab layout — responsive chart + refined portfolio + group cards
The Market tab is non-scrolling, but an oversized fixed-height chart ate ~65%
of the height and squeezed the portfolio into a cramped strip, with custom
groups rendered as tiny afterthought rows at the very bottom.
- Precompute section geometry (hero header + portfolio card height) up front and
let the price chart ABSORB the remaining vertical space, capped at its schema
height and floored at 130px*vs so it stays useful. The chart now shrinks to
make room instead of dominating. Replaces the barely-used SectionBudget.
- Portfolio summary refined: fiat value stays the hero with the 24h change beside
it and the BTC value right-aligned; DRGX balance + Z/T breakdown on the next
row; a full-width shielded/transparent ratio bar + % label.
- Custom groups now render as a wrapping grid of mini glass cards (label + DRGX +
fiat each), sized to the card width, instead of a cramped one-line list. A
"GROUPS" subheader separates them from the all-funds summary. The card grows to
fit the grid.
New i18n key portfolio_groups ("GROUPS"). Full-node + Lite build clean; ctest
1/1; hygiene clean. Rendering change — needs a screenshot check of the Market tab.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -276,16 +276,52 @@ void RenderMarketTab(App* app)
|
|||||||
char buf[128];
|
char buf[128];
|
||||||
|
|
||||||
// ================================================================
|
// ================================================================
|
||||||
// Proportional section budget — all content fits without scrolling
|
// Section geometry — this tab does NOT scroll, so everything must fit. Precompute the
|
||||||
|
// portfolio card height (refined summary + a grid of group cards) and the hero header,
|
||||||
|
// then let the price chart absorb the remaining vertical space (capped at its schema
|
||||||
|
// height, floored so it stays useful). Fixes the old layout where an oversized chart
|
||||||
|
// squeezed the portfolio into a cramped strip.
|
||||||
// ================================================================
|
// ================================================================
|
||||||
float mkSHdr = ovFont->LegacySize + Layout::spacingXs()
|
float mktDp = Layout::dpiScale();
|
||||||
+ ImGui::GetStyle().ItemSpacing.y * 2.0f;
|
|
||||||
float mkGapOver = gap + ImGui::GetStyle().ItemSpacing.y;
|
|
||||||
float mkOverhead = 3.0f * (mkSHdr + mkGapOver) + 2.0f * mkGapOver;
|
|
||||||
float mkCardBudget = std::max(200.0f, marketAvail.y - mkOverhead);
|
|
||||||
|
|
||||||
Layout::SectionBudget mb(mkCardBudget);
|
// -- Portfolio card geometry --
|
||||||
float portfolioBudgetH = mb.allocate(0.18f, 50.0f);
|
const auto& pfEntriesGeo = app->settings()->getPortfolioEntries();
|
||||||
|
float pfInnerW = availWidth - Layout::spacingLg() * 2.0f;
|
||||||
|
float ratioBarH = std::max(S.drawElement("tabs.market", "ratio-bar-min-height").size,
|
||||||
|
S.drawElement("tabs.market", "ratio-bar-height").size * vs);
|
||||||
|
float pfSummaryH = Layout::spacingLg()
|
||||||
|
+ sub1->LegacySize + Layout::spacingSm() // fiat hero row
|
||||||
|
+ body2->LegacySize + Layout::spacingSm() // DRGX balance row
|
||||||
|
+ ratioBarH + Layout::spacingXs() + capFont->LegacySize // ratio bar + % label
|
||||||
|
+ Layout::spacingMd(); // bottom pad
|
||||||
|
int pfN = (int)pfEntriesGeo.size();
|
||||||
|
float pfCardGap = Layout::spacingSm();
|
||||||
|
float pfMinCardW = 200.0f * mktDp;
|
||||||
|
int pfCardsPerRow = std::max(1, (int)((pfInnerW + pfCardGap) / (pfMinCardW + pfCardGap)));
|
||||||
|
if (pfN > 0 && pfCardsPerRow > pfN) pfCardsPerRow = pfN;
|
||||||
|
float pfCardW = (pfN > 0) ? (pfInnerW - (pfCardsPerRow - 1) * pfCardGap) / (float)pfCardsPerRow : 0.0f;
|
||||||
|
float pfCardH = body2->LegacySize + Layout::spacingXs() + body2->LegacySize
|
||||||
|
+ capFont->LegacySize + Layout::spacingSm() * 2.0f;
|
||||||
|
int pfRows = (pfN > 0) ? (pfN + pfCardsPerRow - 1) / pfCardsPerRow : 0;
|
||||||
|
float pfGroupsH = (pfN > 0)
|
||||||
|
? (ovFont->LegacySize + Layout::spacingSm()
|
||||||
|
+ pfRows * pfCardH + std::max(0, pfRows - 1) * pfCardGap
|
||||||
|
+ Layout::spacingMd())
|
||||||
|
: 0.0f;
|
||||||
|
float portfolioCardH = pfSummaryH + pfGroupsH;
|
||||||
|
|
||||||
|
// -- Hero header (price + stats, excluding the chart) --
|
||||||
|
float mktStatsRowH = ovFont->LegacySize + Layout::spacingXs() + sub1->LegacySize + pad;
|
||||||
|
float heroHeaderH = std::max(
|
||||||
|
S.drawElement("tabs.market", "hero-card-min-height").size + mktStatsRowH + pad,
|
||||||
|
(S.drawElement("tabs.market", "hero-card-height").size + mktStatsRowH + pad) * vs);
|
||||||
|
|
||||||
|
// -- Chart absorbs the slack: capped at its schema height, floored so it stays useful --
|
||||||
|
float mktChipH = S.drawElement("tabs.market", "pair-chip-height").height;
|
||||||
|
float mktPairsReserve = mktChipH * 2.0f + Layout::spacingXl() + capFont->LegacySize;
|
||||||
|
float chartH = std::min(chartElem.height * vs,
|
||||||
|
marketAvail.y - heroHeaderH - portfolioCardH - mktPairsReserve - gap * 3.0f);
|
||||||
|
chartH = std::max(chartH, 130.0f * vs);
|
||||||
|
|
||||||
// ================================================================
|
// ================================================================
|
||||||
// PRICE SUMMARY — Combined hero card with price, stats, and exchange
|
// PRICE SUMMARY — Combined hero card with price, stats, and exchange
|
||||||
@@ -293,13 +329,11 @@ void RenderMarketTab(App* app)
|
|||||||
{
|
{
|
||||||
float dp = Layout::dpiScale();
|
float dp = Layout::dpiScale();
|
||||||
ImVec2 cardMin = ImGui::GetCursorScreenPos();
|
ImVec2 cardMin = ImGui::GetCursorScreenPos();
|
||||||
float heroMinH = S.drawElement("tabs.market", "hero-card-min-height").size;
|
float cardH = heroHeaderH;
|
||||||
float statsRowH = ovFont->LegacySize + Layout::spacingXs() + sub1->LegacySize + pad;
|
|
||||||
float cardH = std::max(heroMinH + statsRowH + pad, (S.drawElement("tabs.market", "hero-card-height").size + statsRowH + pad) * vs);
|
|
||||||
ImVec2 cardMax(cardMin.x + availWidth, cardMin.y + cardH);
|
ImVec2 cardMax(cardMin.x + availWidth, cardMin.y + cardH);
|
||||||
// Combined hero + chart: draw ONE glass panel spanning the price/stats header AND the
|
// Combined hero + chart: draw ONE glass panel spanning the price/stats header AND the
|
||||||
// chart below it. The chart block no longer draws its own panel or an inter-card gap.
|
// chart below it (chartH precomputed so the chart shrinks to fit the portfolio).
|
||||||
float mergedChartH = std::max(60.0f, chartElem.height * vs);
|
float mergedChartH = chartH;
|
||||||
ImVec2 mergedMax(cardMin.x + availWidth, cardMax.y + mergedChartH);
|
ImVec2 mergedMax(cardMin.x + availWidth, cardMax.y + mergedChartH);
|
||||||
DrawGlassPanel(dl, cardMin, mergedMax, glassSpec);
|
DrawGlassPanel(dl, cardMin, mergedMax, glassSpec);
|
||||||
|
|
||||||
@@ -448,9 +482,9 @@ void RenderMarketTab(App* app)
|
|||||||
s_price_history = market.price_history;
|
s_price_history = market.price_history;
|
||||||
s_history_initialized = true;
|
s_history_initialized = true;
|
||||||
|
|
||||||
// Chart height from schema. No glass panel here — it shares the combined hero+chart
|
// Chart height precomputed above (responsive — the chart absorbs the vertical slack
|
||||||
// card's panel drawn in PRICE SUMMARY above (mergedChartH uses this same height).
|
// left by the hero header + portfolio card). No glass panel here — it shares the
|
||||||
float chartH = std::max(60.0f, chartElem.height * vs);
|
// combined hero+chart card's panel drawn in PRICE SUMMARY above.
|
||||||
ImVec2 chartMin = ImGui::GetCursorScreenPos();
|
ImVec2 chartMin = ImGui::GetCursorScreenPos();
|
||||||
ImVec2 chartMax(chartMin.x + availWidth, chartMin.y + chartH);
|
ImVec2 chartMax(chartMin.x + availWidth, chartMin.y + chartH);
|
||||||
|
|
||||||
@@ -741,111 +775,126 @@ void RenderMarketTab(App* app)
|
|||||||
double private_balance = state.privateBalance;
|
double private_balance = state.privateBalance;
|
||||||
double transparent_balance = state.transparentBalance;
|
double transparent_balance = state.transparentBalance;
|
||||||
|
|
||||||
// Custom portfolio entries render below the "all funds" summary; grow the card to fit.
|
|
||||||
const auto& pfEntries = app->settings()->getPortfolioEntries();
|
|
||||||
float entryRowH = body2->LegacySize + Layout::spacingSm();
|
|
||||||
float entriesBlockH = pfEntries.empty()
|
|
||||||
? 0.0f
|
|
||||||
: (Layout::spacingSm() * 2.0f + (float)pfEntries.size() * entryRowH);
|
|
||||||
|
|
||||||
ImVec2 cardMin = ImGui::GetCursorScreenPos();
|
ImVec2 cardMin = ImGui::GetCursorScreenPos();
|
||||||
float baseH = std::max(60.0f, portfolioBudgetH);
|
float cardH = portfolioCardH; // precomputed: summary block + group-card grid
|
||||||
float cardH = baseH + entriesBlockH;
|
|
||||||
ImVec2 cardMax(cardMin.x + availWidth, cardMin.y + cardH);
|
ImVec2 cardMax(cardMin.x + availWidth, cardMin.y + cardH);
|
||||||
DrawGlassPanel(dl, cardMin, cardMax, glassSpec);
|
DrawGlassPanel(dl, cardMin, cardMax, glassSpec);
|
||||||
|
|
||||||
float cx = cardMin.x + Layout::spacingLg();
|
float cx = cardMin.x + Layout::spacingLg();
|
||||||
float cy = cardMin.y + Layout::spacingLg();
|
float cy = cardMin.y + Layout::spacingLg();
|
||||||
|
|
||||||
|
// ---- SUMMARY: fiat value (hero) + 24h change, BTC right-aligned ----
|
||||||
if (market.price_usd > 0) {
|
if (market.price_usd > 0) {
|
||||||
double portfolio_usd = total_balance * market.price_usd;
|
double portfolio_usd = total_balance * market.price_usd;
|
||||||
if (portfolio_usd >= 1.0)
|
if (portfolio_usd >= 1.0) snprintf(buf, sizeof(buf), "$%.2f USD", portfolio_usd);
|
||||||
snprintf(buf, sizeof(buf), "$%.2f USD", portfolio_usd);
|
else snprintf(buf, sizeof(buf), "$%.6f USD", portfolio_usd);
|
||||||
else
|
|
||||||
snprintf(buf, sizeof(buf), "$%.6f USD", portfolio_usd);
|
|
||||||
DrawTextShadow(dl, sub1, sub1->LegacySize, ImVec2(cx, cy), Success(), buf);
|
DrawTextShadow(dl, sub1, sub1->LegacySize, ImVec2(cx, cy), Success(), buf);
|
||||||
|
float usdW = sub1->CalcTextSizeA(sub1->LegacySize, FLT_MAX, 0, buf).x;
|
||||||
|
|
||||||
// 24h change on the holdings (the coin's 24h % applies to the value), shown
|
|
||||||
// beside the USD figure and colored by direction.
|
|
||||||
if (market.change_24h != 0.0) {
|
if (market.change_24h != 0.0) {
|
||||||
float usdW = sub1->CalcTextSizeA(sub1->LegacySize, FLT_MAX, 0, buf).x;
|
|
||||||
char chg[48];
|
char chg[48];
|
||||||
snprintf(chg, sizeof(chg), "%+.2f%% %s", market.change_24h, TR("market_24h_change"));
|
snprintf(chg, sizeof(chg), "%+.2f%% %s", market.change_24h, TR("market_24h_change"));
|
||||||
ImU32 chgCol = market.change_24h >= 0 ? Success() : Error();
|
ImU32 chgCol = market.change_24h >= 0 ? Success() : Error();
|
||||||
dl->AddText(capFont, capFont->LegacySize,
|
dl->AddText(capFont, capFont->LegacySize,
|
||||||
ImVec2(cx + usdW + Layout::spacingMd(), cy + 3), chgCol, chg);
|
ImVec2(cx + usdW + Layout::spacingMd(),
|
||||||
|
cy + (sub1->LegacySize - capFont->LegacySize)),
|
||||||
|
chgCol, chg);
|
||||||
}
|
}
|
||||||
|
|
||||||
double portfolio_btc = total_balance * market.price_btc;
|
double portfolio_btc = total_balance * market.price_btc;
|
||||||
snprintf(buf, sizeof(buf), "%.10f BTC", portfolio_btc);
|
snprintf(buf, sizeof(buf), "\xE2\x89\x88 %.8f BTC", portfolio_btc); // "≈ <n> BTC"
|
||||||
float valW = sub1->CalcTextSizeA(sub1->LegacySize, FLT_MAX, 0, buf).x;
|
float btcW = capFont->CalcTextSizeA(capFont->LegacySize, FLT_MAX, 0, buf).x;
|
||||||
dl->AddText(capFont, capFont->LegacySize,
|
dl->AddText(capFont, capFont->LegacySize,
|
||||||
ImVec2(cardMax.x - valW - pad, cy + 2), OnSurfaceMedium(), buf);
|
ImVec2(cardMax.x - btcW - pad, cy + (sub1->LegacySize - capFont->LegacySize)),
|
||||||
|
OnSurfaceMedium(), buf);
|
||||||
} else {
|
} else {
|
||||||
dl->AddText(sub1, sub1->LegacySize, ImVec2(cx, cy), OnSurfaceDisabled(), TR("market_no_price"));
|
dl->AddText(sub1, sub1->LegacySize, ImVec2(cx, cy), OnSurfaceDisabled(), TR("market_no_price"));
|
||||||
}
|
}
|
||||||
|
cy += sub1->LegacySize + Layout::spacingSm();
|
||||||
|
|
||||||
cy += sub1->LegacySize + 8;
|
// DRGX balance + Z/T breakdown (right-aligned).
|
||||||
|
|
||||||
snprintf(buf, sizeof(buf), "%.8f %s", total_balance, DRAGONX_TICKER);
|
snprintf(buf, sizeof(buf), "%.8f %s", total_balance, DRAGONX_TICKER);
|
||||||
dl->AddText(body2, body2->LegacySize, ImVec2(cx, cy), OnSurface(), buf);
|
dl->AddText(body2, body2->LegacySize, ImVec2(cx, cy), OnSurface(), buf);
|
||||||
|
snprintf(buf, sizeof(buf), "Z %.4f \xC2\xB7 T %.4f", private_balance, transparent_balance);
|
||||||
snprintf(buf, sizeof(buf), "Z: %.4f | T: %.4f", private_balance, transparent_balance);
|
|
||||||
float brkW = capFont->CalcTextSizeA(capFont->LegacySize, FLT_MAX, 0, buf).x;
|
float brkW = capFont->CalcTextSizeA(capFont->LegacySize, FLT_MAX, 0, buf).x;
|
||||||
dl->AddText(capFont, capFont->LegacySize,
|
dl->AddText(capFont, capFont->LegacySize,
|
||||||
ImVec2(cardMax.x - brkW - pad, cy + 2), OnSurfaceDisabled(), buf);
|
ImVec2(cardMax.x - brkW - pad, cy + 2), OnSurfaceDisabled(), buf);
|
||||||
|
cy += body2->LegacySize + Layout::spacingSm();
|
||||||
|
|
||||||
cy += body2->LegacySize + 8;
|
// Full-width shielded/transparent ratio bar + % label.
|
||||||
|
|
||||||
if (total_balance > 0) {
|
if (total_balance > 0) {
|
||||||
float barW = availWidth - Layout::spacingXxl() * 1.5f;
|
float barW = pfInnerW;
|
||||||
float barH = std::max(S.drawElement("tabs.market", "ratio-bar-min-height").size, S.drawElement("tabs.market", "ratio-bar-height").size * vs);
|
|
||||||
float shieldedRatio = (float)(private_balance / total_balance);
|
float shieldedRatio = (float)(private_balance / total_balance);
|
||||||
if (shieldedRatio > 1.0f) shieldedRatio = 1.0f;
|
if (shieldedRatio > 1.0f) shieldedRatio = 1.0f;
|
||||||
if (shieldedRatio < 0.0f) shieldedRatio = 0.0f;
|
if (shieldedRatio < 0.0f) shieldedRatio = 0.0f;
|
||||||
float shieldedW = barW * shieldedRatio;
|
float shieldedW = barW * shieldedRatio;
|
||||||
float transpW = barW - shieldedW;
|
float transpW = barW - shieldedW;
|
||||||
|
|
||||||
ImVec2 barStart(cx, cy);
|
ImVec2 barStart(cx, cy);
|
||||||
|
|
||||||
dl->AddRectFilled(barStart, ImVec2(barStart.x + barW, barStart.y + barH),
|
dl->AddRectFilled(barStart, ImVec2(barStart.x + barW, barStart.y + ratioBarH),
|
||||||
IM_COL32(255, 255, 255, 10), 3.0f);
|
IM_COL32(255, 255, 255, 10), 3.0f);
|
||||||
if (shieldedW > 0.5f)
|
if (shieldedW > 0.5f)
|
||||||
dl->AddRectFilled(barStart, ImVec2(barStart.x + shieldedW, barStart.y + barH),
|
dl->AddRectFilled(barStart, ImVec2(barStart.x + shieldedW, barStart.y + ratioBarH),
|
||||||
WithAlpha(Success(), 200),
|
WithAlpha(Success(), 200),
|
||||||
transpW > 0.5f ? ImDrawFlags_RoundCornersLeft : ImDrawFlags_RoundCornersAll, 3.0f);
|
transpW > 0.5f ? ImDrawFlags_RoundCornersLeft : ImDrawFlags_RoundCornersAll, 3.0f);
|
||||||
if (transpW > 0.5f)
|
if (transpW > 0.5f)
|
||||||
dl->AddRectFilled(ImVec2(barStart.x + shieldedW, barStart.y),
|
dl->AddRectFilled(ImVec2(barStart.x + shieldedW, barStart.y),
|
||||||
ImVec2(barStart.x + barW, barStart.y + barH),
|
ImVec2(barStart.x + barW, barStart.y + ratioBarH),
|
||||||
WithAlpha(Warning(), 200),
|
WithAlpha(Warning(), 200),
|
||||||
shieldedW > 0.5f ? ImDrawFlags_RoundCornersRight : ImDrawFlags_RoundCornersAll, 3.0f);
|
shieldedW > 0.5f ? ImDrawFlags_RoundCornersRight : ImDrawFlags_RoundCornersAll, 3.0f);
|
||||||
|
|
||||||
// market_pct_shielded is "%.0f%% Shielded" — pass a double, not an int (passing
|
// market_pct_shielded is "%.0f%% Shielded" — pass a double (an int to %f is UB).
|
||||||
// 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);
|
||||||
snprintf(buf, sizeof(buf), TR("market_pct_shielded"),
|
|
||||||
static_cast<double>(shieldedRatio) * 100.0);
|
|
||||||
dl->AddText(capFont, capFont->LegacySize,
|
dl->AddText(capFont, capFont->LegacySize,
|
||||||
ImVec2(cx, cy + barH + 2), OnSurfaceDisabled(), buf);
|
ImVec2(cx, cy + ratioBarH + Layout::spacingXs()), OnSurfaceDisabled(), buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---- CUSTOM PORTFOLIO ENTRIES (below the all-funds summary) ----
|
// ---- CUSTOM GROUPS — one glass card per entry, wrapping into a grid ----
|
||||||
if (!pfEntries.empty()) {
|
if (pfN > 0) {
|
||||||
float ey = cardMin.y + baseH - Layout::spacingSm();
|
float gy = cardMin.y + pfSummaryH;
|
||||||
dl->AddLine(ImVec2(cardMin.x + glassSpec.rounding * 0.5f, ey),
|
dl->AddText(ovFont, ovFont->LegacySize, ImVec2(cx, gy), OnSurfaceMedium(), TR("portfolio_groups"));
|
||||||
ImVec2(cardMax.x - glassSpec.rounding * 0.5f, ey), WithAlpha(OnSurface(), 20), 1.0f);
|
gy += ovFont->LegacySize + Layout::spacingSm();
|
||||||
ey += Layout::spacingSm();
|
|
||||||
for (const auto& e : pfEntries) {
|
for (int i = 0; i < pfN; i++) {
|
||||||
|
const auto& e = pfEntriesGeo[i];
|
||||||
|
int col = i % pfCardsPerRow;
|
||||||
|
int row = i / pfCardsPerRow;
|
||||||
|
ImVec2 gcMin(cx + col * (pfCardW + pfCardGap), gy + row * (pfCardH + pfCardGap));
|
||||||
|
ImVec2 gcMax(gcMin.x + pfCardW, gcMin.y + pfCardH);
|
||||||
|
|
||||||
|
GlassPanelSpec gcGlass;
|
||||||
|
gcGlass.rounding = 8.0f;
|
||||||
|
gcGlass.fillAlpha = 18;
|
||||||
|
gcGlass.borderAlpha = 30;
|
||||||
|
DrawGlassPanel(dl, gcMin, gcMax, gcGlass);
|
||||||
|
|
||||||
double bal = data::SumPortfolioBalance(e.addresses, state.addresses);
|
double bal = data::SumPortfolioBalance(e.addresses, state.addresses);
|
||||||
dl->AddText(body2, body2->LegacySize, ImVec2(cx, ey), OnSurface(), e.label.c_str());
|
float tcx = gcMin.x + Layout::spacingSm();
|
||||||
char amt[96];
|
float tcy = gcMin.y + Layout::spacingSm();
|
||||||
if (market.price_usd > 0)
|
float maxTextW = pfCardW - Layout::spacingSm() * 2.0f;
|
||||||
snprintf(amt, sizeof(amt), "%.4f %s ($%.2f)", bal, DRAGONX_TICKER, bal * market.price_usd);
|
|
||||||
else
|
// Label (truncated with an ellipsis to the card width).
|
||||||
snprintf(amt, sizeof(amt), "%.4f %s", bal, DRAGONX_TICKER);
|
std::string label = e.label;
|
||||||
float amtW = capFont->CalcTextSizeA(capFont->LegacySize, FLT_MAX, 0, amt).x;
|
bool truncated = false;
|
||||||
dl->AddText(capFont, capFont->LegacySize,
|
while (label.size() > 1 &&
|
||||||
ImVec2(cardMax.x - amtW - pad, ey + 1), OnSurfaceMedium(), amt);
|
body2->CalcTextSizeA(body2->LegacySize, FLT_MAX, 0, label.c_str()).x > maxTextW) {
|
||||||
ey += entryRowH;
|
label.pop_back();
|
||||||
|
truncated = true;
|
||||||
|
}
|
||||||
|
if (truncated) label += "\xE2\x80\xA6";
|
||||||
|
dl->AddText(body2, body2->LegacySize, ImVec2(tcx, tcy), OnSurfaceMedium(), label.c_str());
|
||||||
|
tcy += body2->LegacySize + Layout::spacingXs();
|
||||||
|
|
||||||
|
// DRGX amount.
|
||||||
|
snprintf(buf, sizeof(buf), "%.4f %s", bal, DRAGONX_TICKER);
|
||||||
|
dl->AddText(body2, body2->LegacySize, ImVec2(tcx, tcy), OnSurface(), buf);
|
||||||
|
tcy += body2->LegacySize;
|
||||||
|
|
||||||
|
// Fiat value.
|
||||||
|
if (market.price_usd > 0) {
|
||||||
|
snprintf(buf, sizeof(buf), "$%.2f", bal * market.price_usd);
|
||||||
|
dl->AddText(capFont, capFont->LegacySize, ImVec2(tcx, tcy), OnSurfaceDisabled(), buf);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1119,6 +1119,7 @@ void I18n::loadBuiltinEnglish()
|
|||||||
strings_["market_pct_shielded"] = "%.0f%% Shielded";
|
strings_["market_pct_shielded"] = "%.0f%% Shielded";
|
||||||
strings_["market_portfolio"] = "MY DRGX";
|
strings_["market_portfolio"] = "MY DRGX";
|
||||||
strings_["portfolio_all_funds"] = "All funds";
|
strings_["portfolio_all_funds"] = "All funds";
|
||||||
|
strings_["portfolio_groups"] = "GROUPS";
|
||||||
strings_["portfolio_manage"] = "Manage\xE2\x80\xA6";
|
strings_["portfolio_manage"] = "Manage\xE2\x80\xA6";
|
||||||
strings_["portfolio_manage_title"] = "Manage portfolio";
|
strings_["portfolio_manage_title"] = "Manage portfolio";
|
||||||
strings_["portfolio_add_entry"] = "Add entry";
|
strings_["portfolio_add_entry"] = "Add entry";
|
||||||
|
|||||||
Reference in New Issue
Block a user