fix(ui): console-commands modal slide + wallets footer clipping

Two follow-ups to the modal float work:

- Console RPC command reference (renderCommandsPopup) had the SAME auto-height
  feedback bug as Wallets: BlurFloat with no cardHeight, and its fill-height
  command list read GetContentRegionAvail() inside the AutoResizeY child ->
  self-referential, sliding content off-screen after a monitor move. Give it a
  FIXED viewport-relative cardHeight (fills ~84% of the viewport). Also removed
  its duplicate body H6 heading (the framework h6 title already shows it) —
  missed earlier because it's spec-form, not the positional overload.

- Wallets footer clipping: after the fixed-height conversion the content child
  clips overflow (NoScrollbar), and the hardcoded 130*dp reserve below the table
  was too small for the create/add-folder rows + separator + footer (~160*dp),
  so the buttons clipped — worse at 150%. Compute the reserve from real widget
  metrics (GetFrameHeightWithSpacing + caption height) so it holds at any DPI.

Added a modal-console-commands sweep surface (debug-gated ConsoleTab setter) so
the popup is captured. Verified both at 100% and font_scale 1.5 (150%): footers
on-screen, single headings, lists fill, nothing clipped.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-09 22:40:26 -05:00
parent d8cc1e9ee6
commit 13ff20d791
4 changed files with 22 additions and 6 deletions

View File

@@ -399,6 +399,11 @@ void App::buildSweepCatalog()
add("market-rows-featured", ui::NavPage::Market, add("market-rows-featured", ui::NavPage::Market,
[](App& a) { if (a.settings_) a.settings_->setPortfolioStyle(2); }, [](App& a) { if (a.settings_) a.settings_->setPortfolioStyle(2); },
[](App& a) { if (a.settings_) a.settings_->setPortfolioStyle(0); }); [](App& a) { if (a.settings_) a.settings_->setPortfolioStyle(0); });
// Console RPC command-reference popup (fixed-height dialog with a fill-height command list).
add("modal-console-commands", ui::NavPage::Console,
[](App& a) { a.console_tab_.sweepSetCommandsPopup(true); },
[](App& a) { a.console_tab_.sweepSetCommandsPopup(false); });
} }
// ── State machine ─────────────────────────────────────────────────────────────────────────── // ── State machine ───────────────────────────────────────────────────────────────────────────

View File

@@ -1391,13 +1391,15 @@ void ConsoleTab::renderCommandsPopup()
ov.title = TR("console_rpc_reference"); ov.p_open = &show_commands_popup_; ov.title = TR("console_rpc_reference"); ov.p_open = &show_commands_popup_;
ov.style = material::OverlayStyle::BlurFloat; // floating content on the blur, plain heading ov.style = material::OverlayStyle::BlurFloat; // floating content on the blur, plain heading
ov.cardWidth = popW; ov.cardBottomViewportRatio = 0.94f; // keep authored width ov.cardWidth = popW; ov.cardBottomViewportRatio = 0.94f; // keep authored width
// FIXED height (fills most of the viewport) instead of auto-height: the command list's
// fill-height child reads GetContentRegionAvail() inside the dialog child, which is only stable
// when the child is fixed-height. Auto-height made it self-referential and it slid content
// off-screen after a monitor move (same class of bug as the Wallets modal).
ov.cardHeight = ImGui::GetMainViewport()->Size.y * 0.84f / Layout::dpiScale();
if (!material::BeginOverlayDialog(ov)) { if (!material::BeginOverlayDialog(ov)) {
return; return;
} }
Type().text(TypeStyle::H6, TR("console_rpc_reference"));
ImGui::Dummy(ImVec2(0, Layout::spacingSm()));
// Search filter // Search filter
static char cmdFilter[128] = {0}; static char cmdFilter[128] = {0};
ImGui::SetNextItemWidth(-1); ImGui::SetNextItemWidth(-1);

View File

@@ -48,6 +48,10 @@ public:
*/ */
void renderCommandsPopupModal(); void renderCommandsPopupModal();
// Debug/UI-sweep hook: force the RPC command-reference popup open/closed so the full UI sweep
// can capture it (the popup is otherwise opened only by a toolbar button).
void sweepSetCommandsPopup(bool open) { show_commands_popup_ = open; }
/** /**
* @brief Add a line to the console output * @brief Add a line to the console output
*/ */

View File

@@ -69,8 +69,13 @@ public:
const std::string active = app->settings() ? app->settings()->getActiveWalletFile() : "wallet.dat"; const std::string active = app->settings() ? app->settings()->getActiveWalletFile() : "wallet.dat";
// Leave room below the table for the add-folder row + footer buttons. // Reserve room below the table for the create-wallet + add-folder rows (each a label +
float tableH = ImGui::GetContentRegionAvail().y - 130.0f * dp; // an input row), the separator, and the footer buttons — computed from real widget
// metrics so nothing clips at any DPI (a fixed px reserve was too small at 150%).
const float rowH = ImGui::GetFrameHeightWithSpacing();
const float lblH = Type().caption()->LegacySize + ImGui::GetStyle().ItemSpacing.y;
const float belowH = 3.0f * Layout::spacingSm() + 2.0f * lblH + 3.0f * rowH + Layout::spacingMd();
float tableH = ImGui::GetContentRegionAvail().y - belowH;
if (tableH < 120.0f * dp) tableH = 120.0f * dp; if (tableH < 120.0f * dp) tableH = 120.0f * dp;
const ImGuiTableFlags tflags = ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg | const ImGuiTableFlags tflags = ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg |