fix(ui): prevent text/button cutoff and scale hand-drawn geometry at HiDPI

Findings from a UI-cutoff audit — each is a spot where an in-tree helper
(truncateMiddle / TruncateToWidth / measured button width / the *dpiScale/*hs
factors) was bypassed:

- notifications: the toast-pill height/padding/icon-gap were raw logical px while
  the icon/text drawn inside are DPI-baked, so they clipped the pill at HiDPI.
  Scale the geometry by dpiScale (not the already-scaled glyph metrics).
- settings: in the two-column NODE & SECURITY layout the data-directory path could
  overrun into the Daemon-binary column (shared draw list, no clip rect between
  them). Middle-ellipsize it to the column width; the full path stays in the
  tooltip + click-to-open + copy.
- send: the "Confirm & Send" button width came straight from the schema and was
  never measured against the label, clipping the Russian translation on the
  pre-broadcast dialog. Size to max(schema width, measured label + padding).
- balance: the recent-tx address-column offset missed the `* hs` DPI factor its
  sibling (amount-right-margin) uses, overlapping the type label at HiDPI.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-10 22:11:07 -05:00
co-authored by Claude Opus 4.8
parent 393f3d147e
commit 001e85ac1a
4 changed files with 35 additions and 12 deletions
+12 -2
View File
@@ -2081,12 +2081,22 @@ void RenderSettingsPage(App* app) {
ImGui::SameLine(0, 0);
ImGui::SetCursorPosX(leftX + labelW);
ImGui::AlignTextToFramePadding();
ImGui::TextColored(ImGui::ColorConvertU32ToFloat4(Primary()), "%s", dirPath.c_str());
// In the two-column layout this shares one draw list with the Daemon-binary
// column (no clip rect between them), so a long OS data-dir path (Windows
// AppData / macOS Application Support) would overrun into it. Middle-ellipsize
// to the remaining column width (room left for the copy button); the full path
// stays available via the tooltip, click-to-open, and the copy button.
ImFont* pathFont = ImGui::GetFont();
const float pathAvailW = contentW - labelW - Layout::spacingSm()
- ImGui::GetFrameHeight() - Layout::spacingXs();
const std::string dirShown =
material::TruncateToWidth(dirPath, pathFont, pathFont->LegacySize, pathAvailW);
ImGui::TextColored(ImGui::ColorConvertU32ToFloat4(Primary()), "%s", dirShown.c_str());
if (ImGui::IsItemHovered()) {
const ImVec2 tmn = ImGui::GetItemRectMin(), tmx = ImGui::GetItemRectMax();
dl->AddLine(ImVec2(tmn.x, tmx.y), ImVec2(tmx.x, tmx.y), Primary());
ImGui::SetMouseCursor(ImGuiMouseCursor_Hand);
material::Tooltip("%s", TR("tt_open_dir"));
material::Tooltip("%s\n%s", dirPath.c_str(), TR("tt_open_dir"));
}
if (ImGui::IsItemClicked()) util::Platform::openFolder(dirPath);
ImGui::SameLine(0, Layout::spacingSm());