refactor(mining): surface inconclusive benchmark; dedup idle combo

- mining_benchmark: when a thread benchmark finishes with no nonzero
  hashrate sample (e.g. the pool never reported a rate), don't finish
  silently — set a new `inconclusive` flag on ThreadBenchmarkUpdate and
  let mining_tab warn. Keeps the state-machine core pure/no-I/O (it is
  unit-tested), rather than calling the Notifications singleton from it.
- mining_controls: fold the two byte-identical idle-delay combo blocks
  (non-scaling + thread-scaling branches) into one lambda parameterised
  by combo id; removes ~30 lines of duplication.
- request_payment: drop the dead s_selected_addr_idx state and write the
  address-selected comparisons as std::string == char* consistently.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-05 15:09:08 -05:00
parent 658c0f355b
commit ec48538881
5 changed files with 24 additions and 38 deletions

View File

@@ -176,8 +176,9 @@ void RenderMiningControls(App* app, const WalletState& state, const MiningInfo&
idleRightEdge = gBtnX - 4.0f * dp;
}
// Idle delay combo (to the left, when idle is enabled and NOT in thread scaling mode)
if (idleOn && !threadScaling) {
// Idle delay combo renderer (shared by the non-scaling and thread-scaling
// branches below). Draws right-aligned at idleRightEdge and advances it.
auto renderIdleDelayCombo = [&](const char* comboId) {
struct DelayOption { int seconds; const char* label; };
static const DelayOption delays[] = {
{30, "30s"}, {60, "1m"}, {120, "2m"}, {300, "5m"}, {600, "10m"}
@@ -192,7 +193,7 @@ void RenderMiningControls(App* app, const WalletState& state, const MiningInfo&
float comboY = curY + (headerH - ImGui::GetFrameHeight()) * 0.5f;
ImGui::SetCursorScreenPos(ImVec2(comboX, comboY));
ImGui::SetNextItemWidth(comboW);
if (ImGui::BeginCombo("##IdleDelay", previewLabel, ImGuiComboFlags_NoArrowButton)) {
if (ImGui::BeginCombo(comboId, previewLabel, ImGuiComboFlags_NoArrowButton)) {
for (const auto& d : delays) {
bool selected = (d.seconds == curDelay);
if (ImGui::Selectable(d.label, selected)) {
@@ -206,6 +207,11 @@ void RenderMiningControls(App* app, const WalletState& state, const MiningInfo&
if (ImGui::IsItemHovered())
material::Tooltip("%s", TR("tt_idle_delay"));
idleRightEdge = comboX - 4.0f * dp;
};
// Idle delay combo (to the left, when idle is enabled and NOT in thread scaling mode)
if (idleOn && !threadScaling) {
renderIdleDelayCombo("##IdleDelay");
}
// Thread scaling controls: idle delay + active threads / idle threads combos
@@ -213,36 +219,7 @@ void RenderMiningControls(App* app, const WalletState& state, const MiningInfo&
int hwThreads = std::max(1, (int)std::thread::hardware_concurrency());
// Idle delay combo
{
struct DelayOption { int seconds; const char* label; };
static const DelayOption delays[] = {
{30, "30s"}, {60, "1m"}, {120, "2m"}, {300, "5m"}, {600, "10m"}
};
int curDelay = app->settings()->getMineIdleDelay();
const char* previewLabel = "2m";
for (const auto& d : delays) {
if (d.seconds == curDelay) { previewLabel = d.label; break; }
}
float comboW = schema::UI().drawElement("components.settings-page", "idle-combo-width").sizeOr(64.0f);
float comboX = idleRightEdge - comboW;
float comboY = curY + (headerH - ImGui::GetFrameHeight()) * 0.5f;
ImGui::SetCursorScreenPos(ImVec2(comboX, comboY));
ImGui::SetNextItemWidth(comboW);
if (ImGui::BeginCombo("##IdleDelayScale", previewLabel, ImGuiComboFlags_NoArrowButton)) {
for (const auto& d : delays) {
bool selected = (d.seconds == curDelay);
if (ImGui::Selectable(d.label, selected)) {
app->settings()->setMineIdleDelay(d.seconds);
app->settings()->save();
}
if (selected) ImGui::SetItemDefaultFocus();
}
ImGui::EndCombo();
}
if (ImGui::IsItemHovered())
material::Tooltip("%s", TR("tt_idle_delay"));
idleRightEdge = comboX - 4.0f * dp;
}
renderIdleDelayCombo("##IdleDelayScale");
// Idle threads combo (threads when system is idle)
{