feat(updater): in-app dragonxd updater + browse-all-releases
Add a full-node daemon updater (util/DaemonUpdater + daemon_download_dialog) reachable from Settings -> NODE & SECURITY: downloads/verifies (SHA-256 + enforced ed25519 signature) and atomically installs the latest dragonxd from the project Gitea, with a "Restart daemon now" step. Add a shared "Browse all releases..." picker (release_list_view) to both the miner and daemon updaters so users can pin older/pre-release builds. Pure no-I/O cores (daemon_updater_core / xmrig_updater_core) are unit-tested; sign-daemon-release.sh signs release archives offline. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -11,6 +11,7 @@
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "../../app.h"
|
||||
#include "../../config/settings.h"
|
||||
@@ -21,6 +22,7 @@
|
||||
#include "../material/type.h"
|
||||
#include "../material/colors.h"
|
||||
#include "../theme.h"
|
||||
#include "release_list_view.h"
|
||||
#include "imgui.h"
|
||||
|
||||
namespace dragonx {
|
||||
@@ -33,8 +35,11 @@ public:
|
||||
s_app = app;
|
||||
s_open = true;
|
||||
s_persisted = false;
|
||||
s_installed_tag = app->settings() ? app->settings()->getXmrigVersion() : std::string();
|
||||
s_rows.clear();
|
||||
s_releases.clear();
|
||||
s_updater = std::make_unique<util::XmrigUpdater>();
|
||||
s_updater->startCheck(app->settings() ? app->settings()->getXmrigVersion() : std::string());
|
||||
s_updater->startCheck(s_installed_tag);
|
||||
}
|
||||
|
||||
static bool isOpen() { return s_open; }
|
||||
@@ -54,6 +59,8 @@ public:
|
||||
case St::UpToDate:
|
||||
case St::UpdateAvailable: renderPrompt(dp, p); break;
|
||||
case St::Unavailable: renderUnavailable(dp, p); break;
|
||||
case St::Listing: renderListing(dp, p); break;
|
||||
case St::ReleaseList: renderReleaseList(dp, p); break;
|
||||
case St::Downloading:
|
||||
case St::Verifying:
|
||||
case St::Extracting: renderProgress(dp, p); break;
|
||||
@@ -121,9 +128,50 @@ private:
|
||||
installAction(TR("xmrig_reinstall"));
|
||||
}
|
||||
ImGui::Spacing();
|
||||
// Browse all releases (pre-releases / older versions).
|
||||
if (TactileButton(TR("xmrig_browse_releases"), ImVec2(fullW(), 0))) {
|
||||
s_rows.clear();
|
||||
s_updater->startListReleases();
|
||||
}
|
||||
ImGui::Spacing();
|
||||
if (TactileButton(TR("close"), ImVec2(fullW(), 0))) s_open = false;
|
||||
}
|
||||
|
||||
static void renderListing(float, const Progress&) {
|
||||
using namespace material;
|
||||
Type().text(TypeStyle::Body2, TR("xmrig_loading_releases"));
|
||||
}
|
||||
|
||||
static void renderReleaseList(float dp, const Progress&) {
|
||||
using namespace material;
|
||||
// Snapshot + build rows once per listing (not every frame). Cleared on browse / show.
|
||||
if (s_rows.empty()) {
|
||||
s_releases = s_updater->getReleases();
|
||||
const std::string token = util::currentXmrigPlatformToken();
|
||||
s_rows.reserve(s_releases.size());
|
||||
for (const auto& r : s_releases) {
|
||||
ReleaseRow row;
|
||||
row.tag = r.tag;
|
||||
row.title = r.name;
|
||||
row.date = r.publishedAt.size() >= 10 ? r.publishedAt.substr(0, 10) : r.publishedAt;
|
||||
row.prerelease = r.prerelease;
|
||||
row.hasAsset = util::selectXmrigAsset(r, token) >= 0;
|
||||
row.installed = !s_installed_tag.empty() && r.tag == s_installed_tag;
|
||||
s_rows.push_back(std::move(row));
|
||||
}
|
||||
}
|
||||
// Can't replace a running miner binary — disable installs while mining (TOCTOU guard).
|
||||
const char* disabledNote = s_app->isPoolMinerRunning() ? TR("xmrig_stop_mining_first") : nullptr;
|
||||
bool back = false;
|
||||
const int idx = RenderReleaseList(s_rows, dp, &back, disabledNote);
|
||||
if (back) { s_rows.clear(); s_updater->startCheck(s_installed_tag); return; }
|
||||
if (idx >= 0 && !s_app->isPoolMinerRunning() && idx < static_cast<int>(s_releases.size())) {
|
||||
const util::XmrigRelease rel = s_releases[idx];
|
||||
s_rows.clear();
|
||||
s_updater->startInstallRelease(resources::getDaemonDirectory(), rel);
|
||||
}
|
||||
}
|
||||
|
||||
static void renderProgress(float dp, const Progress& p) {
|
||||
using namespace material;
|
||||
const char* title = p.state == St::Downloading ? TR("xmrig_downloading")
|
||||
@@ -180,6 +228,9 @@ private:
|
||||
|
||||
static inline bool s_open = false;
|
||||
static inline bool s_persisted = false;
|
||||
static inline std::string s_installed_tag;
|
||||
static inline std::vector<ReleaseRow> s_rows; // built once per listing (UI rows)
|
||||
static inline std::vector<util::XmrigRelease> s_releases; // matching releases (install by index)
|
||||
static inline App* s_app = nullptr;
|
||||
static inline std::unique_ptr<util::XmrigUpdater> s_updater;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user