diff --git a/src/ui/windows/mining_tab.cpp b/src/ui/windows/mining_tab.cpp index 8c8013d..bf43d05 100644 --- a/src/ui/windows/mining_tab.cpp +++ b/src/ui/windows/mining_tab.cpp @@ -7,6 +7,7 @@ #include "mining_tab_helpers.h" #include "mining_pool_panel.h" #include "xmrig_download_dialog.h" +#include "../../util/xmrig_updater.h" #include "../../app.h" #include "../../util/i18n.h" #include "../../config/version.h" @@ -53,6 +54,13 @@ bool IsMiningBenchmarkActive() { return s_benchmark.active(); } +// Miner-update version check (one shot per session): fetches the latest DRG-XMRig release tag in +// the background so the "Update" button can show it. Network call to the project Gitea, started +// the first time the pool section is shown. +static util::XmrigUpdater s_xmrig_version_check; +static bool s_xmrig_check_started = false; +static std::string s_xmrig_latest_tag; + // Pool mode state static bool s_pool_mode = false; static char s_pool_url[256] = "pool.dragonx.is:3433"; @@ -152,6 +160,17 @@ static void RenderMiningTabContent(App* app) strncpy(s_pool_worker, app->settings()->getPoolWorker().c_str(), sizeof(s_pool_worker) - 1); s_pool_state_loaded = true; } + // Kick off a one-shot miner-version check the first time the pool section is shown, then cache + // the latest tag once it arrives (so the "Update" button can display it). Network call. + if (s_pool_mode && !s_xmrig_check_started) { + s_xmrig_version_check.startCheck(app->settings()->getXmrigVersion()); + s_xmrig_check_started = true; + } + if (s_xmrig_check_started && s_xmrig_latest_tag.empty()) { + const auto _vp = s_xmrig_version_check.getProgress(); + if (!_vp.latest_tag.empty()) s_xmrig_latest_tag = _vp.latest_tag; + } + if (!app->supportsSoloMining() && !s_pool_mode) { s_pool_mode = true; app->settings()->setPoolMode(true); @@ -1250,6 +1269,53 @@ static void RenderMiningTabContent(App* app) idleRightEdge = btnX - 4.0f * dp; } + // --- Miner update: "Update " button + current version (left of benchmark) --- + if (s_pool_mode && !benchRunning) { + const std::string curVer = app->settings()->getXmrigVersion(); + char xbtn[64]; + if (!s_xmrig_latest_tag.empty()) + snprintf(xbtn, sizeof(xbtn), "%s %s", TR("xmrig_update_short"), s_xmrig_latest_tag.c_str()); + else + snprintf(xbtn, sizeof(xbtn), "%s", TR("xmrig_update_button")); + + const bool minerBusy = state.pool_mining.xmrig_running; + ImVec2 xlblSz = capFont->CalcTextSizeA(capFont->LegacySize, FLT_MAX, 0, xbtn); + float xpadX = 8.0f * dp; + float xbtnW = xlblSz.x + xpadX * 2.0f; + float xbtnH = capFont->LegacySize + 6.0f * dp; + float xbtnX = idleRightEdge - xbtnW; + float xbtnY = curY + (headerH - xbtnH) * 0.5f; + + ImGui::SetCursorScreenPos(ImVec2(xbtnX, xbtnY)); + ImGui::InvisibleButton("##XmrigUpdateBtn", ImVec2(xbtnW, xbtnH)); + bool xhov = ImGui::IsItemHovered(); + bool xclk = ImGui::IsItemClicked(); + ImU32 xpill = minerBusy ? WithAlpha(OnSurface(), 12) + : (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() : OnSurfaceMedium(), xbtn); + if (xhov) { + ImGui::SetMouseCursor(ImGuiMouseCursor_Hand); + ImGui::SetTooltip("%s", minerBusy ? TR("xmrig_stop_mining_first") + : TR("xmrig_update_title")); + } + if (xclk && !minerBusy) XmrigDownloadDialog::show(app); + + // Current installed version, as text to the LEFT of the button. + char xcur[64]; + snprintf(xcur, sizeof(xcur), "%s %s", TR("xmrig_current"), + curVer.empty() ? TR("xmrig_none") : curVer.c_str()); + ImVec2 xcurSz = capFont->CalcTextSizeA(capFont->LegacySize, FLT_MAX, 0, xcur); + float xcurX = xbtnX - 6.0f * dp - xcurSz.x; + dl->AddText(capFont, capFont->LegacySize, + ImVec2(xcurX, curY + (headerH - xcurSz.y) * 0.5f), + OnSurfaceDisabled(), xcur); + idleRightEdge = xcurX - 8.0f * dp; + } + ImGui::SetCursorScreenPos(benchSavedCur); } @@ -1575,20 +1641,8 @@ static void RenderMiningTabContent(App* app) ImGui::Dummy(ImVec2(0, gap)); } - // ================================================================ - // POOL MINER — download / update the bundled DRG-XMRig miner from the project release server. - // (Pool mode uses xmrig; disabled while it's running so we never replace a live binary.) - // ================================================================ - if (s_pool_mode) { - const bool minerBusy = state.pool_mining.xmrig_running; - ImGui::BeginDisabled(minerBusy); - if (TactileButton(TR("xmrig_update_button"), ImVec2(availWidth, 0))) - XmrigDownloadDialog::show(app); - ImGui::EndDisabled(); - if (minerBusy && ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) - ImGui::SetTooltip("%s", TR("xmrig_stop_mining_first")); - ImGui::Dummy(ImVec2(0, gap)); - } + // (The miner download/update control lives in the mining-control header row, next to the + // benchmark button — see the "Miner update" block above.) // ================================================================ // HASHRATE + STATS — Combined glass card: stat values on top, chart below diff --git a/src/util/i18n.cpp b/src/util/i18n.cpp index ec15f3b..25c47d6 100644 --- a/src/util/i18n.cpp +++ b/src/util/i18n.cpp @@ -1038,6 +1038,9 @@ void I18n::loadBuiltinEnglish() // --- Miner (xmrig) updater --- strings_["xmrig_update_button"] = "Update miner…"; + strings_["xmrig_update_short"] = "Update"; + strings_["xmrig_current"] = "Current:"; + strings_["xmrig_none"] = "none"; strings_["xmrig_update_title"] = "Update Miner"; strings_["xmrig_stop_mining_first"] = "Stop mining before updating the miner."; strings_["xmrig_checking"] = "Checking for the latest miner…";