feat(daemon-update): two-pane version picker (versions left, detail right)

Redesign the Update Node dialog to mirror the Manage-Portfolio editor: the list
of node versions on the LEFT (with latest / installed / pre-release badges +
date), the selected version's detail on the RIGHT — status vs installed, release
notes (checksum table + markdown heading markers stripped), the verify/downgrade
note, and the install action (Download & install / Install this version /
Reinstall). One Close in the footer.

The dialog now fetches the full release list up front (startListReleases) so the
picker is populated immediately; Downloading/Verifying/Done/Failed render in the
right pane with the list still visible. Layout is GetContentRegionAvail-based so
it adapts to a viewport-capped card (verified 100% + 150%, dark + light).

Adds a sweep seam (sweepSeed/sweepClose) + a modal-daemon-update sweep surface
seeded with fake releases for offline visual verification. Adversarially
reviewed (3 lenses); fixed the real findings — live list was never populated
from getReleases() (only the sweep seeded it), defensive s_rows bounds in the
detail pane, notes box dropped when the pane is too short so the install button
stays visible, and a badge-overrun guard for long tags. DPI "findings" were the
recurring false positives (LegacySize/spacing/GetFrameHeight are all dp-scaled).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-10 16:28:33 -05:00
parent e6bea8eb04
commit c6624913de
3 changed files with 343 additions and 101 deletions

View File

@@ -19,6 +19,7 @@
#include "ui/sidebar.h"
#include "ui/windows/send_tab.h"
#include "ui/windows/wallets_dialog.h"
#include "ui/windows/daemon_download_dialog.h"
#include "util/platform.h"
#include "wallet/wallet_capabilities.h"
@@ -437,6 +438,35 @@ void App::buildSweepCatalog()
[](App& a) { a.console_tab_.sweepSetCommandsPopup(true); },
[](App& a) { a.console_tab_.sweepSetCommandsPopup(false); });
// Daemon updater — the two-pane version picker (versions left, selected-version detail right).
// Seeds fake releases so the offline sweep renders it without a network fetch / live updater.
add("modal-daemon-update", ui::NavPage::Settings,
[](App& a) {
auto mk = [](const char* tag, const char* name, const char* date, const char* body, bool pre) {
util::DaemonRelease r; r.ok = true; r.tag = tag; r.name = name; r.body = body;
r.prerelease = pre; r.publishedAt = std::string(date) + "T10:00:00Z";
util::DaemonReleaseAsset as;
as.name = std::string("dragonx-") + tag + "-linux-amd64.zip";
as.downloadUrl = "https://git.dragonx.is/" + as.name; as.size = 43000000;
r.assets.push_back(as);
return r;
};
std::vector<util::DaemonRelease> rels;
rels.push_back(mk("v1.0.4", "DragonX v1.0.4", "2026-06-28",
"## What's new\n- Faster initial block sync\n- BIP39 seed-phrase wallet support\n"
"- Mempool handling fixes and lower memory use\n\n## Checksums\n| File | SHA-256 |\n"
"|---|---|\n| dragonx-v1.0.4-linux-amd64.zip | `ab12cd34` |\n", false));
rels.push_back(mk("v1.0.3", "DragonX v1.0.3", "2026-05-14",
"## Notes\n- Stability improvements\n- RPC fixes\n", false));
rels.push_back(mk("v1.0.2", "DragonX v1.0.2", "2026-04-02",
"- First tagged mainnet build\n", false));
rels.push_back(mk("v1.1.0-rc1", "DragonX v1.1.0-rc1", "2026-07-01",
"Release candidate for the 1.1.0 series. Testing only.\n", true));
ui::DaemonUpdateDialog::sweepSeed(&a, rels, util::DaemonUpdater::State::ReleaseList,
"v1.0.3-dc45e7d90");
},
[](App&) { ui::DaemonUpdateDialog::sweepClose(); });
// In-app folder picker (Wallets → Scan another folder). Populate a small demo tree so the
// list shows sub-folders + wallet files, then open the wallets dialog + the picker over it.
add("modal-folder-picker", ui::NavPage::Settings,