From 5dcfe0f147c7871eaf5f3a88bd9e9fded38d4633 Mon Sep 17 00:00:00 2001 From: Christian Cleberg Date: Mon, 13 Apr 2026 22:37:22 -0500 Subject: v1.2.0 domain management and wallet expansion Complete v1.1-aligned domain flows with forwards and glue CRUD, improve API payload resilience, and add wallet transaction/payment views. Harden error handling and UX states across domain screens, remove out-of-scope DNSSEC/renewal record flows for now, and keep auth/session behavior aligned with token-based usage. --- Rune/ViewModels/WalletViewModel.swift | 65 +++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 Rune/ViewModels/WalletViewModel.swift (limited to 'Rune/ViewModels/WalletViewModel.swift') diff --git a/Rune/ViewModels/WalletViewModel.swift b/Rune/ViewModels/WalletViewModel.swift new file mode 100644 index 0000000..cbe0538 --- /dev/null +++ b/Rune/ViewModels/WalletViewModel.swift @@ -0,0 +1,65 @@ +import Combine +import Foundation + +@MainActor +final class WalletViewModel: ObservableObject { + @Published private(set) var transactions: [WalletTransaction] = [] + @Published private(set) var selectedPayment: WalletPayment? + @Published private(set) var isLoadingTransactions = false + @Published private(set) var isLoadingPayment = false + @Published var transactionsErrorMessage: String? + @Published var paymentErrorMessage: String? + + func reset() { + transactions = [] + selectedPayment = nil + isLoadingTransactions = false + isLoadingPayment = false + transactionsErrorMessage = nil + paymentErrorMessage = nil + } + + func loadTransactions(client: NjallaClient) async { + guard !isLoadingTransactions else { return } + + isLoadingTransactions = true + defer { + isLoadingTransactions = false + } + + do { + transactions = try await client.listTransactions().sorted { + ($0.date ?? "", $0.id) > ($1.date ?? "", $1.id) + } + transactionsErrorMessage = nil + } catch is CancellationError { + return + } catch { + if (error as? URLError)?.code == .cancelled { + return + } + transactionsErrorMessage = error.userFacingMessage + } + } + + func loadPayment(id: String, client: NjallaClient) async { + guard !isLoadingPayment else { return } + + isLoadingPayment = true + defer { + isLoadingPayment = false + } + + do { + selectedPayment = try await client.getPayment(id: id) + paymentErrorMessage = nil + } catch is CancellationError { + return + } catch { + if (error as? URLError)?.code == .cancelled { + return + } + paymentErrorMessage = error.userFacingMessage + } + } +} -- cgit v1.2.3