gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-taler-ios] 29/54: Model cleanup


From: gnunet
Subject: [taler-taler-ios] 29/54: Model cleanup
Date: Fri, 30 Jun 2023 22:34:01 +0200

This is an automated email from the git hooks/post-receive script.

marc-stibane pushed a commit to branch master
in repository taler-ios.

commit 99d5f1ac7ddb4bc76ae9ed398a6af463bdfef4d1
Author: Marc Stibane <marc@taler.net>
AuthorDate: Tue Jun 27 14:49:53 2023 +0200

    Model cleanup
---
 TalerWallet1/Model/Model+Settings.swift            |  56 +++++-----
 TalerWallet1/Model/Model+Transactions.swift        |  57 +++++-----
 TalerWallet1/Model/WalletModel.swift               |   7 +-
 TalerWallet1/Views/Balances/BalancesListView.swift |   6 +
 .../Views/Balances/BalancesSectionView.swift       |  16 +--
 TalerWallet1/Views/Payment/PaymentURIView.swift    | 124 +++++++++++++++------
 6 files changed, 160 insertions(+), 106 deletions(-)

diff --git a/TalerWallet1/Model/Model+Settings.swift 
b/TalerWallet1/Model/Model+Settings.swift
index 188d4a0..a085cb5 100644
--- a/TalerWallet1/Model/Model+Settings.swift
+++ b/TalerWallet1/Model/Model+Settings.swift
@@ -13,35 +13,6 @@ fileprivate let DEMO_BANKAPIBASEURL  = DEMOBANK + 
"/demobanks/default/access-api
 fileprivate let DEMO_MERCHANTBASEURL = DEMOBACKEND
 fileprivate let DEMO_MERCHANTAUTHTOKEN = "secret-token:sandbox"
 
-// MARK: -
-extension WalletModel {
-    @MainActor func loadTestKudosM()
-      async throws {          // M for MainActor
-        let amount = Amount(currency: DEMOCURRENCY, integer: 11, fraction: 0)
-        let request = WalletBackendWithdrawTestBalance(amount: amount,
-                                                  bankBaseUrl: 
DEMO_BANKBASEURL,
-                                              exchangeBaseUrl: 
DEMO_EXCHANGEBASEURL,
-                                         bankAccessApiBaseUrl: 
DEMO_BANKAPIBASEURL)
-        let response = try await sendRequest(request, ASYNCDELAY)
-        symLog?.log("received: \(response)")
-    }
-
-    @MainActor func runIntegrationTestM(newVersion: Bool)
-      async throws {               // M for MainActor
-        let amountW = Amount(currency: DEMOCURRENCY, integer: 3, fraction: 0)
-        let amountS = Amount(currency: DEMOCURRENCY, integer: 1, fraction: 0)
-        let request = WalletBackendRunIntegration(newVersion: newVersion,
-                                            amountToWithdraw: amountW,
-                                               amountToSpend: amountS,
-                                                 bankBaseUrl: 
DEMO_BANKAPIBASEURL,
-                                        bankAccessApiBaseUrl: 
DEMO_BANKAPIBASEURL,
-                                             exchangeBaseUrl: 
DEMO_EXCHANGEBASEURL,
-                                             merchantBaseUrl: 
DEMO_MERCHANTBASEURL,
-                                           merchantAuthToken: 
DEMO_MERCHANTAUTHTOKEN)
-        let _ = try await sendRequest(request, ASYNCDELAY)
-        symLog?.log("runIntegrationTest finished")
-    }
-}
 // MARK: -
 /// A request to add a test balance to the wallet.
 fileprivate struct WalletBackendWithdrawTestBalance: 
WalletBackendFormattedRequest {
@@ -64,6 +35,17 @@ fileprivate struct WalletBackendWithdrawTestBalance: 
WalletBackendFormattedReque
         var bankAccessApiBaseUrl: String
     }
 }
+extension WalletModel {
+    @MainActor func loadTestKudosM()
+    async throws {          // M for MainActor
+        let amount = Amount(currency: DEMOCURRENCY, integer: 11, fraction: 0)
+        let request = WalletBackendWithdrawTestBalance(amount: amount,
+                                                       bankBaseUrl: 
DEMO_BANKBASEURL,
+                                                       exchangeBaseUrl: 
DEMO_EXCHANGEBASEURL,
+                                                       bankAccessApiBaseUrl: 
DEMO_BANKAPIBASEURL)
+        let response = try await sendRequest(request, ASYNCDELAY)
+    }
+} // loadTestKudosM()
 // MARK: -
 /// A request to add a test balance to the wallet.
 fileprivate struct WalletBackendRunIntegration: WalletBackendFormattedRequest {
@@ -100,3 +82,19 @@ fileprivate struct WalletBackendRunIntegration: 
WalletBackendFormattedRequest {
         var merchantAuthToken: String
     }
 }
