fix(settings): swap Install bundled/Test connection; unique daemon Refresh ID
Swap the "Install bundled" and "Test connection" daemon-binary buttons:
Install bundled now sits in the left common row (Check for updates | Refresh
| Install bundled); Test connection leads the right-aligned maintenance
group. Each button keeps its own disabled-predicates, action, and tooltip.
Give the daemon-binary Refresh button a unique ImGui ID
("Refresh##daemonRefresh") so it no longer collides with the theme-section
Refresh buttons, which triggered Dear ImGui's "2 visible items with
conflicting ID!" error. The label still displays "Refresh".
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2251,7 +2251,7 @@ void RenderSettingsPage(App* app) {
|
|||||||
if (ui::DaemonUpdateDialog::consumeInstalled())
|
if (ui::DaemonUpdateDialog::consumeInstalled())
|
||||||
s_settingsState.daemon_info_loaded = false;
|
s_settingsState.daemon_info_loaded = false;
|
||||||
|
|
||||||
// Action row: Check for updates | Refresh | Test connection on the left,
|
// Action row: Check for updates | Refresh | Install bundled on the left,
|
||||||
// with the four maintenance actions right-aligned on the same row.
|
// with the four maintenance actions right-aligned on the same row.
|
||||||
ImGui::Dummy(ImVec2(0, Layout::spacingXs()));
|
ImGui::Dummy(ImVec2(0, Layout::spacingXs()));
|
||||||
float daemonBtnRowY = ImGui::GetCursorScreenPos().y;
|
float daemonBtnRowY = ImGui::GetCursorScreenPos().y;
|
||||||
@@ -2260,40 +2260,42 @@ void RenderSettingsPage(App* app) {
|
|||||||
}
|
}
|
||||||
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) material::Tooltip("%s", TR("tt_daemon_update_check"));
|
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) material::Tooltip("%s", TR("tt_daemon_update_check"));
|
||||||
ImGui::SameLine(0, spMd);
|
ImGui::SameLine(0, spMd);
|
||||||
if (TactileButton(TR("refresh"), ImVec2(0, 0), dbBtnFont)) {
|
// Unique ImGui ID (label still displays "Refresh") — the theme sections
|
||||||
|
// also have "Refresh" buttons, so a bare label collides on this page.
|
||||||
|
if (TactileButton((std::string(TR("refresh")) + "##daemonRefresh").c_str(), ImVec2(0, 0), dbBtnFont)) {
|
||||||
s_settingsState.daemon_info_loaded = false;
|
s_settingsState.daemon_info_loaded = false;
|
||||||
}
|
}
|
||||||
ImGui::SameLine(0, spMd);
|
ImGui::SameLine(0, spMd);
|
||||||
ImGui::BeginDisabled(!app->isConnected());
|
ImGui::BeginDisabled(!app->isUsingEmbeddedDaemon() || !bun.available);
|
||||||
if (TactileButton(TR("test_connection"), ImVec2(0, 0), dbBtnFont)) {
|
if (TactileButton(TR("daemon_install_bundled"), ImVec2(0, 0), dbBtnFont)) {
|
||||||
if (app->rpc() && app->rpc()->isConnected() && app->worker()) {
|
s_settingsState.confirm_reinstall_daemon = true;
|
||||||
app->worker()->post([rpc = app->rpc()]() -> rpc::RPCWorker::MainCb {
|
|
||||||
try {
|
|
||||||
rpc::RPCClient::TraceScope trace("Settings / Test connection");
|
|
||||||
rpc->call("getinfo");
|
|
||||||
return []() { Notifications::instance().success("RPC connection OK"); };
|
|
||||||
} catch (const std::exception& e) {
|
|
||||||
std::string err = e.what();
|
|
||||||
return [err]() { Notifications::instance().error("RPC error: " + err); };
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
Notifications::instance().warning("Not connected to daemon");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) material::Tooltip("%s", TR("tt_test_conn"));
|
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) material::Tooltip("%s", TR("tt_daemon_install_bundled"));
|
||||||
ImGui::EndDisabled();
|
ImGui::EndDisabled();
|
||||||
|
|
||||||
// The four maintenance actions (Install bundled / Rescan / Delete blockchain
|
// The four maintenance actions (Test connection / Rescan / Delete blockchain
|
||||||
// / Repair wallet), right-aligned on the SAME row as Test connection — no
|
// / Repair wallet), right-aligned on the SAME row as Install bundled — no
|
||||||
// separate "Advanced" toggle. Every BeginDisabled/EndDisabled predicate is
|
// separate "Advanced" toggle. Every BeginDisabled/EndDisabled predicate is
|
||||||
// preserved exactly. Wraps to a right-aligned next row when too narrow.
|
// preserved exactly. Wraps to a right-aligned next row when too narrow.
|
||||||
auto renderDaemonMaintenanceButtons = [&]() {
|
auto renderDaemonMaintenanceButtons = [&]() {
|
||||||
ImGui::BeginDisabled(!app->isUsingEmbeddedDaemon() || !bun.available);
|
ImGui::BeginDisabled(!app->isConnected());
|
||||||
if (TactileButton(TR("daemon_install_bundled"), ImVec2(0, 0), dbBtnFont)) {
|
if (TactileButton(TR("test_connection"), ImVec2(0, 0), dbBtnFont)) {
|
||||||
s_settingsState.confirm_reinstall_daemon = true;
|
if (app->rpc() && app->rpc()->isConnected() && app->worker()) {
|
||||||
|
app->worker()->post([rpc = app->rpc()]() -> rpc::RPCWorker::MainCb {
|
||||||
|
try {
|
||||||
|
rpc::RPCClient::TraceScope trace("Settings / Test connection");
|
||||||
|
rpc->call("getinfo");
|
||||||
|
return []() { Notifications::instance().success("RPC connection OK"); };
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
std::string err = e.what();
|
||||||
|
return [err]() { Notifications::instance().error("RPC error: " + err); };
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
Notifications::instance().warning("Not connected to daemon");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) material::Tooltip("%s", TR("tt_daemon_install_bundled"));
|
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) material::Tooltip("%s", TR("tt_test_conn"));
|
||||||
ImGui::EndDisabled();
|
ImGui::EndDisabled();
|
||||||
ImGui::SameLine(0, spMd);
|
ImGui::SameLine(0, spMd);
|
||||||
ImGui::BeginDisabled(!app->isConnected());
|
ImGui::BeginDisabled(!app->isConnected());
|
||||||
@@ -2320,17 +2322,17 @@ void RenderSettingsPage(App* app) {
|
|||||||
};
|
};
|
||||||
{
|
{
|
||||||
// Group width (button font) to right-align the four maintenance actions.
|
// Group width (button font) to right-align the four maintenance actions.
|
||||||
const char* mLabels[] = { TR("daemon_install_bundled"), TR("rescan"),
|
const char* mLabels[] = { TR("test_connection"), TR("rescan"),
|
||||||
TR("delete_blockchain"), TR("repair_wallet") };
|
TR("delete_blockchain"), TR("repair_wallet") };
|
||||||
float groupW = spMd * 3.0f;
|
float groupW = spMd * 3.0f;
|
||||||
for (const char* l : mLabels)
|
for (const char* l : mLabels)
|
||||||
groupW += dbBtnFont->CalcTextSizeA(dbBtnFont->LegacySize, FLT_MAX, 0, l).x
|
groupW += dbBtnFont->CalcTextSizeA(dbBtnFont->LegacySize, FLT_MAX, 0, l).x
|
||||||
+ ImGui::GetStyle().FramePadding.x * 2.0f;
|
+ ImGui::GetStyle().FramePadding.x * 2.0f;
|
||||||
float afterTestX = ImGui::GetItemRectMax().x + spMd; // right edge of Test connection
|
float afterTestX = ImGui::GetItemRectMax().x + spMd; // right edge of Install bundled
|
||||||
float rightEdge = sectionOrigin.x + contentW;
|
float rightEdge = sectionOrigin.x + contentW;
|
||||||
float groupX = rightEdge - groupW;
|
float groupX = rightEdge - groupW;
|
||||||
if (groupX >= afterTestX) {
|
if (groupX >= afterTestX) {
|
||||||
// Fits on the Test-connection row, right-aligned.
|
// Fits on the Install-bundled row, right-aligned.
|
||||||
ImGui::SameLine(0, 0);
|
ImGui::SameLine(0, 0);
|
||||||
ImGui::SetCursorScreenPos(ImVec2(groupX, daemonBtnRowY));
|
ImGui::SetCursorScreenPos(ImVec2(groupX, daemonBtnRowY));
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Reference in New Issue
Block a user