feat(request,balance): Request-Payment create-address empty-state + tx empty states

- Request-Payment no longer dead-ends with no shielded address: it shows a hint
  and a "Create a shielded address" button (auto-selecting the new address), and
  labels address entries with their contact/wallet names.
- The balance "Recent transactions" empty area uses a proper empty-state and now
  distinguishes "still loading / syncing" from "no transactions yet" instead of a
  dim one-liner that also showed mid-sync.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-10-18 22:50:30 -05:00
co-authored by Claude Opus 4.8
parent f2d9590058
commit 3f127f9b62
2 changed files with 81 additions and 20 deletions
+21 -1
View File
@@ -1057,7 +1057,27 @@ void RenderSharedRecentTx(App* app, float recentH, float availW, float hs, float
int count = std::min({4, maxRows, (int)txs.size()}); // show only the most recent (state.transactions is newest-first)
if (count == 0) {
Type().textColored(TypeStyle::Caption, OnSurfaceDisabled(), TR("no_transactions_yet"));
const bool roomForIcon = ImGui::GetContentRegionAvail().y >= 100.0f * dp;
if (!app->isConnected()) {
// Disconnected: not "empty" and not "loading" — keep a plain caption.
Type().textColored(TypeStyle::Caption, OnSurfaceDisabled(),
TR(app->isLiteBuild() ? "lite_no_wallet" : "not_connected"));
} else {
const std::string txLoadingText = app->transactionRefreshProgressText();
// In lite, transactionRefreshProgressText() is empty and last_tx_update is stamped differently,
// so treat only an active sync as "loading" there.
const bool loadingOrSyncing = !txLoadingText.empty() ||
(state.sync.syncing && !state.sync.isSynced()) ||
(!app->isLiteBuild() && state.last_tx_update == 0);
if (loadingOrSyncing) {
char lbuf[192];
const char* base = !txLoadingText.empty() ? txLoadingText.c_str() : TR("loading_transactions");
snprintf(lbuf, sizeof(lbuf), "%s%s", base, material::LoadingDots());
material::DrawEmptyState(roomForIcon ? ICON_MD_HOURGLASS_EMPTY : nullptr, lbuf);
} else {
material::DrawEmptyState(roomForIcon ? ICON_MD_RECEIPT_LONG : nullptr, TR("no_transactions_yet"));
}
}
} else {
ImDrawList* dl = ImGui::GetWindowDrawList();
ImFont* capFont = Type().caption();