Refactor app services and stabilize refresh/UI flows

- Add refresh scheduler and network refresh service boundaries for typed
  refresh results, ordered RPC collectors, applicators, and price parsing.
- Add daemon lifecycle and wallet security workflow helpers while preserving
  App-owned command RPC, decrypt, cancellation, and UI handoff behavior.
- Split balance, console, mining, amount formatting, and async task logic into
  focused modules with expanded Phase 4 test coverage.
- Fix market price loading by triggering price refresh immediately, avoiding
  queue-pressure drops, tracking loading/error state, and adding translations.
- Polish send, explorer, peers, settings, theme/schema, and related tab UI.
- Replace checked-in generated language headers with build-generated resources.
- Document the cleanup audit, UI static-state guidance, and architecture updates.
This commit is contained in:
dan_s
2026-04-29 12:47:57 -05:00
parent 9e1b1397ad
commit d684db446e
95 changed files with 8776 additions and 37563 deletions

View File

@@ -219,14 +219,7 @@ static void RenderSourceDropdown(App* app, float width) {
// Auto-select the address with the largest balance on first load
if (!s_auto_selected && app->isConnected() && !state.addresses.empty()) {
int bestIdx = -1;
double bestBal = 0.0;
for (size_t i = 0; i < state.addresses.size(); i++) {
if (state.addresses[i].balance > bestBal && state.addresses[i].isSpendable()) {
bestBal = state.addresses[i].balance;
bestIdx = static_cast<int>(i);
}
}
int bestIdx = bestSpendableAddressIndex(state.addresses);
if (bestIdx >= 0) {
s_selected_from_idx = bestIdx;
snprintf(s_from_address, sizeof(s_from_address), "%s",
@@ -260,16 +253,7 @@ static void RenderSourceDropdown(App* app, float width) {
ImGui::TextDisabled("%s", TR("no_addresses_available"));
} else {
// Sort by balance descending, only show spendable addresses with balance
std::vector<size_t> sortedIdx;
sortedIdx.reserve(state.addresses.size());
for (size_t i = 0; i < state.addresses.size(); i++) {
if (state.addresses[i].balance > 0 && state.addresses[i].isSpendable())
sortedIdx.push_back(i);
}
std::sort(sortedIdx.begin(), sortedIdx.end(),
[&](size_t a, size_t b) {
return state.addresses[a].balance > state.addresses[b].balance;
});
std::vector<size_t> sortedIdx = sortedSpendableAddressIndices(state.addresses);
if (sortedIdx.empty()) {
ImGui::TextDisabled("%s", TR("send_no_balance"));
@@ -731,14 +715,16 @@ void RenderSendConfirmPopup(App* app) {
Type().textColored(TypeStyle::Overline, OnSurfaceMedium(), TR("send_amount_details"));
ImVec2 cMin = ImGui::GetCursorScreenPos();
float cH = std::max(schema::UI().drawElement("tabs.send", "confirm-amount-card-min-height").size, schema::UI().drawElement("tabs.send", "confirm-amount-card-height").size * popVs);
float rowStep = std::max(schema::UI().drawElement("tabs.send", "confirm-row-step-min").size, schema::UI().drawElement("tabs.send", "confirm-row-step").size * popVs);
float configuredH = std::max(schema::UI().drawElement("tabs.send", "confirm-amount-card-min-height").size, schema::UI().drawElement("tabs.send", "confirm-amount-card-height").size * popVs);
float contentH = Layout::spacingMd() * 2.0f + capFont->LegacySize * 2.0f + sub1->LegacySize + rowStep * 2.0f;
float cH = std::max(configuredH, contentH);
ImVec2 cMax(cMin.x + popW, cMin.y + cH);
GlassPanelSpec gs; gs.rounding = popGlassRound;
DrawGlassPanel(popDl, cMin, cMax, gs);
float cx = cMin.x + Layout::spacingMd() + Layout::spacingXs();
float cy = cMin.y + Layout::spacingSm() + Layout::spacingXs();
float rowStep = std::max(schema::UI().drawElement("tabs.send", "confirm-row-step-min").size, schema::UI().drawElement("tabs.send", "confirm-row-step").size * popVs);
float cx = cMin.x + Layout::spacingLg();
float cy = cMin.y + Layout::spacingMd();
popDl->AddText(capFont, capFont->LegacySize, ImVec2(cx, cy), OnSurfaceMedium(), TR("send_amount"));
snprintf(buf, sizeof(buf), "%.8f %s", s_amount, DRAGONX_TICKER);
@@ -756,11 +742,11 @@ void RenderSendConfirmPopup(App* app) {
snprintf(buf, sizeof(buf), "$%.6f", s_fee * market.price_usd);
popDl->AddText(capFont, capFont->LegacySize, ImVec2(cx + usdX, cy), OnSurfaceDisabled(), buf);
}
cy += Layout::spacingSm();
popDl->AddLine(ImVec2(cx, cy + Layout::spacingMd()),
ImVec2(cx + popW - Layout::spacingXl(), cy + Layout::spacingMd()),
cy += rowStep * 0.5f;
popDl->AddLine(ImVec2(cx, cy),
ImVec2(cMax.x - Layout::spacingLg(), cy),
ImGui::GetColorU32(Divider()), S.drawElement("tabs.send", "confirm-divider-thickness").size);
cy += rowStep;
cy += rowStep * 0.5f;
popDl->AddText(sub1, sub1->LegacySize, ImVec2(cx, cy), OnSurfaceMedium(), TR("send_total"));
snprintf(buf, sizeof(buf), "%.8f %s", total, DRAGONX_TICKER);