Fix wallet view hanging on loading placeholder indefinitely
Resolves a race condition in wallet data fetching that caused views to hang on loading placeholders. The issue occurred due to: 1. Multiple state updates triggering view re-renders mid-fetch 2. Refreshable tasks getting cancelled before completion Changes: - Remove premature state reset in refreshWalletInformation() - Atomically update balance and transactions together after fetching - Replace onAppear + manual task cancellation with SwiftUI .task modifier - Simplify refresh flow to use proper async/await without explicit task management This ensures the wallet view completes data loading in a single atomic operation, preventing intermediate loading states from persisting. Closes: https://github.com/damus-io/damus/issues/2999 Changelog-Fixed: Wallet view no longer hangs on loading placeholder Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This commit is contained in:
@@ -122,25 +122,20 @@ class WalletModel: ObservableObject {
|
||||
|
||||
|
||||
func refreshWalletInformation() async throws {
|
||||
await self.resetWalletStateInformation()
|
||||
// Implementation note: Do not reset wallet information here
|
||||
// This is important to avoid re-rendering the view twice (waste),
|
||||
// and to avoid refreshable tasks to be cancelled before updating everything
|
||||
try await loadWalletInformation()
|
||||
}
|
||||
|
||||
func loadWalletInformation() async throws {
|
||||
try await loadBalance()
|
||||
try await loadTransactionList()
|
||||
}
|
||||
|
||||
func loadBalance() async throws {
|
||||
// Implementation note: Get all needed info first, then atomically set the new state.
|
||||
// This is important to avoid re-rendering the view twice (waste),
|
||||
// and to avoid refreshable tasks to be cancelled before updating everything
|
||||
let balance = try await fetchBalance()
|
||||
DispatchQueue.main.async {
|
||||
self.balance = balance
|
||||
}
|
||||
}
|
||||
|
||||
func loadTransactionList() async throws {
|
||||
let transactions = try await fetchTransactions(from: nil, until: nil, limit: 50, offset: 0, unpaid: false, type: "")
|
||||
DispatchQueue.main.async {
|
||||
self.balance = balance
|
||||
self.transactions = transactions
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@ struct WalletView: View {
|
||||
@ObservedObject var model: WalletModel
|
||||
@ObservedObject var settings: UserSettingsStore
|
||||
@State private var showBalance: Bool = false
|
||||
@State private var walletRefreshTask: Task<Void, Never>? = nil
|
||||
|
||||
init(damus_state: DamusState, model: WalletModel? = nil) {
|
||||
self.damus_state = damus_state
|
||||
@@ -104,11 +103,11 @@ struct WalletView: View {
|
||||
)
|
||||
}
|
||||
}
|
||||
.onAppear() {
|
||||
self.refreshWalletInformation()
|
||||
.task {
|
||||
await self.refreshWalletInformation()
|
||||
}
|
||||
.refreshable {
|
||||
self.refreshWalletInformation()
|
||||
await self.refreshWalletInformation()
|
||||
}
|
||||
.sheet(isPresented: $show_settings, onDismiss: { self.show_settings = false }) {
|
||||
ScrollView {
|
||||
@@ -126,10 +125,7 @@ struct WalletView: View {
|
||||
}
|
||||
}
|
||||
|
||||
@MainActor
|
||||
func refreshWalletInformation() {
|
||||
walletRefreshTask?.cancel()
|
||||
walletRefreshTask = Task {
|
||||
func refreshWalletInformation() async {
|
||||
do {
|
||||
try await self.model.refreshWalletInformation()
|
||||
}
|
||||
@@ -142,7 +138,6 @@ struct WalletView: View {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@MainActor
|
||||
let test_wallet_connect_url = WalletConnectURL(pubkey: test_pubkey, relay: .init("wss://relay.damus.io")!, keypair: test_damus_state.keypair.to_full()!, lud16: "jb55@sendsats.com")
|
||||
|
||||
Reference in New Issue
Block a user