daemon version check, idle mining control, bootstrap mirror, import key paste, and cleanup

- Add startup binary version checking for dragonxd/xmrig
- Display daemon version in UI
- Add idle mining thread count adjustment
- Add bootstrap mirror option (bootstrap2.dragonx.is) in setup wizard
- Add paste button to import private key dialog with address validation
- Add z-address generation UI feedback (loading indicator)
- Add option to delete blockchain data while preserving wallet.dat
- Add font scale slider hotkey tooltip (Ctrl+Plus/Ctrl+Minus)
- Fix Windows RPC auth: trim \r from config values, add .cookie fallback
- Fix connection status message during block index loading
- Improve application shutdown to prevent lingering background process
This commit is contained in:
dan_s
2026-03-17 14:57:12 -05:00
parent f0c87e4092
commit 4a841fd032
27 changed files with 897 additions and 2050 deletions

View File

@@ -415,6 +415,9 @@ void App::checkAutoLock() {
// ===========================================================================
// Mine when idle — auto-start/stop mining based on system idle state
// Supports two modes:
// 1. Start/Stop mode (default): start mining when idle, stop when active
// 2. Thread scaling mode: mining stays running, thread count changes
// ===========================================================================
void App::checkIdleMining() {
@@ -422,6 +425,7 @@ void App::checkIdleMining() {
// Feature disabled — if we previously auto-started, stop now
if (idle_mining_active_) {
idle_mining_active_ = false;
idle_scaled_to_idle_ = false;
if (settings_ && settings_->getPoolMode()) {
if (xmrig_manager_ && xmrig_manager_->isRunning())
stopPoolMining();
@@ -430,46 +434,89 @@ void App::checkIdleMining() {
stopMining();
}
}
// Reset scaling state when feature is off
if (idle_scaled_to_idle_) idle_scaled_to_idle_ = false;
return;
}
int idleSec = util::Platform::getSystemIdleSeconds();
int delay = settings_->getMineIdleDelay();
bool isPool = settings_->getPoolMode();
bool threadScaling = settings_->getIdleThreadScaling();
int maxThreads = std::max(1, (int)std::thread::hardware_concurrency());
// Check if mining is already running (manually started by user)
bool miningActive = isPool
? (xmrig_manager_ && xmrig_manager_->isRunning())
: state_.mining.generate;
if (idleSec >= delay) {
// System is idle — start mining if not already running
if (!miningActive && !idle_mining_active_ && !mining_toggle_in_progress_.load()) {
// For solo mining, need daemon connected and synced
if (!isPool && (!state_.connected || state_.sync.syncing)) return;
if (threadScaling) {
// --- Thread scaling mode ---
// Mining must already be running (started by user). We just adjust threads.
if (!miningActive || mining_toggle_in_progress_.load()) return;
int threads = settings_->getPoolThreads();
if (threads <= 0) threads = std::max(1, (int)std::thread::hardware_concurrency() / 2);
int activeThreads = settings_->getIdleThreadsActive();
int idleThreads = settings_->getIdleThreadsIdle();
// Resolve auto values: active defaults to half, idle defaults to all
if (activeThreads <= 0) activeThreads = std::max(1, maxThreads / 2);
if (idleThreads <= 0) idleThreads = maxThreads;
idle_mining_active_ = true;
if (isPool)
startPoolMining(threads);
else
startMining(threads);
DEBUG_LOGF("[App] Idle mining started after %d seconds idle\n", idleSec);
if (idleSec >= delay) {
// System is idle — scale up to idle thread count
if (!idle_scaled_to_idle_) {
idle_scaled_to_idle_ = true;
if (isPool) {
stopPoolMining();
startPoolMining(idleThreads);
} else {
startMining(idleThreads);
}
DEBUG_LOGF("[App] Idle thread scaling: %d -> %d threads (idle)\n", activeThreads, idleThreads);
}
} else {
// User is active — scale down to active thread count
if (idle_scaled_to_idle_) {
idle_scaled_to_idle_ = false;
if (isPool) {
stopPoolMining();
startPoolMining(activeThreads);
} else {
startMining(activeThreads);
}
DEBUG_LOGF("[App] Idle thread scaling: %d -> %d threads (active)\n", idleThreads, activeThreads);
}
}
} else {
// User is active — stop mining if we auto-started it
if (idle_mining_active_) {
idle_mining_active_ = false;
if (isPool) {
if (xmrig_manager_ && xmrig_manager_->isRunning())
stopPoolMining();
} else {
if (state_.mining.generate)
stopMining();
// --- Start/Stop mode (original behavior) ---
if (idleSec >= delay) {
// System is idle — start mining if not already running
if (!miningActive && !idle_mining_active_ && !mining_toggle_in_progress_.load()) {
// For solo mining, need daemon connected and synced
if (!isPool && (!state_.connected || state_.sync.syncing)) return;
int threads = settings_->getPoolThreads();
if (threads <= 0) threads = std::max(1, maxThreads / 2);
idle_mining_active_ = true;
if (isPool)
startPoolMining(threads);
else
startMining(threads);
DEBUG_LOGF("[App] Idle mining started after %d seconds idle\n", idleSec);
}
} else {
// User is active — stop mining if we auto-started it
if (idle_mining_active_) {
idle_mining_active_ = false;
if (isPool) {
if (xmrig_manager_ && xmrig_manager_->isRunning())
stopPoolMining();
} else {
if (state_.mining.generate)
stopMining();
}
DEBUG_LOGF("[App] Idle mining stopped — user returned\n");
}
DEBUG_LOGF("[App] Idle mining stopped — user returned\n");
}
}
}