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

@@ -147,7 +147,14 @@ void ImportKeyDialog::render(App* app)
if (material::StyledButton(TR("paste_from_clipboard"), ImVec2(0,0), S.resolveFont(importBtn.font))) {
const char* clipboard = ImGui::GetClipboardText();
if (clipboard) {
strncpy(s_key_input, clipboard, sizeof(s_key_input) - 1);
std::string trimmed(clipboard);
while (!trimmed.empty() && (trimmed.front() == ' ' || trimmed.front() == '\t' ||
trimmed.front() == '\n' || trimmed.front() == '\r'))
trimmed.erase(trimmed.begin());
while (!trimmed.empty() && (trimmed.back() == ' ' || trimmed.back() == '\t' ||
trimmed.back() == '\n' || trimmed.back() == '\r'))
trimmed.pop_back();
snprintf(s_key_input, sizeof(s_key_input), "%s", trimmed.c_str());
}
}
@@ -156,6 +163,43 @@ void ImportKeyDialog::render(App* app)
s_key_input[0] = '\0';
}
// Key validation indicator
if (s_key_input[0] != '\0') {
auto keys = splitKeys(s_key_input);
int zCount = 0, tCount = 0, unknownCount = 0;
for (const auto& key : keys) {
std::string kt = detectKeyType(key);
if (kt == "z-spending") zCount++;
else if (kt == "t-privkey") tCount++;
else unknownCount++;
}
if (zCount > 0 || tCount > 0) {
ImGui::PushFont(material::Type().iconSmall());
material::Type().textColored(material::TypeStyle::Caption, material::Success(), ICON_MD_CHECK_CIRCLE);
ImGui::PopFont();
ImGui::SameLine(0, 2.0f);
char validBuf[128];
if (zCount > 0 && tCount > 0)
snprintf(validBuf, sizeof(validBuf), "%d shielded, %d transparent key(s)", zCount, tCount);
else if (zCount > 0)
snprintf(validBuf, sizeof(validBuf), "%d shielded key(s)", zCount);
else
snprintf(validBuf, sizeof(validBuf), "%d transparent key(s)", tCount);
material::Type().textColored(material::TypeStyle::Caption, material::Success(), validBuf);
if (unknownCount > 0) {
ImGui::SameLine();
snprintf(validBuf, sizeof(validBuf), "(%d unrecognized)", unknownCount);
material::Type().textColored(material::TypeStyle::Caption, material::Error(), validBuf);
}
} else if (unknownCount > 0) {
ImGui::PushFont(material::Type().iconSmall());
material::Type().textColored(material::TypeStyle::Caption, material::Error(), ICON_MD_ERROR);
ImGui::PopFont();
ImGui::SameLine(0, 2.0f);
material::Type().textColored(material::TypeStyle::Caption, material::Error(), "Unrecognized key format");
}
}
ImGui::Spacing();
// Rescan options