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 {
|
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()
|
try await loadWalletInformation()
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadWalletInformation() async throws {
|
func loadWalletInformation() async throws {
|
||||||
try await loadBalance()
|
// Implementation note: Get all needed info first, then atomically set the new state.
|
||||||
try await loadTransactionList()
|
// This is important to avoid re-rendering the view twice (waste),
|
||||||
}
|
// and to avoid refreshable tasks to be cancelled before updating everything
|
||||||
|
|
||||||
func loadBalance() async throws {
|
|
||||||
let balance = try await fetchBalance()
|
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: "")
|
let transactions = try await fetchTransactions(from: nil, until: nil, limit: 50, offset: 0, unpaid: false, type: "")
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
|
self.balance = balance
|
||||||
self.transactions = transactions
|
self.transactions = transactions
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ struct WalletView: View {
|
|||||||
@ObservedObject var model: WalletModel
|
@ObservedObject var model: WalletModel
|
||||||
@ObservedObject var settings: UserSettingsStore
|
@ObservedObject var settings: UserSettingsStore
|
||||||
@State private var showBalance: Bool = false
|
@State private var showBalance: Bool = false
|
||||||
@State private var walletRefreshTask: Task<Void, Never>? = nil
|
|
||||||
|
|
||||||
init(damus_state: DamusState, model: WalletModel? = nil) {
|
init(damus_state: DamusState, model: WalletModel? = nil) {
|
||||||
self.damus_state = damus_state
|
self.damus_state = damus_state
|
||||||
@@ -104,11 +103,11 @@ struct WalletView: View {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.onAppear() {
|
.task {
|
||||||
self.refreshWalletInformation()
|
await self.refreshWalletInformation()
|
||||||
}
|
}
|
||||||
.refreshable {
|
.refreshable {
|
||||||
self.refreshWalletInformation()
|
await self.refreshWalletInformation()
|
||||||
}
|
}
|
||||||
.sheet(isPresented: $show_settings, onDismiss: { self.show_settings = false }) {
|
.sheet(isPresented: $show_settings, onDismiss: { self.show_settings = false }) {
|
||||||
ScrollView {
|
ScrollView {
|
||||||
@@ -126,10 +125,7 @@ struct WalletView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@MainActor
|
func refreshWalletInformation() async {
|
||||||
func refreshWalletInformation() {
|
|
||||||
walletRefreshTask?.cancel()
|
|
||||||
walletRefreshTask = Task {
|
|
||||||
do {
|
do {
|
||||||
try await self.model.refreshWalletInformation()
|
try await self.model.refreshWalletInformation()
|
||||||
}
|
}
|
||||||
@@ -142,7 +138,6 @@ struct WalletView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@MainActor
|
@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")
|
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