fix(ui): finish HiDPI pass — cosmetic ×dpiScale, narrow-width reflow, recent-list reserves

The tail of the DPI/font-scale/responsiveness audit — ~26 remaining findings.

Container / recent-list (Theme-1 leftovers):
- Send: drop NoScrollbar|NoScrollWithMouse on ##SendFormScroll so Recent Sends is
  reachable at font_scale 1.5 (parity with receive).
- Receive: cap the QR/form card via std::min(mainCardTargetH, availH - recentReserve)
  so RECENT RECEIVED stays on-screen (identity at 1.0x).
- Wallets dialog: size the capped-mode list to whole rows so it no longer clips a
  partial row / crowds "Create a new wallet".

Narrow-width (1024px) reflow:
- Console toolbar reserves space for ALL trailing controls (both icon toggles + zoom
  buttons) so the +/- zoom no longer runs off-window.
- History sort combo sized to its measured widest localized label ("Newest first").
- Settings Theme/Layout/Language row: scale the wide→stacked breakpoint by dpiScale so
  it drops to full-width stacked combos at 1.5x (Consolidated Card no longer clips).
- Recent-tx type label: derive the address column X from the measured label width so it
  can't collide at narrow widths.
- Mining Recent Pool Payouts: floor the panel height to fit the empty-state caption.

Cosmetic ×dpiScale() on absolute geometry (no-ops at 1.0x): mining SOLO|POOL toggle &
idle combos, market pair-chips, password/PIN strength bars, receive/send currency
toggles, explorer search bar/rows/rounding, About-card logo, chat empty-state wrap,
recent-list address/time offsets, address-toolbar & two-row action buttons, console
line-gap/status-dot/pane rounding.

Verified at font_scale 1.5 and at 1024px across full-node + Lite + Windows (ctest
green) and an adversarial diff review (one over-reserve regression fixed).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-18 21:29:10 -05:00
co-authored by Claude Opus 4.8
parent 99d1e73676
commit ce8c7696d4
15 changed files with 118 additions and 54 deletions
+10 -6
View File
@@ -1154,7 +1154,7 @@ static void RenderRecentSends(const WalletState& state, float width, ImFont* cap
ImVec2(txX, rowPos.y + 2.0f * dp), OnSurfaceMedium(), TR("sent_type"));
// Address (second line)
float addrX = txX + S.drawElement("tabs.balance", "recent-tx-addr-offset").sizeOr(65.0f);
float addrX = txX + S.drawElement("tabs.balance", "recent-tx-addr-offset").sizeOr(65.0f) * hs;
std::string addrDisplay = util::truncateMiddle(tx.address,
(int)S.drawElement("tabs.balance", "recent-tx-addr-trunc").sizeOr(20.0f));
rowDL->AddText(capFont, capFont->LegacySize,
@@ -1173,7 +1173,7 @@ static void RenderRecentSends(const WalletState& state, float width, ImFont* cap
std::string ago = timeAgo(tx.timestamp);
ImVec2 agoSz = capFont->CalcTextSizeA(capFont->LegacySize, 10000.0f, 0.0f, ago.c_str());
rowDL->AddText(capFont, capFont->LegacySize,
ImVec2(rightEdge - agoSz.x - S.drawElement("tabs.balance", "recent-tx-time-margin").sizeOr(4.0f),
ImVec2(rightEdge - agoSz.x - S.drawElement("tabs.balance", "recent-tx-time-margin").sizeOr(4.0f) * hs,
rowPos.y + 2.0f * dp),
OnSurfaceDisabled(), ago.c_str());
@@ -1251,8 +1251,12 @@ void RenderSendTab(App* app)
// SCROLLABLE CONTENT
// ================================================================
ImVec2 formAvail = ImGui::GetContentRegionAvail();
// NOTE: no NoScrollbar/NoScrollWithMouse here (mirrors receive_tab's ##ReceiveScroll).
// At font_scale 1.5 the form card grows to mainCardTargetH and pushes the appended
// "Recent Sends" list below the fold; letting this child scroll keeps it reachable.
// No-op at 1.0x where the content already fits (no scrollbar appears).
ImGui::BeginChild("##SendFormScroll", formAvail, false,
ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse);
ImGuiWindowFlags_NoBackground);
dl = ImGui::GetWindowDrawList();
// Top-aligned content — consistent vertical position across all tabs
@@ -1428,7 +1432,7 @@ void RenderSendTab(App* app)
ImGui::Dummy(ImVec2(0, Layout::spacingSm()));
// Toggle between DRGX and USD input
float toggleW = schema::UI().drawElement("tabs.send", "toggle-currency-width").size;
float toggleW = schema::UI().drawElement("tabs.send", "toggle-currency-width").size * Layout::dpiScale();
float amtInputW = colW - toggleW - Layout::spacingMd();
if (amtInputW < schema::UI().drawElement("tabs.send", "amount-input-min-width").size) amtInputW = schema::UI().drawElement("tabs.send", "amount-input-min-width").size;
@@ -1501,8 +1505,8 @@ void RenderSendTab(App* app)
float bH = bMax.y - bMin.y;
ImFont* font = ImGui::GetFont();
ImVec2 textSz = font->CalcTextSizeA(font->LegacySize, 10000, 0, currLabel);
float iconW = schema::UI().drawElement("tabs.send", "swap-icon-width").size;
float iconGap = schema::UI().drawElement("tabs.send", "swap-icon-gap").size;
float iconW = schema::UI().drawElement("tabs.send", "swap-icon-width").size * Layout::dpiScale();
float iconGap = schema::UI().drawElement("tabs.send", "swap-icon-gap").size * Layout::dpiScale();
float totalW = iconW + iconGap + textSz.x;
float startX = bMin.x + ((bMax.x - bMin.x) - totalW) * 0.5f;
float cy = bMin.y + bH * 0.5f;