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/Views/Settings/WalletTransactionsView.swift | 75 ++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 Rune/Views/Settings/WalletTransactionsView.swift (limited to 'Rune/Views/Settings/WalletTransactionsView.swift') diff --git a/Rune/Views/Settings/WalletTransactionsView.swift b/Rune/Views/Settings/WalletTransactionsView.swift new file mode 100644 index 0000000..f0106de --- /dev/null +++ b/Rune/Views/Settings/WalletTransactionsView.swift @@ -0,0 +1,75 @@ +import SwiftUI + +struct WalletTransactionsView: View { + @ObservedObject var viewModel: WalletViewModel + let client: NjallaClient + + var body: some View { + List { + if let errorMessage = viewModel.transactionsErrorMessage { + Section { + InlineErrorView(message: errorMessage, retryTitle: "Retry Transactions") { + Task { + await viewModel.loadTransactions(client: client) + } + } + .listRowInsets(EdgeInsets(top: 8, leading: 16, bottom: 8, trailing: 16)) + } + } + + if viewModel.isLoadingTransactions && viewModel.transactions.isEmpty { + Section { + HStack { + Spacer() + ProgressView("Loading Transactions") + Spacer() + } + } + } else if viewModel.transactions.isEmpty { + Section { + ContentUnavailableView( + "No Transactions", + systemImage: "eurosign.circle", + description: Text("No wallet transactions were returned for this account.") + ) + } + } else { + ForEach(viewModel.transactions) { transaction in + NavigationLink { + WalletPaymentDetailView(transactionID: transaction.id, viewModel: viewModel, client: client) + } label: { + VStack(alignment: .leading, spacing: 4) { + Text(transaction.type ?? "Transaction") + .font(.headline) + Text(transactionDateText(transaction)) + .font(.subheadline) + .foregroundStyle(.secondary) + if let amount = transaction.amount { + Text("Amount: €\(amount)") + .font(.subheadline) + .foregroundStyle(.secondary) + } + } + .padding(.vertical, 4) + } + } + } + } + .listStyle(.insetGrouped) + .navigationTitle("Transactions") + .navigationBarTitleDisplayMode(.inline) + .task { + await viewModel.loadTransactions(client: client) + } + .refreshable { + await viewModel.loadTransactions(client: client) + } + } + + private func transactionDateText(_ transaction: WalletTransaction) -> String { + if let date = transaction.date, !date.isEmpty { + return date + } + return "ID: \(transaction.id)" + } +} -- cgit v1.2.3