+extension WalletModel {
+    @MainActor func runIntegrationTestM(newVersion: Bool)
+    async throws {               // M for MainActor
+        let amountW = Amount(currency: DEMOCURRENCY, integer: 3, fraction: 0)
+        let amountS = Amount(currency: DEMOCURRENCY, integer: 1, fraction: 0)
+        let request = WalletBackendRunIntegration(newVersion: newVersion,
+                                                  amountToWithdraw: amountW,
+                                                  amountToSpend: amountS,
+                                                  bankBaseUrl: 
DEMO_BANKAPIBASEURL,
+                                                  bankAccessApiBaseUrl: 
DEMO_BANKAPIBASEURL,
+                                                  exchangeBaseUrl: 
DEMO_EXCHANGEBASEURL,
+                                                  merchantBaseUrl: 
DEMO_MERCHANTBASEURL,
+                                                  merchantAuthToken: 
DEMO_MERCHANTAUTHTOKEN)
+        let _ = try await sendRequest(request, ASYNCDELAY)
+    }
+} // runIntegrationTestM()
diff --git a/TalerWallet1/Model/Model+Transactions.swift 
b/TalerWallet1/Model/Model+Transactions.swift
index f6bb23c..39e9842 100644
--- a/TalerWallet1/Model/Model+Transactions.swift
+++ b/TalerWallet1/Model/Model+Transactions.swift
@@ -72,6 +72,17 @@ struct DeleteTransaction: WalletBackendFormattedRequest {
         var transactionId: String
     }
 }
