fix(ui): tidy Node maintenance layout + widen the Daemon binary panel
- Delete Blockchain and Repair Wallet now sit on one line, paired with the same uniform button width as Test Connection / Rescan Blockchain (a clean 2-column grid; all maintenance buttons share one rowBtnW sized across the four labels). - The Daemon binary panel lays Installed and Bundled side by side across the node column (version + size·date | version + size) instead of stacked narrow lines, with the status line spanning underneath and Install bundled / Refresh paired below. - Shorten the install button label to "Install bundled" so it fits the shared width; the tooltip still explains the full action. Date shown as YYYY-MM-DD. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -2012,7 +2012,8 @@ void RenderSettingsPage(App* app) {
|
|||||||
float nodeBtnW;
|
float nodeBtnW;
|
||||||
{
|
{
|
||||||
if (btnFont) ImGui::PushFont(btnFont);
|
if (btnFont) ImGui::PushFont(btnFont);
|
||||||
nodeBtnW = rowBtnW({TR("test_connection"), TR("rescan")});
|
nodeBtnW = rowBtnW({TR("test_connection"), TR("rescan"),
|
||||||
|
TR("delete_blockchain"), TR("repair_wallet")});
|
||||||
if (btnFont) ImGui::PopFont(/* btnFont */);
|
if (btnFont) ImGui::PopFont(/* btnFont */);
|
||||||
}
|
}
|
||||||
ImGui::SetCursorScreenPos(ImVec2(leftX, ImGui::GetCursorScreenPos().y));
|
ImGui::SetCursorScreenPos(ImVec2(leftX, ImGui::GetCursorScreenPos().y));
|
||||||
@@ -2045,20 +2046,16 @@ void RenderSettingsPage(App* app) {
|
|||||||
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) ImGui::SetTooltip("%s", TR("tt_rescan"));
|
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) ImGui::SetTooltip("%s", TR("tt_rescan"));
|
||||||
ImGui::EndDisabled();
|
ImGui::EndDisabled();
|
||||||
|
|
||||||
// Delete blockchain button (always available when using embedded daemon)
|
// Row 2: Delete blockchain | Repair wallet (embedded daemon only) — paired on
|
||||||
|
// one line with the same width/style as the Test connection | Rescan row above.
|
||||||
ImGui::SetCursorScreenPos(ImVec2(leftX, ImGui::GetCursorScreenPos().y + Layout::spacingSm()));
|
ImGui::SetCursorScreenPos(ImVec2(leftX, ImGui::GetCursorScreenPos().y + Layout::spacingSm()));
|
||||||
ImGui::BeginDisabled(!app->isUsingEmbeddedDaemon());
|
ImGui::BeginDisabled(!app->isUsingEmbeddedDaemon());
|
||||||
if (TactileButton(TR("delete_blockchain"), ImVec2(0, 0), btnFont)) {
|
if (TactileButton(TR("delete_blockchain"), ImVec2(nodeBtnW, 0), btnFont)) {
|
||||||
s_settingsState.confirm_delete_blockchain = true;
|
s_settingsState.confirm_delete_blockchain = true;
|
||||||
}
|
}
|
||||||
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) ImGui::SetTooltip("%s", TR("tt_delete_blockchain"));
|
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) ImGui::SetTooltip("%s", TR("tt_delete_blockchain"));
|
||||||
ImGui::EndDisabled();
|
ImGui::SameLine(0, Layout::spacingMd());
|
||||||
|
if (TactileButton(TR("repair_wallet"), ImVec2(nodeBtnW, 0), btnFont)) {
|
||||||
// Repair wallet (-zapwallettxes=2): wipe & rebuild wallet tx/note records from
|
|
||||||
// the chain (keys kept). Fixes notes that fail to spend after a rescan.
|
|
||||||
ImGui::SetCursorScreenPos(ImVec2(leftX, ImGui::GetCursorScreenPos().y + Layout::spacingSm()));
|
|
||||||
ImGui::BeginDisabled(!app->isUsingEmbeddedDaemon());
|
|
||||||
if (TactileButton(TR("repair_wallet"), ImVec2(0, 0), btnFont)) {
|
|
||||||
s_settingsState.confirm_repair_wallet = true;
|
s_settingsState.confirm_repair_wallet = true;
|
||||||
}
|
}
|
||||||
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) ImGui::SetTooltip("%s", TR("tt_repair_wallet"));
|
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) ImGui::SetTooltip("%s", TR("tt_repair_wallet"));
|
||||||
@@ -2086,7 +2083,7 @@ void RenderSettingsPage(App* app) {
|
|||||||
localtime_r(&t, &tmv);
|
localtime_r(&t, &tmv);
|
||||||
#endif
|
#endif
|
||||||
char buf[32];
|
char buf[32];
|
||||||
std::strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M", &tmv);
|
std::strftime(buf, sizeof(buf), "%Y-%m-%d", &tmv);
|
||||||
return std::string(buf);
|
return std::string(buf);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -2094,25 +2091,40 @@ void RenderSettingsPage(App* app) {
|
|||||||
Type().textColored(TypeStyle::Overline, OnSurfaceMedium(), TR("daemon_binary"));
|
Type().textColored(TypeStyle::Overline, OnSurfaceMedium(), TR("daemon_binary"));
|
||||||
ImGui::Dummy(ImVec2(0, Layout::spacingXs()));
|
ImGui::Dummy(ImVec2(0, Layout::spacingXs()));
|
||||||
|
|
||||||
|
// Installed | Bundled side by side, spanning the node column's width.
|
||||||
|
const float dbStartY = ImGui::GetCursorScreenPos().y;
|
||||||
|
const float dbLineH = ImGui::GetTextLineHeightWithSpacing();
|
||||||
|
const float dbCol2X = leftX + leftColW * 0.5f;
|
||||||
|
const ImVec4 dbDim = ImGui::ColorConvertU32ToFloat4(OnSurfaceMedium());
|
||||||
|
|
||||||
|
// Column 1 — Installed (version, then size · date)
|
||||||
|
ImGui::SetCursorScreenPos(ImVec2(leftX, dbStartY));
|
||||||
|
Type().textColored(TypeStyle::Overline, OnSurfaceMedium(), TR("daemon_installed"));
|
||||||
|
ImGui::SetCursorScreenPos(ImVec2(leftX, dbStartY + dbLineH));
|
||||||
if (inst.exists) {
|
if (inst.exists) {
|
||||||
ImGui::Text("%s %s", TR("daemon_installed"),
|
ImGui::TextUnformatted(inst.version.empty() ? TR("unknown") : inst.version.c_str());
|
||||||
inst.version.empty() ? TR("unknown") : inst.version.c_str());
|
ImGui::SetCursorScreenPos(ImVec2(leftX, dbStartY + dbLineH * 2));
|
||||||
ImGui::TextColored(ImGui::ColorConvertU32ToFloat4(OnSurfaceMedium()), " %s · %s",
|
ImGui::TextColored(dbDim, "%s · %s",
|
||||||
util::Platform::formatFileSize(inst.size).c_str(),
|
util::Platform::formatFileSize(inst.size).c_str(),
|
||||||
fmtDate(inst.modifiedEpoch).c_str());
|
fmtDate(inst.modifiedEpoch).c_str());
|
||||||
} else {
|
} else {
|
||||||
ImGui::Text("%s %s", TR("daemon_installed"), TR("daemon_not_installed"));
|
ImGui::TextColored(dbDim, "%s", TR("daemon_not_installed"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Column 2 — Bundled (version, then size)
|
||||||
|
ImGui::SetCursorScreenPos(ImVec2(dbCol2X, dbStartY));
|
||||||
|
Type().textColored(TypeStyle::Overline, OnSurfaceMedium(), TR("daemon_bundled"));
|
||||||
|
ImGui::SetCursorScreenPos(ImVec2(dbCol2X, dbStartY + dbLineH));
|
||||||
if (bun.available) {
|
if (bun.available) {
|
||||||
ImGui::Text("%s %s", TR("daemon_bundled"),
|
ImGui::TextUnformatted(bun.version.empty() ? TR("unknown") : bun.version.c_str());
|
||||||
bun.version.empty() ? TR("unknown") : bun.version.c_str());
|
ImGui::SetCursorScreenPos(ImVec2(dbCol2X, dbStartY + dbLineH * 2));
|
||||||
ImGui::TextColored(ImGui::ColorConvertU32ToFloat4(OnSurfaceMedium()), " %s",
|
ImGui::TextColored(dbDim, "%s", util::Platform::formatFileSize(bun.size).c_str());
|
||||||
util::Platform::formatFileSize(bun.size).c_str());
|
|
||||||
} else {
|
} else {
|
||||||
ImGui::Text("%s %s", TR("daemon_bundled"), TR("daemon_none_bundled"));
|
ImGui::TextColored(dbDim, "%s", TR("daemon_none_bundled"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Status line, below both sub-columns, spanning the node column.
|
||||||
|
ImGui::SetCursorScreenPos(ImVec2(leftX, dbStartY + dbLineH * 3 + Layout::spacingXs()));
|
||||||
if (bun.available) {
|
if (bun.available) {
|
||||||
const bool sameSize = inst.exists && inst.size == bun.size;
|
const bool sameSize = inst.exists && inst.size == bun.size;
|
||||||
if (!inst.exists)
|
if (!inst.exists)
|
||||||
@@ -2124,15 +2136,16 @@ void RenderSettingsPage(App* app) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ImGui::Dummy(ImVec2(0, Layout::spacingXs()));
|
ImGui::Dummy(ImVec2(0, Layout::spacingXs()));
|
||||||
|
// Install bundled daemon | Refresh — paired, same width/style as the rows above.
|
||||||
ImGui::SetCursorScreenPos(ImVec2(leftX, ImGui::GetCursorScreenPos().y));
|
ImGui::SetCursorScreenPos(ImVec2(leftX, ImGui::GetCursorScreenPos().y));
|
||||||
ImGui::BeginDisabled(!app->isUsingEmbeddedDaemon() || !bun.available);
|
ImGui::BeginDisabled(!app->isUsingEmbeddedDaemon() || !bun.available);
|
||||||
if (TactileButton(TR("daemon_install_bundled"), ImVec2(0, 0), btnFont)) {
|
if (TactileButton(TR("daemon_install_bundled"), ImVec2(nodeBtnW, 0), btnFont)) {
|
||||||
s_settingsState.confirm_reinstall_daemon = true;
|
s_settingsState.confirm_reinstall_daemon = true;
|
||||||
}
|
}
|
||||||
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) ImGui::SetTooltip("%s", TR("tt_daemon_install_bundled"));
|
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) ImGui::SetTooltip("%s", TR("tt_daemon_install_bundled"));
|
||||||
ImGui::EndDisabled();
|
ImGui::EndDisabled();
|
||||||
ImGui::SameLine(0, Layout::spacingMd());
|
ImGui::SameLine(0, Layout::spacingMd());
|
||||||
if (TactileButton(TR("refresh"), ImVec2(0, 0), btnFont)) {
|
if (TactileButton(TR("refresh"), ImVec2(nodeBtnW, 0), btnFont)) {
|
||||||
s_settingsState.daemon_info_loaded = false; // recompute next frame
|
s_settingsState.daemon_info_loaded = false; // recompute next frame
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -424,14 +424,14 @@ void I18n::loadBuiltinEnglish()
|
|||||||
strings_["confirm_repair_wallet_msg"] = "This restarts the daemon with -zapwallettxes=2: it deletes all of the wallet's transaction and note records, then rebuilds them from the blockchain. Use this when transactions fail to build (\"Invalid sapling spend proof\" / \"shielded requirements not met\") even after a full rescan. It takes a long time and the wallet stays offline until it finishes.";
|
strings_["confirm_repair_wallet_msg"] = "This restarts the daemon with -zapwallettxes=2: it deletes all of the wallet's transaction and note records, then rebuilds them from the blockchain. Use this when transactions fail to build (\"Invalid sapling spend proof\" / \"shielded requirements not met\") even after a full rescan. It takes a long time and the wallet stays offline until it finishes.";
|
||||||
strings_["confirm_repair_wallet_safe"] = "Your keys, addresses and balance are preserved — only the cached transaction records are rebuilt.";
|
strings_["confirm_repair_wallet_safe"] = "Your keys, addresses and balance are preserved — only the cached transaction records are rebuilt.";
|
||||||
strings_["daemon_binary"] = "Daemon binary";
|
strings_["daemon_binary"] = "Daemon binary";
|
||||||
strings_["daemon_installed"] = "Installed:";
|
strings_["daemon_installed"] = "Installed";
|
||||||
strings_["daemon_bundled"] = "Bundled:";
|
strings_["daemon_bundled"] = "Bundled";
|
||||||
strings_["daemon_not_installed"] = "not installed";
|
strings_["daemon_not_installed"] = "not installed";
|
||||||
strings_["daemon_none_bundled"] = "none in this build";
|
strings_["daemon_none_bundled"] = "none in this build";
|
||||||
strings_["daemon_status_match"] = "Installed binary matches the bundled version.";
|
strings_["daemon_status_match"] = "Installed binary matches the bundled version.";
|
||||||
strings_["daemon_status_differ"] = "Installed binary differs from the bundled version.";
|
strings_["daemon_status_differ"] = "Installed binary differs from the bundled version.";
|
||||||
strings_["daemon_status_missing"] = "No daemon installed — install the bundled version.";
|
strings_["daemon_status_missing"] = "No daemon installed — install the bundled version.";
|
||||||
strings_["daemon_install_bundled"] = "Install bundled daemon";
|
strings_["daemon_install_bundled"] = "Install bundled";
|
||||||
strings_["tt_daemon_install_bundled"] = "Stop the node, overwrite the installed dragonxd with the version bundled in this wallet build, then restart";
|
strings_["tt_daemon_install_bundled"] = "Stop the node, overwrite the installed dragonxd with the version bundled in this wallet build, then restart";
|
||||||
strings_["confirm_reinstall_daemon_title"] = "Install Bundled Daemon";
|
strings_["confirm_reinstall_daemon_title"] = "Install Bundled Daemon";
|
||||||
strings_["confirm_reinstall_daemon_msg"] = "This stops the daemon, overwrites the installed dragonxd (and dragonx-cli/dragonx-tx) with the versions bundled in this wallet build, then restarts the node. Use this to recover or update the node binary.";
|
strings_["confirm_reinstall_daemon_msg"] = "This stops the daemon, overwrites the installed dragonxd (and dragonx-cli/dragonx-tx) with the versions bundled in this wallet build, then restarts the node. Use this to recover or update the node binary.";
|
||||||
|
|||||||
Reference in New Issue
Block a user