feat(mining): thread-count stepper, adaptive tiles, dropdown click-through fix, xmrig version state
Mining-tab UI improvements: - Thread selector: a centered [-] N [+] stepper (top-aligned in the header) to pick an exact thread count — number centered, -/+ step by one (clamped to [1, cores]), still typeable (commits on Enter so it doesn't restart the miner mid-typing). - Thread tiles now render at an adaptive step (1/2/4/8 by core count) plus 1 and the max, so a high-core CPU (e.g. a 192-thread EPYC) shows ~25 tiles instead of one-per-thread and no longer overflows the card. Unchanged for <=24-core machines. - Fix: clicking the X (or a row) in an open saved-pools / payout-address dropdown no longer bleeds through to the thread tiles / Mine button — the custom drawlist hit-tests now gate on IsPopupOpen(AnyPopup). - xmrig update button: shows "xmrig releases" when installed >= latest (numeric version compare), else "Update <latest>"; the "Current: <ver>" text and the button are subtle green when up to date and subtle orange when an update is available (neutral when either version is unknown). New i18n keys back-filled across all 8 languages; CJK subset font rebuilt for the new glyphs. Verified across full-node, lite, and Windows builds; the stepper layout confirmed via the UI sweep. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Binary file not shown.
@@ -949,6 +949,9 @@
|
||||
"mining_syncing_tooltip": "Blockchain synchronisiert...",
|
||||
"mining_tag": " · Mining",
|
||||
"mining_threads": "Mining-Threads",
|
||||
"mining_threads_input_tooltip": "Genaue Thread-Anzahl eingeben (Enter zum Übernehmen)",
|
||||
"mining_threads_minus_tooltip": "Weniger Threads",
|
||||
"mining_threads_plus_tooltip": "Mehr Threads",
|
||||
"mining_to_save": "zum Speichern",
|
||||
"mining_today": "Heute",
|
||||
"mining_uptime": "Laufzeit",
|
||||
@@ -1785,6 +1788,7 @@
|
||||
"xmrig_loading_releases": "Releases werden geladen…",
|
||||
"xmrig_none": "keiner",
|
||||
"xmrig_reinstall": "Neu installieren",
|
||||
"xmrig_releases": "xmrig-Releases",
|
||||
"xmrig_stop_mining_first": "Stoppen Sie das Mining, bevor Sie den Miner aktualisieren.",
|
||||
"xmrig_unavailable_body": "Für diese Plattform ist kein Miner-Build verfügbar.",
|
||||
"xmrig_unavailable_title": "Miner-Updates nicht verfügbar",
|
||||
|
||||
@@ -949,6 +949,9 @@
|
||||
"mining_syncing_tooltip": "El blockchain está sincronizando...",
|
||||
"mining_tag": " · Minería",
|
||||
"mining_threads": "Hilos de Minería",
|
||||
"mining_threads_input_tooltip": "Escribe un número exacto de hilos (pulsa Enter para aplicar)",
|
||||
"mining_threads_minus_tooltip": "Menos hilos",
|
||||
"mining_threads_plus_tooltip": "Más hilos",
|
||||
"mining_to_save": "para guardar",
|
||||
"mining_today": "Hoy",
|
||||
"mining_uptime": "Tiempo activo",
|
||||
@@ -1785,6 +1788,7 @@
|
||||
"xmrig_loading_releases": "Cargando versiones…",
|
||||
"xmrig_none": "ninguno",
|
||||
"xmrig_reinstall": "Reinstalar",
|
||||
"xmrig_releases": "versiones de xmrig",
|
||||
"xmrig_stop_mining_first": "Detén la minería antes de actualizar el minero.",
|
||||
"xmrig_unavailable_body": "No hay ninguna versión del minero disponible para esta plataforma.",
|
||||
"xmrig_unavailable_title": "Actualizaciones del minero no disponibles",
|
||||
|
||||
@@ -949,6 +949,9 @@
|
||||
"mining_syncing_tooltip": "La blockchain se synchronise...",
|
||||
"mining_tag": " · Minage",
|
||||
"mining_threads": "Threads de minage",
|
||||
"mining_threads_input_tooltip": "Saisissez un nombre exact de threads (Entrée pour appliquer)",
|
||||
"mining_threads_minus_tooltip": "Moins de threads",
|
||||
"mining_threads_plus_tooltip": "Plus de threads",
|
||||
"mining_to_save": "pour enregistrer",
|
||||
"mining_today": "Aujourd'hui",
|
||||
"mining_uptime": "Temps de fonctionnement",
|
||||
@@ -1785,6 +1788,7 @@
|
||||
"xmrig_loading_releases": "Chargement des versions…",
|
||||
"xmrig_none": "aucun",
|
||||
"xmrig_reinstall": "Réinstaller",
|
||||
"xmrig_releases": "versions de xmrig",
|
||||
"xmrig_stop_mining_first": "Arrêtez le minage avant de mettre à jour le mineur.",
|
||||
"xmrig_unavailable_body": "Aucune version du mineur n'est disponible pour cette plateforme.",
|
||||
"xmrig_unavailable_title": "Mises à jour du mineur indisponibles",
|
||||
|
||||
@@ -949,6 +949,9 @@
|
||||
"mining_syncing_tooltip": "ブロックチェーン同期中...",
|
||||
"mining_tag": " · マイニング",
|
||||
"mining_threads": "マイニングスレッド",
|
||||
"mining_threads_input_tooltip": "正確なスレッド数を入力(Enter で適用)",
|
||||
"mining_threads_minus_tooltip": "スレッドを減らす",
|
||||
"mining_threads_plus_tooltip": "スレッドを増やす",
|
||||
"mining_to_save": "保存する",
|
||||
"mining_today": "今日",
|
||||
"mining_uptime": "稼働時間",
|
||||
@@ -1782,6 +1785,7 @@
|
||||
"xmrig_loading_releases": "リリースを読み込み中…",
|
||||
"xmrig_none": "なし",
|
||||
"xmrig_reinstall": "再インストール",
|
||||
"xmrig_releases": "xmrig リリース",
|
||||
"xmrig_stop_mining_first": "マイナーを更新する前にマイニングを停止してください。",
|
||||
"xmrig_unavailable_body": "このプラットフォーム向けのマイナービルドは利用できません。",
|
||||
"xmrig_unavailable_title": "マイナーの更新は利用できません",
|
||||
|
||||
@@ -948,6 +948,9 @@
|
||||
"mining_syncing_tooltip": "블록체인 동기화 중...",
|
||||
"mining_tag": " · 채굴",
|
||||
"mining_threads": "채굴 스레드",
|
||||
"mining_threads_input_tooltip": "정확한 스레드 수 입력 (Enter로 적용)",
|
||||
"mining_threads_minus_tooltip": "스레드 줄이기",
|
||||
"mining_threads_plus_tooltip": "스레드 늘리기",
|
||||
"mining_to_save": "저장하려면",
|
||||
"mining_today": "오늘",
|
||||
"mining_uptime": "가동 시간",
|
||||
@@ -1784,6 +1787,7 @@
|
||||
"xmrig_loading_releases": "릴리스를 불러오는 중…",
|
||||
"xmrig_none": "없음",
|
||||
"xmrig_reinstall": "재설치",
|
||||
"xmrig_releases": "xmrig 릴리스",
|
||||
"xmrig_stop_mining_first": "채굴기를 업데이트하기 전에 채굴을 중지하세요.",
|
||||
"xmrig_unavailable_body": "이 플랫폼에서 사용 가능한 채굴기 빌드가 없습니다.",
|
||||
"xmrig_unavailable_title": "채굴기 업데이트를 사용할 수 없습니다",
|
||||
|
||||
@@ -949,6 +949,9 @@
|
||||
"mining_syncing_tooltip": "Blockchain está sincronizando...",
|
||||
"mining_tag": " · Mineração",
|
||||
"mining_threads": "Threads de Mineração",
|
||||
"mining_threads_input_tooltip": "Digite um número exato de threads (Enter para aplicar)",
|
||||
"mining_threads_minus_tooltip": "Menos threads",
|
||||
"mining_threads_plus_tooltip": "Mais threads",
|
||||
"mining_to_save": "para salvar",
|
||||
"mining_today": "Hoje",
|
||||
"mining_uptime": "Tempo Ativo",
|
||||
@@ -1785,6 +1788,7 @@
|
||||
"xmrig_loading_releases": "Carregando versões…",
|
||||
"xmrig_none": "nenhum",
|
||||
"xmrig_reinstall": "Reinstalar",
|
||||
"xmrig_releases": "versões do xmrig",
|
||||
"xmrig_stop_mining_first": "Pare a mineração antes de atualizar o minerador.",
|
||||
"xmrig_unavailable_body": "Nenhuma versão do minerador está disponível para esta plataforma.",
|
||||
"xmrig_unavailable_title": "Atualizações do minerador indisponíveis",
|
||||
|
||||
@@ -949,6 +949,9 @@
|
||||
"mining_syncing_tooltip": "Блокчейн синхронизируется...",
|
||||
"mining_tag": " · Майнинг",
|
||||
"mining_threads": "Потоки майнинга",
|
||||
"mining_threads_input_tooltip": "Введите точное число потоков (Enter для применения)",
|
||||
"mining_threads_minus_tooltip": "Меньше потоков",
|
||||
"mining_threads_plus_tooltip": "Больше потоков",
|
||||
"mining_to_save": "для сохранения",
|
||||
"mining_today": "Сегодня",
|
||||
"mining_uptime": "Время работы",
|
||||
@@ -1785,6 +1788,7 @@
|
||||
"xmrig_loading_releases": "Загрузка релизов…",
|
||||
"xmrig_none": "нет",
|
||||
"xmrig_reinstall": "Переустановить",
|
||||
"xmrig_releases": "релизы xmrig",
|
||||
"xmrig_stop_mining_first": "Остановите майнинг перед обновлением майнера.",
|
||||
"xmrig_unavailable_body": "Для этой платформы нет доступной сборки майнера.",
|
||||
"xmrig_unavailable_title": "Обновления майнера недоступны",
|
||||
|
||||
@@ -948,6 +948,9 @@
|
||||
"mining_syncing_tooltip": "区块链同步中...",
|
||||
"mining_tag": " · 挖矿",
|
||||
"mining_threads": "挖矿线程",
|
||||
"mining_threads_input_tooltip": "输入精确的线程数(按 Enter 应用)",
|
||||
"mining_threads_minus_tooltip": "减少线程",
|
||||
"mining_threads_plus_tooltip": "增加线程",
|
||||
"mining_to_save": "保存",
|
||||
"mining_today": "今天",
|
||||
"mining_uptime": "运行时间",
|
||||
@@ -1783,6 +1786,7 @@
|
||||
"xmrig_loading_releases": "正在加载发行版…",
|
||||
"xmrig_none": "无",
|
||||
"xmrig_reinstall": "重新安装",
|
||||
"xmrig_releases": "xmrig 版本",
|
||||
"xmrig_stop_mining_first": "更新矿工程序前请先停止挖矿。",
|
||||
"xmrig_unavailable_body": "此平台没有可用的矿工构建版本。",
|
||||
"xmrig_unavailable_title": "矿工更新不可用",
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <cstdlib> // std::atoi (xmrig version compare)
|
||||
|
||||
namespace dragonx {
|
||||
namespace ui {
|
||||
@@ -56,6 +57,25 @@ void RenderMiningControls(App* app, const WalletState& state, const MiningInfo&
|
||||
float miningBtnGap = gap;
|
||||
float miningBtnMaxW = availWidth * schema::UI().drawElement("tabs.mining", "btn-max-width-ratio").size;
|
||||
|
||||
// Thread-count tiles at an adaptive step (multiples of 1/2/4/8, chosen by core count) plus 1 and the
|
||||
// max, so the tile row stays bounded (~<=24 tiles) instead of one tile per thread — a 192-thread
|
||||
// EPYC would otherwise overflow the card. Exact in-between counts are settable via the input box.
|
||||
int tileStep = 1;
|
||||
if (max_threads > 96) tileStep = 8;
|
||||
else if (max_threads > 48) tileStep = 4;
|
||||
else if (max_threads > 24) tileStep = 2;
|
||||
std::vector<int> threadOptions;
|
||||
threadOptions.push_back(1);
|
||||
for (int v = tileStep; v < max_threads; v += tileStep)
|
||||
if (v > 1) threadOptions.push_back(v);
|
||||
if (max_threads > 1 && threadOptions.back() != max_threads) threadOptions.push_back(max_threads);
|
||||
const int nOpts = (int)threadOptions.size();
|
||||
|
||||
// Custom drawlist hit-tests (the thread tiles + the Mine button) bypass ImGui's popup input capture,
|
||||
// so a click on an open dropdown (saved pools / payout addresses) would ALSO fire them. Gate on this
|
||||
// so clicking the dropdown's X (or a row) doesn't bleed through to the tiles/Mine button.
|
||||
const bool anyPopupOpen = ImGui::IsPopupOpen("", ImGuiPopupFlags_AnyPopupId | ImGuiPopupFlags_AnyPopupLevel);
|
||||
|
||||
// --- Compute thread grid layout based on controls card width ---
|
||||
// Estimate controlsW first to compute cols correctly
|
||||
// The Mine button is square (= card height, which scales with DPI), so the width we
|
||||
@@ -65,8 +85,8 @@ void RenderMiningControls(App* app, const WalletState& state, const MiningInfo&
|
||||
float innerW = estControlsW - pad * 2;
|
||||
float cellSz = std::clamp(schema::UI().drawElement("tabs.mining", "cell-size").size * vs, schema::UI().drawElement("tabs.mining", "cell-min-size").size, schema::UI().drawElement("tabs.mining", "cell-max-size").sizeOr(42.0f));
|
||||
float cellGap = std::max(schema::UI().drawElement("tabs.mining", "cell-gap-min").size, cellSz * schema::UI().drawElement("tabs.mining", "cell-gap-ratio").size);
|
||||
int cols = std::max(1, std::min(max_threads, (int)(innerW / (cellSz + cellGap))));
|
||||
int rows = (max_threads + cols - 1) / cols;
|
||||
int cols = std::max(1, std::min(nOpts, (int)(innerW / (cellSz + cellGap))));
|
||||
int rows = (nOpts + cols - 1) / cols;
|
||||
float gridW = cols * cellSz + (cols - 1) * cellGap;
|
||||
float gridH = rows * cellSz + (rows - 1) * cellGap;
|
||||
|
||||
@@ -116,6 +136,67 @@ void RenderMiningControls(App* app, const WalletState& state, const MiningInfo&
|
||||
OnSurfaceDisabled(), buf);
|
||||
}
|
||||
|
||||
// Centered, top-aligned thread-count stepper: [-] centered editable number [+]. Lets a
|
||||
// high-core CPU pick an EXACT count that isn't one of the tiles. The input commits on Enter
|
||||
// (not per keystroke) so it doesn't restart the miner while the user is still typing.
|
||||
{
|
||||
auto applyThreads = [&](int tc) {
|
||||
tc = std::clamp(tc, 1, max_threads);
|
||||
if (tc == s_selected_threads) return;
|
||||
s_selected_threads = tc;
|
||||
app->settings()->setPoolThreads(tc);
|
||||
app->settings()->save();
|
||||
if (mining.generate) app->startMining(tc);
|
||||
if (s_pool_mode && state.pool_mining.xmrig_running) {
|
||||
app->stopPoolMining();
|
||||
app->startPoolMining(tc);
|
||||
}
|
||||
};
|
||||
ImFont* stepFont = Type().iconSmall();
|
||||
const float fieldH = capFont->LegacySize + 6.0f * dp;
|
||||
const float sideW = fieldH; // square -/+ buttons
|
||||
const float fieldW = 46.0f * dp;
|
||||
const float g = 2.0f * dp;
|
||||
const float totalW = sideW + g + fieldW + g + sideW;
|
||||
float sx = cardMin.x + (controlsW - totalW) * 0.5f;
|
||||
const float sy = curY;
|
||||
ImVec2 savedCur = ImGui::GetCursorScreenPos();
|
||||
|
||||
material::IconButtonStyle sideStyle;
|
||||
sideStyle.color = OnSurfaceMedium();
|
||||
sideStyle.hoverBg = StateHover();
|
||||
|
||||
// "-" button
|
||||
sideStyle.tooltip = TR("mining_threads_minus_tooltip");
|
||||
ImGui::SetCursorScreenPos(ImVec2(sx, sy));
|
||||
if (material::IconButton("##ThreadMinus", ICON_MD_REMOVE, stepFont, ImVec2(sideW, fieldH), sideStyle))
|
||||
applyThreads(s_selected_threads - 1);
|
||||
sx += sideW + g;
|
||||
|
||||
// Centered editable number: symmetric FramePadding pushes the digits to the field centre.
|
||||
char tb[8]; snprintf(tb, sizeof(tb), "%d", s_selected_threads);
|
||||
float basePad = ImGui::GetStyle().FramePadding.x;
|
||||
float txtW = ImGui::CalcTextSize(tb).x;
|
||||
float centerPad = std::max(basePad, (fieldW - txtW) * 0.5f);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(centerPad, ImGui::GetStyle().FramePadding.y));
|
||||
ImGui::SetCursorScreenPos(ImVec2(sx, sy));
|
||||
ImGui::SetNextItemWidth(fieldW);
|
||||
int tc = s_selected_threads;
|
||||
if (ImGui::InputInt("##ThreadCountInput", &tc, 0, 0, ImGuiInputTextFlags_EnterReturnsTrue))
|
||||
applyThreads(tc);
|
||||
if (ImGui::IsItemHovered()) material::Tooltip("%s", TR("mining_threads_input_tooltip"));
|
||||
ImGui::PopStyleVar();
|
||||
sx += fieldW + g;
|
||||
|
||||
// "+" button
|
||||
sideStyle.tooltip = TR("mining_threads_plus_tooltip");
|
||||
ImGui::SetCursorScreenPos(ImVec2(sx, sy));
|
||||
if (material::IconButton("##ThreadPlus", ICON_MD_ADD, stepFont, ImVec2(sideW, fieldH), sideStyle))
|
||||
applyThreads(s_selected_threads + 1);
|
||||
|
||||
ImGui::SetCursorScreenPos(savedCur);
|
||||
}
|
||||
|
||||
// Idle mining toggle (top-right corner of card)
|
||||
float idleRightEdge = cardMax.x - pad;
|
||||
{
|
||||
@@ -475,8 +556,39 @@ 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();
|
||||
// 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> {
|
||||
if (!s.empty() && (s[0] == 'v' || s[0] == 'V')) s.erase(0, 1);
|
||||
s = s.substr(0, s.find('-')); // drop any -build suffix
|
||||
std::vector<int> v; size_t p = 0;
|
||||
while (p <= s.size()) {
|
||||
size_t q = s.find('.', p);
|
||||
v.push_back(std::atoi(s.substr(p, q == std::string::npos ? std::string::npos : q - p).c_str()));
|
||||
if (q == std::string::npos) break;
|
||||
p = q + 1;
|
||||
}
|
||||
return v;
|
||||
};
|
||||
const bool verKnown = !curVer.empty() && !s_xmrig_latest_tag.empty();
|
||||
bool upToDate = false;
|
||||
if (verKnown) {
|
||||
auto a = verNum(curVer), b = verNum(s_xmrig_latest_tag);
|
||||
int cmp = 0;
|
||||
for (size_t i = 0; i < std::max(a.size(), b.size()) && cmp == 0; ++i) {
|
||||
int x = i < a.size() ? a[i] : 0, y = i < b.size() ? b[i] : 0;
|
||||
if (x != y) cmp = x < y ? -1 : 1;
|
||||
}
|
||||
upToDate = (cmp >= 0); // installed >= latest
|
||||
}
|
||||
const bool outdated = verKnown && !upToDate;
|
||||
const ImU32 subtleGreen = IM_COL32(120, 190, 130, 255);
|
||||
const ImU32 subtleOrange = IM_COL32(214, 158, 74, 255);
|
||||
|
||||
char xbtn[64];
|
||||
if (!s_xmrig_latest_tag.empty())
|
||||
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());
|
||||
else
|
||||
snprintf(xbtn, sizeof(xbtn), "%s", TR("xmrig_update_button"));
|
||||
@@ -499,7 +611,9 @@ void RenderMiningControls(App* app, const WalletState& state, const MiningInfo&
|
||||
xpill, xbtnH * 0.3f);
|
||||
dl->AddText(capFont, capFont->LegacySize,
|
||||
ImVec2(xbtnX + xpadX, xbtnY + (xbtnH - xlblSz.y) * 0.5f),
|
||||
minerBusy ? OnSurfaceDisabled() : OnSurfaceMedium(), xbtn);
|
||||
minerBusy ? OnSurfaceDisabled()
|
||||
: (upToDate ? subtleGreen : outdated ? subtleOrange : OnSurfaceMedium()),
|
||||
xbtn);
|
||||
if (xhov) {
|
||||
ImGui::SetMouseCursor(ImGuiMouseCursor_Hand);
|
||||
material::Tooltip("%s", minerBusy ? TR("xmrig_stop_mining_first")
|
||||
@@ -515,7 +629,7 @@ void RenderMiningControls(App* app, const WalletState& state, const MiningInfo&
|
||||
float xcurX = xbtnX - 6.0f * dp - xcurSz.x;
|
||||
dl->AddText(capFont, capFont->LegacySize,
|
||||
ImVec2(xcurX, curY + (headerH - xcurSz.y) * 0.5f),
|
||||
OnSurfaceDisabled(), xcur);
|
||||
upToDate ? subtleGreen : outdated ? subtleOrange : OnSurfaceDisabled(), xcur);
|
||||
idleRightEdge = xcurX - 8.0f * dp;
|
||||
}
|
||||
|
||||
@@ -548,14 +662,14 @@ void RenderMiningControls(App* app, const WalletState& state, const MiningInfo&
|
||||
// Track which thread the mouse is currently over (-1 = none)
|
||||
int hovered_thread = -1;
|
||||
|
||||
// First pass: hit-test all cells to find hovered thread
|
||||
for (int i = 0; i < max_threads; i++) {
|
||||
// First pass: hit-test all cells to find the hovered thread-count option (its value, not index)
|
||||
for (int i = 0; i < nOpts; i++) {
|
||||
int row = i / cols;
|
||||
int col = i % cols;
|
||||
float cx = gridX + col * (cellSz + cellGap);
|
||||
float cy = gridY + row * (cellSz + cellGap);
|
||||
if (material::IsRectHovered(ImVec2(cx, cy), ImVec2(cx + cellSz, cy + cellSz))) {
|
||||
hovered_thread = i + 1;
|
||||
hovered_thread = threadOptions[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -566,8 +680,8 @@ void RenderMiningControls(App* app, const WalletState& state, const MiningInfo&
|
||||
if (hovered_thread > 0 && !benchActive)
|
||||
ImGui::SetMouseCursor(ImGuiMouseCursor_Hand);
|
||||
|
||||
// Drag-to-select logic (disabled during benchmark)
|
||||
if (!benchActive && ImGui::IsMouseClicked(0) && hovered_thread > 0) {
|
||||
// Drag-to-select logic (disabled during benchmark; ignored while a dropdown popup is open)
|
||||
if (!benchActive && !anyPopupOpen && ImGui::IsMouseClicked(0) && hovered_thread > 0) {
|
||||
// Begin drag
|
||||
s_drag_active = true;
|
||||
s_drag_anchor_thread = hovered_thread;
|
||||
@@ -587,8 +701,8 @@ void RenderMiningControls(App* app, const WalletState& state, const MiningInfo&
|
||||
}
|
||||
}
|
||||
|
||||
// Render cells
|
||||
for (int i = 0; i < max_threads; i++) {
|
||||
// Render cells (one per discrete thread-count option)
|
||||
for (int i = 0; i < nOpts; i++) {
|
||||
int row = i / cols;
|
||||
int col = i % cols;
|
||||
float cx = gridX + col * (cellSz + cellGap);
|
||||
@@ -596,8 +710,8 @@ void RenderMiningControls(App* app, const WalletState& state, const MiningInfo&
|
||||
ImVec2 cMin(cx, cy);
|
||||
ImVec2 cMax(cx + cellSz, cy + cellSz);
|
||||
|
||||
int threadNum = i + 1;
|
||||
bool active = threadNum <= s_selected_threads;
|
||||
int threadNum = threadOptions[i];
|
||||
bool active = threadNum <= s_selected_threads; // fill-up-to-selected heat metaphor
|
||||
bool hovered = (threadNum == hovered_thread);
|
||||
|
||||
// Determine visual state
|
||||
@@ -674,7 +788,7 @@ void RenderMiningControls(App* app, const WalletState& state, const MiningInfo&
|
||||
ImVec2 bMin(btnX, btnY);
|
||||
ImVec2 bMax(btnX + miningBtnSz, btnY + cardH);
|
||||
|
||||
bool btnHovered = material::IsRectHovered(bMin, bMax);
|
||||
bool btnHovered = !anyPopupOpen && material::IsRectHovered(bMin, bMax); // don't bleed through an open dropdown
|
||||
bool btnClicked = btnHovered && ImGui::IsMouseClicked(0);
|
||||
bool isSyncing = state.sync.syncing;
|
||||
bool poolBlockedBySolo = s_pool_mode && mining.generate && !state.pool_mining.xmrig_running;
|
||||
|
||||
@@ -1296,6 +1296,9 @@ void I18n::loadBuiltinEnglish()
|
||||
strings_["start_mining"] = "Start Mining";
|
||||
strings_["stop_mining"] = "Stop Mining";
|
||||
strings_["mining_threads"] = "Mining Threads";
|
||||
strings_["mining_threads_input_tooltip"] = "Type an exact thread count (press Enter to apply)";
|
||||
strings_["mining_threads_minus_tooltip"] = "Fewer threads";
|
||||
strings_["mining_threads_plus_tooltip"] = "More threads";
|
||||
strings_["mining_statistics"] = "Mining Statistics";
|
||||
strings_["local_hashrate"] = "Local Hashrate";
|
||||
strings_["network_hashrate"] = "Network Hashrate";
|
||||
@@ -1933,6 +1936,7 @@ void I18n::loadBuiltinEnglish()
|
||||
// --- Miner (xmrig) updater ---
|
||||
strings_["xmrig_update_button"] = "Update miner…";
|
||||
strings_["xmrig_update_short"] = "Update";
|
||||
strings_["xmrig_releases"] = "xmrig releases";
|
||||
strings_["xmrig_current"] = "Current:";
|
||||
strings_["xmrig_none"] = "none";
|
||||
strings_["xmrig_update_title"] = "Update Miner";
|
||||
|
||||
Reference in New Issue
Block a user