feat(settings): daemon maintenance actions right-aligned on Test row; fix Open-folder overflow
- Remove the "Advanced" toggle. The four maintenance actions (Install bundled / Rescan / Delete blockchain / Repair wallet) now render right-aligned on the same row as Check-for-updates / Refresh / Test connection (wrapping to a right-aligned next row only when the window is too narrow). Predicates preserved. - Fix the Open-data-folder button overflowing the card's right edge (worse at high display scaling): its width was estimated with the CURRENT font, not the button font, so the estimate was wrong. Measure with the button font and give the button an explicit width so its right edge lands exactly on the card edge regardless of DPI/font-scale timing. - Drop the now-unused node_advanced_expanded flag. Full-node build clean; hygiene clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -144,7 +144,6 @@ struct SettingsPageState {
|
||||
std::set<std::string> debug_categories;
|
||||
bool debug_cats_dirty = false;
|
||||
bool debug_expanded = false;
|
||||
bool node_advanced_expanded = true; // Node & Security: rare/destructive daemon actions (shown by default)
|
||||
bool effects_expanded = false;
|
||||
bool tools_expanded = false;
|
||||
bool confirm_clear_ztx = false;
|
||||
@@ -2024,8 +2023,12 @@ void RenderSettingsPage(App* app) {
|
||||
// gets whatever width is left after the data-dir label, wallet-size
|
||||
// label+value, and the trailing button.
|
||||
ImFont* nodeBtnFont = S.resolveFont("button");
|
||||
float openBtnW = ImGui::CalcTextSize(TR("settings_open_data_dir")).x +
|
||||
ImGui::GetStyle().FramePadding.x * 2.0f + btnPad;
|
||||
if (!nodeBtnFont) nodeBtnFont = Type().button();
|
||||
// Measure with the BUTTON font (not the current font) so the width matches
|
||||
// the real TactileButton size — the old estimate mis-measured and the button
|
||||
// overflowed the card's right edge, worse at high DPI.
|
||||
float openBtnW = nodeBtnFont->CalcTextSizeA(nodeBtnFont->LegacySize, FLT_MAX, 0,
|
||||
TR("settings_open_data_dir")).x + ImGui::GetStyle().FramePadding.x * 2.0f;
|
||||
float dataDirLabelW = ImGui::CalcTextSize(TR("settings_data_dir")).x;
|
||||
float sizeLabelW = ImGui::CalcTextSize(TR("settings_wallet_size_label")).x;
|
||||
float sizeValueW = ImGui::CalcTextSize(size_str.c_str()).x;
|
||||
@@ -2084,18 +2087,17 @@ void RenderSettingsPage(App* app) {
|
||||
else
|
||||
ImGui::TextDisabled("%s", TR("settings_not_found"));
|
||||
|
||||
// Open-data-folder button: right-aligned when there is room, else trailing —
|
||||
// kept on the data-dir row (rowTopY), not the next line.
|
||||
// Open-data-folder button: right-aligned on the data-dir row (rowTopY), with
|
||||
// an EXPLICIT width (openBtnW) so its right edge lands exactly on the card
|
||||
// edge and never overflows, regardless of DPI / font-scale timing.
|
||||
float rowY = rowTopY;
|
||||
float rightEdge = sectionOrigin.x + contentW;
|
||||
float actualOpenW = ImGui::CalcTextSize(TR("settings_open_data_dir")).x +
|
||||
ImGui::GetStyle().FramePadding.x * 2.0f;
|
||||
float openX = rightEdge - actualOpenW;
|
||||
float openX = rightEdge - openBtnW;
|
||||
float afterSizeX = ImGui::GetItemRectMax().x + spMd;
|
||||
ImGui::SameLine(0, spMd);
|
||||
if (openX > afterSizeX)
|
||||
ImGui::SetCursorScreenPos(ImVec2(openX, rowY));
|
||||
if (TactileButton(TR("settings_open_data_dir"), ImVec2(0, 0), nodeBtnFont)) {
|
||||
if (TactileButton(TR("settings_open_data_dir"), ImVec2(openBtnW, 0), nodeBtnFont)) {
|
||||
util::Platform::openFolder(dirPath);
|
||||
}
|
||||
if (ImGui::IsItemHovered()) material::Tooltip("%s", TR("tt_open_data_dir"));
|
||||
@@ -2250,8 +2252,10 @@ void RenderSettingsPage(App* app) {
|
||||
if (ui::DaemonUpdateDialog::consumeInstalled())
|
||||
s_settingsState.daemon_info_loaded = false;
|
||||
|
||||
// Common action row: Check for updates | Refresh | Test connection.
|
||||
// Action row: Check for updates | Refresh | Test connection on the left,
|
||||
// with the four maintenance actions right-aligned on the same row.
|
||||
ImGui::Dummy(ImVec2(0, Layout::spacingXs()));
|
||||
float daemonBtnRowY = ImGui::GetCursorScreenPos().y;
|
||||
if (TactileButton(TR("daemon_update_check"), ImVec2(0, 0), dbBtnFont)) {
|
||||
ui::DaemonUpdateDialog::show(app, inst.exists ? inst.version : std::string());
|
||||
}
|
||||
@@ -2281,10 +2285,11 @@ void RenderSettingsPage(App* app) {
|
||||
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) material::Tooltip("%s", TR("tt_test_conn"));
|
||||
ImGui::EndDisabled();
|
||||
|
||||
// The FOUR destructive maintenance actions, in one horizontal row prefixed
|
||||
// by a visible "Advanced" toggle. Every BeginDisabled/EndDisabled predicate
|
||||
// is preserved exactly.
|
||||
auto renderDaemonAdvancedButtons = [&]() {
|
||||
// The four maintenance actions (Install bundled / Rescan / Delete blockchain
|
||||
// / Repair wallet), right-aligned on the SAME row as Test connection — no
|
||||
// separate "Advanced" toggle. Every BeginDisabled/EndDisabled predicate is
|
||||
// preserved exactly. Wraps to a right-aligned next row when too narrow.
|
||||
auto renderDaemonMaintenanceButtons = [&]() {
|
||||
ImGui::BeginDisabled(!app->isUsingEmbeddedDaemon() || !bun.available);
|
||||
if (TactileButton(TR("daemon_install_bundled"), ImVec2(0, 0), dbBtnFont)) {
|
||||
s_settingsState.confirm_reinstall_daemon = true;
|
||||
@@ -2314,40 +2319,28 @@ void RenderSettingsPage(App* app) {
|
||||
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) material::Tooltip("%s", TR("tt_repair_wallet"));
|
||||
ImGui::EndDisabled();
|
||||
};
|
||||
|
||||
// Advanced — a clearly-clickable toggle (label + arrow) on its own line,
|
||||
// controlling the rare + destructive daemon maintenance actions. When
|
||||
// expanded the four buttons render on one horizontal row: inline with the
|
||||
// toggle when there is room, otherwise wrapped to the next full-width row.
|
||||
ImGui::Dummy(ImVec2(0, Layout::spacingSm()));
|
||||
{
|
||||
char advBuf[64];
|
||||
const char* advArrow = s_settingsState.node_advanced_expanded
|
||||
? ICON_MD_EXPAND_LESS : ICON_MD_EXPAND_MORE;
|
||||
snprintf(advBuf, sizeof(advBuf), "%s %s##NodeAdvancedToggle",
|
||||
TR("advanced"), advArrow);
|
||||
// Width of the four Advanced buttons + gaps, to decide inline vs. wrap.
|
||||
float advBtnsW = spMd * 3;
|
||||
const char* advLabels[] = { TR("daemon_install_bundled"), TR("rescan"),
|
||||
TR("delete_blockchain"), TR("repair_wallet") };
|
||||
for (const char* l : advLabels)
|
||||
advBtnsW += ImGui::CalcTextSize(l).x + ImGui::GetStyle().FramePadding.x * 2.0f;
|
||||
float advToggleW = ImGui::CalcTextSize(advBuf).x +
|
||||
ImGui::GetStyle().FramePadding.x * 2.0f;
|
||||
|
||||
if (TactileButton(advBuf, ImVec2(0, 0), dbBtnFont)) {
|
||||
s_settingsState.node_advanced_expanded = !s_settingsState.node_advanced_expanded;
|
||||
}
|
||||
if (s_settingsState.node_advanced_expanded) {
|
||||
const bool inline_ = (advToggleW + spMd + advBtnsW) <= contentW;
|
||||
if (inline_) {
|
||||
ImGui::SameLine(0, spMd);
|
||||
} else {
|
||||
ImGui::Dummy(ImVec2(0, Layout::spacingXs()));
|
||||
ImGui::SetCursorScreenPos(ImVec2(sectionOrigin.x, ImGui::GetCursorScreenPos().y));
|
||||
}
|
||||
renderDaemonAdvancedButtons();
|
||||
// Group width (button font) to right-align the four maintenance actions.
|
||||
const char* mLabels[] = { TR("daemon_install_bundled"), TR("rescan"),
|
||||
TR("delete_blockchain"), TR("repair_wallet") };
|
||||
float groupW = spMd * 3.0f;
|
||||
for (const char* l : mLabels)
|
||||
groupW += dbBtnFont->CalcTextSizeA(dbBtnFont->LegacySize, FLT_MAX, 0, l).x
|
||||
+ ImGui::GetStyle().FramePadding.x * 2.0f;
|
||||
float afterTestX = ImGui::GetItemRectMax().x + spMd; // right edge of Test connection
|
||||
float rightEdge = sectionOrigin.x + contentW;
|
||||
float groupX = rightEdge - groupW;
|
||||
if (groupX >= afterTestX) {
|
||||
// Fits on the Test-connection row, right-aligned.
|
||||
ImGui::SameLine(0, 0);
|
||||
ImGui::SetCursorScreenPos(ImVec2(groupX, daemonBtnRowY));
|
||||
} else {
|
||||
// Too narrow: wrap to the next row, right-aligned (clamped to left edge).
|
||||
ImGui::Dummy(ImVec2(0, Layout::spacingXs()));
|
||||
float wrapX = std::max(sectionOrigin.x, rightEdge - groupW);
|
||||
ImGui::SetCursorScreenPos(ImVec2(wrapX, ImGui::GetCursorScreenPos().y));
|
||||
}
|
||||
renderDaemonMaintenanceButtons();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user