feat(ui): implement UI/UX audit — i18n, HiDPI, theme, destructive-action & overflow fixes
Implements all 26 confirmed UI/UX audit findings plus the 4 dashboard/timeline tile labels. Verified across full-node + Lite + Windows builds (ctest green) and an adversarial diff review (one market-tab delete regression caught + fixed). i18n coverage: - Balance hero/quick-actions/toasts + dashboard & timeline tiles (Total Balance, Shielded, Transparent, Quick Send, Quick Receive, Click to open, Market) - Send: Review Send / Cancel / Paste / view-only tooltip / memo byte counter - Settings: Lite lifecycle errors, plaintext-RPC security warning, 8 toasts - Mining pool-payout tooltip - Resolve daemon_update_title double-assignment collision (new daemon_update_prompt_title) - 23 new keys translated into all 8 locales; CJK subset font rebuilt HiDPI: DPI-scale the Send amount bar, mining thread-tile clamp bounds, receive loading skeleton, and sidebar notification-badge insets. Light theme: theme-aware material::SurfaceOverlay() for balance bar tracks and row-hover highlights; contacts active-pill foreground uses OnPrimary(). Destructive actions: arm/confirm for portfolio-group delete, saved pool/worker remove, and avatar-image delete. Interaction/overflow: route balance star/eye buttons and the console fold-toggle through popup-safe guards; clip peer addr/subver; truncate the balance custom label; measure Settings tool-button widths; mining stepper disabled-state feedback; +/- stepper buttons restyled to match the thread tiles. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -424,11 +424,13 @@ static void RenderAmountBar(ImDrawList* dl, double available, float innerW,
|
||||
? std::clamp((float)((s_amount + s_fee) / available), 0.0f, 1.0f)
|
||||
: 0.0f;
|
||||
|
||||
float maxBtnW = schema::UI().drawElement("tabs.send", "amount-bar-max-btn-width").size;
|
||||
const float dp = Layout::dpiScale();
|
||||
float maxBtnW = schema::UI().drawElement("tabs.send", "amount-bar-max-btn-width").size * dp;
|
||||
float gap = Layout::spacingMd();
|
||||
float barW = innerW - maxBtnW - gap;
|
||||
if (barW < schema::UI().drawElement("tabs.send", "progress-bar-min-width").size) barW = schema::UI().drawElement("tabs.send", "progress-bar-min-width").size;
|
||||
float barH = schema::UI().drawElement("tabs.send", "amount-bar-height").size;
|
||||
float minBarW = schema::UI().drawElement("tabs.send", "progress-bar-min-width").size * dp;
|
||||
if (barW < minBarW) barW = minBarW;
|
||||
float barH = schema::UI().drawElement("tabs.send", "amount-bar-height").size * dp;
|
||||
float barRound = barH * 0.5f;
|
||||
|
||||
ImVec2 barMin = ImGui::GetCursorScreenPos();
|
||||
@@ -1000,7 +1002,7 @@ static void RenderActionButtons(App* app, float width, float vScale,
|
||||
|
||||
ImGui::BeginDisabled(!can_send);
|
||||
char sendId[64];
|
||||
snprintf(sendId, sizeof(sendId), "Review Send%s", suffix);
|
||||
snprintf(sendId, sizeof(sendId), "%s##ReviewSend%s", TR("review_send"), suffix);
|
||||
if (TactileButton(sendId, ImVec2(sendBtnW, btnH), S.resolveFont(S.button("tabs.send", "send-button").font))) {
|
||||
s_show_confirm = true;
|
||||
}
|
||||
@@ -1020,7 +1022,7 @@ static void RenderActionButtons(App* app, float width, float vScale,
|
||||
else if (total > available)
|
||||
material::Tooltip("%s", TR("send_tooltip_exceeds_balance"));
|
||||
else if (!sourceSpendable)
|
||||
material::Tooltip("%s", "View-only address — no spending key, cannot send");
|
||||
material::Tooltip("%s", TR("send_tooltip_view_only"));
|
||||
else if (s_sending)
|
||||
material::Tooltip("%s", TR("send_tooltip_in_progress"));
|
||||
}
|
||||
@@ -1033,7 +1035,7 @@ static void RenderActionButtons(App* app, float width, float vScale,
|
||||
ImGui::PushStyleColor(ImGuiCol_Border, ImGui::ColorConvertU32ToFloat4(OnSurfaceDisabled()));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, S.drawElement("tabs.send", "cancel-btn-border-size").size);
|
||||
char clearId[64];
|
||||
snprintf(clearId, sizeof(clearId), "Cancel%s", suffix);
|
||||
snprintf(clearId, sizeof(clearId), "%s##Cancel%s", TR("cancel"), suffix);
|
||||
if (TactileButton(clearId, ImVec2(cancelBtnW, btnH), S.resolveFont(S.button("tabs.send", "clear-button").font))) {
|
||||
if (FormHasData()) {
|
||||
s_clear_confirm_pending = true;
|
||||
@@ -1377,7 +1379,7 @@ void RenderSendTab(App* app)
|
||||
s_preview_text.c_str(), s_preview_text.c_str() + std::min(s_preview_text.size(), (size_t)S.drawElement("tabs.send", "paste-preview-max-chars").size));
|
||||
}
|
||||
|
||||
if (TactileButton("Paste##to", ImVec2(pasteW, 0), S.resolveFont(S.button("tabs.send", "paste-button").font))) {
|
||||
if (TactileButton((std::string(TR("paste")) + "##to").c_str(), ImVec2(pasteW, 0), S.resolveFont(S.button("tabs.send", "paste-button").font))) {
|
||||
if (s_paste_previewing) {
|
||||
// Commit the preview
|
||||
snprintf(s_to_address, sizeof(s_to_address), "%s", s_preview_text.c_str());
|
||||
@@ -1547,7 +1549,7 @@ void RenderSendTab(App* app)
|
||||
size_t memo_len = strlen(s_memo);
|
||||
size_t memoMax = (size_t)S.drawElement("business", "memo-max-length").size;
|
||||
bool memoAtCap = memo_len + 1 >= memoMax;
|
||||
snprintf(buf, sizeof(buf), "%zu / %zu bytes", memo_len, memoMax);
|
||||
snprintf(buf, sizeof(buf), TR("byte_count_fmt"), memo_len, memoMax);
|
||||
Type().textColored(TypeStyle::Caption, memoAtCap ? Warning() : OnSurfaceDisabled(), buf);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user