+/// A request to delete a wallet transaction by ID.
+struct FailTransaction: WalletBackendFormattedRequest {
+    struct Response: Decodable {}
+    func operation() -> String { return "failTransaction" }
+    func args() -> Args { return Args(transactionId: transactionId) }
+
+    var transactionId: String
+    struct Args: Encodable {
+        var transactionId: String
+    }
+}
 /// A request to suspend a wallet transaction by ID.
 struct SuspendTransaction: WalletBackendFormattedRequest {
     struct Response: Decodable {}
@@ -97,69 +108,51 @@ struct ResumeTransaction: WalletBackendFormattedRequest {
 // MARK: -
 extension WalletModel {
     /// ask wallet-core for its list of transactions filtered by searchString
-    func fetchTransactionsT(currency: String? = nil, searchString: String? = 
nil)
+    func transactionsT(currency: String? = nil, searchString: String? = nil)
     async -> [Transaction] {                                          // might 
be called from a background thread itself
         do {
             let request = GetTransactions(currency: currency, search: 
searchString)
-            logger.info("getTransactions")
             let response = try await sendRequest(request, ASYNCDELAY)
             return response.transactions
         } catch {
-            logger.error("getTransactions failed: \(error)")
             return []
         }
     }
     /// fetch transactions from Wallet-Core. No networking involved
-    @MainActor func fetchTransactionsM(currency: String? = nil, searchString: 
String? = nil)
+    @MainActor func transactionsMA(currency: String? = nil, searchString: 
String? = nil)
     async -> [Transaction] {    // M for MainActor
-        return await fetchTransactionsT(currency: currency, searchString: 
searchString)
+        return await transactionsT(currency: currency, searchString: 
searchString)
     }
 
-    func abortTransactionT(transactionId: String)
-      async throws {          // might be called from a background thread 
itself
+    /// abort the specified transaction from Wallet-Core. No networking 
involved
+    func abortTransaction(transactionId: String) async throws {
         let request = AbortTransaction(transactionId: transactionId)
         logger.info("abortTransaction: \(transactionId, privacy: 
.private(mask: .hash))")
         let _ = try await sendRequest(request, ASYNCDELAY)
     }
-    /// delete the specified transaction from Wallet-Core. No networking 
involved
-    @MainActor func abortTransactionM(transactionId: String)
-    async throws {             // M for MainActor
-        try await abortTransactionT(transactionId: transactionId)
-    }
 
-    func deleteTransactionT(transactionId: String)
-      async throws {          // might be called from a background thread 
itself
+    /// delete the specified transaction from Wallet-Core. No networking 
involved
+    func deleteTransaction(transactionId: String) async throws {
         let request = DeleteTransaction(transactionId: transactionId)
         logger.info("deleteTransaction: \(transactionId, privacy: 
.private(mask: .hash))")
         let _ = try await sendRequest(request, ASYNCDELAY)
     }
-    /// delete the specified transaction from Wallet-Core. No networking 
involved
-    @MainActor func deleteTransactionM(transactionId: String)
-      async throws {              // M for MainActor
-        try await deleteTransactionT(transactionId: transactionId)
+
+    func failTransaction(transactionId: String) async throws {
+        let request = FailTransaction(transactionId: transactionId)
+        logger.info("failTransaction: \(transactionId, privacy: .private(mask: 
.hash))")
+        let _ = try await sendRequest(request, ASYNCDELAY)
     }
 
-    func suspendTransactionT(transactionId: String)
-      async throws {          // might be called from a background thread 
itself
+    func suspendTransaction(transactionId: String) async throws {
         let request = SuspendTransaction(transactionId: transactionId)
         logger.info("suspendTransaction: \(transactionId, privacy: 
.private(mask: .hash))")
         let _ = try await sendRequest(request, ASYNCDELAY)
     }
-    /// delete the specified transaction from Wallet-Core. No networking 
involved
-    @MainActor func suspendTransactionM(transactionId: String)
-      async throws {               // M for MainActor
-        try await suspendTransactionT(transactionId: transactionId)
-    }
 
-    func resumeTransactionT(transactionId: String)
-    async throws {            // might be called from a background thread 
itself
+    func resumeTransaction(transactionId: String) async throws {
         let request = ResumeTransaction(transactionId: transactionId)
         logger.info("resumeTransaction: \(transactionId, privacy: 
.private(mask: .hash))")
         let _ = try await sendRequest(request, ASYNCDELAY)
     }
-    /// delete the specified transaction from Wallet-Core. No networking 
involved
-    @MainActor func resumeTransactionM(transactionId: String)
-      async throws {              // M for MainActor
-        try await resumeTransactionT(transactionId: transactionId)
-    }
 }
diff --git a/TalerWallet1/Model/WalletModel.swift 
b/TalerWallet1/Model/WalletModel.swift
index d0ce810..525bf11 100644
--- a/TalerWallet1/Model/WalletModel.swift
+++ b/TalerWallet1/Model/WalletModel.swift
@@ -13,13 +13,8 @@ fileprivate let ASYNCDELAY: UInt = 0   //set e.g to 6 or 9 
seconds for debugging
 // MARK: -
 /// The "virtual" base class for all models
 class WalletModel: ObservableObject {
-    public static let shared = WalletModel(0)
+    public static let shared = WalletModel()
     static func className() -> String {"\(self)"}
-    var symLog: SymLogC?
-
-    init(_ symbol: Int) {                               // init with 0 to 
disable logging for this class
-        self.symLog = SymLogC(symbol == 0 ? 0 : -1, funcName: Self.className())
-    }
     let logger = Logger (subsystem: "net.taler.gnu", category: "WalletModel")
 
     func sendRequest<T: WalletBackendFormattedRequest> (_ request: T, _ delay: 
UInt = 0)
diff --git a/TalerWallet1/Views/Balances/BalancesListView.swift 
b/TalerWallet1/Views/Balances/BalancesListView.swift
index 9029ff3..4a716eb 100644
--- a/TalerWallet1/Views/Balances/BalancesListView.swift
+++ b/TalerWallet1/Views/Balances/BalancesListView.swift
@@ -80,6 +80,12 @@ struct BalancesListView: View {
             .overlay {
                 if balances.isEmpty {
                     WalletEmptyView()
+                        .refreshable {
+                            symLog.log("refreshing")
+                            await reloadAction()      // this closure is 
already async, no need for a Task
+                                                      // TODO: reload 
transactions
+                        }
+
                 }
             }
             .alert("Scanning QR-codes requires access to the camera",
diff --git a/TalerWallet1/Views/Balances/BalancesSectionView.swift 
b/TalerWallet1/Views/Balances/BalancesSectionView.swift
index 594b651..29f32e3 100644
--- a/TalerWallet1/Views/Balances/BalancesSectionView.swift
+++ b/TalerWallet1/Views/Balances/BalancesSectionView.swift
@@ -66,25 +66,25 @@ struct BalancesSectionView: View {
 #endif
         let currency = balance.available.currencyStr
         let reloadCompleted = {
-            transactions = await model.fetchTransactionsT(currency: currency)
+            transactions = await model.transactionsT(currency: currency)
             completedTransactions = 
WalletModel.completedTransactions(transactions)
 //            sectionID = UUID()
         }
         let reloadPending = {
-            transactions = await model.fetchTransactionsT(currency: currency)
+            transactions = await model.transactionsT(currency: currency)
             pendingTransactions = WalletModel.pendingTransactions(transactions)
 //            sectionID = UUID()
         }
         let reloadUncompleted = {
-            transactions = await model.fetchTransactionsT(currency: currency)
+            transactions = await model.transactionsT(currency: currency)
             uncompletedTransactions = 
WalletModel.uncompletedTransactions(transactions)
 //            sectionID = UUID()
         }
-        let deleteAction = model.deleteTransactionT // dummyTransaction
-        let abortAction = model.abortTransactionT
-        let suspendAction = model.suspendTransactionT // dummyTransaction
-        let resumeAction = model.resumeTransactionT
+        let abortAction = model.abortTransaction
+        let deleteAction = model.deleteTransaction // dummyTransaction
         let failAction = model.failTransaction
+        let suspendAction = model.suspendTransaction // dummyTransaction
+        let resumeAction = model.resumeTransaction
 
         Section {
 //            if "KUDOS" == currency && !balance.available.isZero {
@@ -190,8 +190,8 @@ struct BalancesSectionView: View {
         }.id(sectionID)
         .task {
             if shownSectionID != sectionID {
-                let response = await model.fetchTransactionsT(currency: 
currency)
                 symLog.log("task for BalancesSectionView \(sectionID) - reload 
Transactions")
+                let response = await model.transactionsT(currency: currency)
                 transactions = response
                 pendingTransactions = WalletModel.pendingTransactions(response)
                 uncompletedTransactions = 
WalletModel.uncompletedTransactions(response)
diff --git a/TalerWallet1/Views/Payment/PaymentURIView.swift 
b/TalerWallet1/Views/Payment/PaymentURIView.swift
index 5b4a0d6..69dbae8 100644
--- a/TalerWallet1/Views/Payment/PaymentURIView.swift
+++ b/TalerWallet1/Views/Payment/PaymentURIView.swift
@@ -3,17 +3,20 @@
  * See LICENSE.md
  */
 import SwiftUI
+import taler_swift
 import SymLog
 
-// Will be called either by the user scanning a QR code or tapping the 
provided link, both from the shop's website
-// we show the user the payment details
+// Will be called either by the user scanning a QR code or tapping the 
provided link,
+// both from the shop's website. We show the payment details
 struct PaymentURIView: View {
     private let symLog = SymLogV()
+    let navTitle = String(localized: "Confirm Payment", comment:"pay merchant")
+
+    // the scanned URL
     let url: URL
 
     @EnvironmentObject private var model: WalletModel
 
-    @State var detailsForUri: PaymentDetailsForUri? = nil
 
     func playSound(success: Bool) {
         let url = URL(fileURLWithPath: 
"/System/Library/Audio/UISounds/payment_"
@@ -21,46 +24,105 @@ struct PaymentURIView: View {
         GNU_Taler.playSound(fileURL: url)
     }
 
-    func acceptAction() {
+    func acceptAction(detailsForUri: PaymentDetailsForUri) {
         Task {
             do {
-                if let detailsForUri {
-                    let confirmPayResult = try await 
model.confirmPayM(detailsForUri.proposalId)
-                    symLog.log(confirmPayResult as Any)
-                    if confirmPayResult.type == "done" {
-                        // TODO: Show Hints that Payment was successfull
-                        playSound(success: true)
-                    } else {
-                        // TODO: show error
-                        playSound(success: false)
-                    }
+                let confirmPayResult = try await 
model.confirmPayM(detailsForUri.proposalId)
+                symLog.log(confirmPayResult as Any)
+                if confirmPayResult.type == "done" {
+                    playSound(success: true)
+                    // TODO: Show Hints that Payment was successfull
+                } else {
+                    playSound(success: false)
+                    // TODO: show error
                 }
-            } catch {    // TODO: error
+            } catch {
                 playSound(success: false)
+                // TODO: error
                 symLog.log(error.localizedDescription)
             }
             dismissTop()
         }
     }
 
+    @State var detailsForUri: PaymentDetailsForUri? = nil
+
     var body: some View {
-        let badURL = "Error in URL: \(url)"
-        VStack {
-            if let detailsForUri {
-                PaymentAcceptView(detailsForUri: detailsForUri, acceptAction: 
acceptAction)
-                    .navigationTitle("Payment")
-            } else {
-                WithdrawProgressView(message: url.host ?? badURL)
-                    .navigationTitle("Contacting Exchange")
-            }
-        }.task {
-            do {
-                symLog.log(".task")
-                let details = try await 
model.preparePayForUriM(url.absoluteString)
-                detailsForUri = details
-            } catch {    // TODO: error
-                symLog.log(error.localizedDescription)
+        if let detailsForUri {
+            VStack {
+                let baseURL = detailsForUri.contractTerms.exchanges.first?.url
+                let raw = detailsForUri.amountRaw
+                let effective = detailsForUri.amountEffective
+                let currency = raw.currencyStr
+                let fee = try! Amount.diff(raw, effective)      // TODO: 
different currencies
+                ThreeAmountsView(topTitle: String(localized: "Amount to pay:"),
+                                topAmount: raw, fee: fee,
+                              bottomTitle: String(localized: "\(currency) to 
be spent:"),
+                             bottomAmount: effective,
+                                    large: true, pending: false, incoming: 
false,
+                                  baseURL: baseURL)
+                // TODO: payment: popup with all possible exchanges, check fees
+                .safeAreaInset(edge: .bottom) {
+                    Button(navTitle, action: { acceptAction(detailsForUri: 
detailsForUri) })
+                        .buttonStyle(TalerButtonStyle(type: .prominent))
+                        .padding(.horizontal)
+                }
             }
+            .navigationTitle(navTitle)
+        } else {
+            let badURL = "Error in URL: \(url)"
+            WithdrawProgressView(message: url.host ?? badURL)
+                .navigationTitle("Contacting Exchange")
+                .task {
+                    do {
+                        symLog.log(".task")
+                        let details = try await 
model.preparePayForUriM(url.absoluteString)
+                        detailsForUri = details
+                    } catch {    // TODO: error
+                        symLog.log(error.localizedDescription)
+                    }
+                }
         }
     }
 }
+// MARK: -
+struct PaymentURIView_Previews: PreviewProvider {
+    static var previews: some View {
+        let merchant = Merchant(name: "Merchant")
+        let extra = Extra(articleName: "articleName")
+        let product = Product(description: "description")
+        let terms = ContractTerms(amount: try! Amount(fromString: LONGCURRENCY 
+ ":2.2"),
+                                  maxFee: try! Amount(fromString: LONGCURRENCY 
+ ":0.2"),
+                                  maxWireFee: try! Amount(fromString: 
LONGCURRENCY + ":0.2"),
+                                  merchant: merchant,
+                                  extra: extra,
+                                  summary: "summary",
+                                  timestamp: Timestamp.now(),
+                                  payDeadline: Timestamp.tomorrow(),
+                                  refundDeadline: Timestamp.tomorrow(),
+                                  wireTransferDeadline: Timestamp.tomorrow(),
+                                  merchantBaseURL: "merchantBaseURL",
+                                  fulfillmentURL: "fulfillmentURL",
+                                  publicReorderURL: "publicReorderURL",
+                                  auditors: [],
+                                  exchanges: [],
+                                  orderID: "orderID",
+                                  nonce: "nonce",
+                                  merchantPub: "merchantPub",
+                                  products: [product],
+                                  hWire: "hWire",
+                                  wireMethod: "wireMethod",
+                                  wireFeeAmortization: 0)
+        let details = PaymentDetailsForUri(
+            amountRaw: try! Amount(fromString: LONGCURRENCY + ":2.2"),
+            amountEffective: try! Amount(fromString: LONGCURRENCY + ":2.4"),
+            noncePriv: "noncePriv",
+            proposalId: "proposalId",
+            contractTerms: terms,
+            contractTermsHash: "termsHash"
+        )
+        let url = URL(string: "taler://pay/some_amount")!
+        
+        PaymentURIView(url: url, detailsForUri: details)
+    }
+}

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]