feat(mining): explain solo/pool, add a payout-address create path, surface the miner download

New-user mining cluster from the UX audit:
- Solo/Pool toggle: hover tooltips on each half explaining the trade-off
  (solo = no fees but long waits on a small CPU; pool = frequent small payouts,
  needs the miner + a shielded payout address).
- Payout field: when it's empty (new wallets have no z-address, and a pool
  payout must be shielded) the bookmark button is replaced by a one-click
  "Generate a shielded payout address" button (createNewZAddress → fills the
  field, persists, toasts), instead of only a hover hint to the Receive tab.
- Miner updater pill: when no miner is installed it becomes a prominent accent
  "Download miner" call-to-action with a "pool mining needs DRG-XMRig" tooltip,
  instead of a subtle grey "Update" pill that's easy to miss.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-10-18 09:03:24 -05:00
co-authored by Claude Opus 4.8
parent 8eee351faa
commit 7d2972f315
3 changed files with 63 additions and 16 deletions
+12 -4
View File
@@ -579,6 +579,9 @@ void RenderMiningControls(App* app, const WalletState& state, const MiningInfo&
std::string curVer = s_live_miner_ver;
if (curVer.empty()) curVer = app->poolMiningInstalledVersion();
if (curVer.empty()) curVer = app->settings()->getXmrigVersion();
// No miner installed at all → pool mining can't run. Make this a prominent
// "Download miner" call-to-action instead of a subtle grey "Update" pill.
const bool minerMissing = curVer.empty();
// Version state: subtle GREEN + "xmrig releases" when up to date, subtle ORANGE +
// "Update <latest>" when an update is available, neutral when either version is unknown.
auto verNum = [](std::string s) -> std::vector<int> {
@@ -609,7 +612,9 @@ void RenderMiningControls(App* app, const WalletState& state, const MiningInfo&
const ImU32 subtleOrange = IM_COL32(214, 158, 74, 255);
char xbtn[64];
if (upToDate)
if (minerMissing)
snprintf(xbtn, sizeof(xbtn), "%s", TR("xmrig_download_miner"));
else if (upToDate)
snprintf(xbtn, sizeof(xbtn), "%s", TR("xmrig_releases"));
else if (!s_xmrig_latest_tag.empty())
snprintf(xbtn, sizeof(xbtn), "%s %s", TR("xmrig_update_short"), s_xmrig_latest_tag.c_str());
@@ -629,18 +634,21 @@ void RenderMiningControls(App* app, const WalletState& state, const MiningInfo&
bool xhov = ImGui::IsItemHovered();
bool xclk = ImGui::IsItemClicked();
ImU32 xpill = minerBusy ? WithAlpha(OnSurface(), 12)
: (xhov ? StateHover() : WithAlpha(OnSurface(), 28));
: (minerMissing ? WithAlpha(Primary(), xhov ? 70 : 45)
: (xhov ? StateHover() : WithAlpha(OnSurface(), 28)));
dl->AddRectFilled(ImVec2(xbtnX, xbtnY), ImVec2(xbtnX + xbtnW, xbtnY + xbtnH),
xpill, xbtnH * 0.3f);
dl->AddText(capFont, capFont->LegacySize,
ImVec2(xbtnX + xpadX, xbtnY + (xbtnH - xlblSz.y) * 0.5f),
minerBusy ? OnSurfaceDisabled()
: (upToDate ? subtleGreen : outdated ? subtleOrange : OnSurfaceMedium()),
: (minerMissing ? Primary()
: (upToDate ? subtleGreen : outdated ? subtleOrange : OnSurfaceMedium())),
xbtn);
if (xhov) {
ImGui::SetMouseCursor(ImGuiMouseCursor_Hand);
material::Tooltip("%s", minerBusy ? TR("xmrig_stop_mining_first")
: TR("xmrig_update_title"));
: (minerMissing ? TR("xmrig_download_miner_tip")
: TR("xmrig_update_title")));
}
if (xclk && !minerBusy) XmrigDownloadDialog::show(app);