[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[taler-taler-ios] 13/54: Overhaul withdraw + p2p
From: |
gnunet |
Subject: |
[taler-taler-ios] 13/54: Overhaul withdraw + p2p |
Date: |
Fri, 30 Jun 2023 22:33:45 +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 a41e3ea751bf572995a11e81e5aa7065fae2160b
Author: Marc Stibane <marc@taler.net>
AuthorDate: Tue Jun 20 09:23:54 2023 +0200
Overhaul withdraw + p2p
---
TalerWallet.xcodeproj/project.pbxproj | 12 +-
TalerWallet1/Controllers/PublicConstants.swift | 3 +-
TalerWallet1/Model/Peer2peerModel.swift | 17 ++-
TalerWallet1/Model/WithdrawModel.swift | 18 +--
TalerWallet1/Views/Balances/BalancesListView.swift | 10 +-
.../Views/Balances/BalancesSectionView.swift | 44 ++++--
.../Views/Exchange/ExchangeSectionView.swift | 9 +-
TalerWallet1/Views/Exchange/ManualWithdraw.swift | 107 ++++----------
.../Views/Exchange/ManualWithdrawDone.swift | 23 ++-
TalerWallet1/Views/Exchange/QuiteSomeCoins.swift | 102 +++++++++++++
.../Views/HelperViews/TransactionButton.swift | 88 +++++++++++
TalerWallet1/Views/Peer2peer/ReceivePurpose.swift | 2 +-
TalerWallet1/Views/Peer2peer/RequestPayment.swift | 25 +++-
TalerWallet1/Views/Peer2peer/SendAmount.swift | 57 +++----
TalerWallet1/Views/Peer2peer/SendNow.swift | 4 +-
.../Views/Transactions/TransactionDetailView.swift | 164 ++++++++-------------
.../Views/Transactions/TransactionsListView.swift | 14 +-
.../WithdrawAcceptDone.swift | 79 +++++-----
.../WithdrawAcceptView.swift | 103 +++++++------
.../WithdrawProgressView.swift | 10 +-
.../WithdrawBankIntegrated/WithdrawURIView.swift | 89 +++++++----
21 files changed, 607 insertions(+), 373 deletions(-)
diff --git a/TalerWallet.xcodeproj/project.pbxproj
b/TalerWallet.xcodeproj/project.pbxproj
index fbd3794..4d3cbfe 100644
--- a/TalerWallet.xcodeproj/project.pbxproj
+++ b/TalerWallet.xcodeproj/project.pbxproj
@@ -74,7 +74,6 @@
4EB095602989CBFE0043A8A1 /* BalancesSectionView.swift in
Sources */ = {isa = PBXBuildFile; fileRef = 4EB0953A2989CBFE0043A8A1 /*
BalancesSectionView.swift */; };
4EB095612989CBFE0043A8A1 /* WithdrawURIView.swift in Sources */
= {isa = PBXBuildFile; fileRef = 4EB0953C2989CBFE0043A8A1 /*
WithdrawURIView.swift */; };
4EB095622989CBFE0043A8A1 /* WithdrawModel.swift in Sources */ =
{isa = PBXBuildFile; fileRef = 4EB0953D2989CBFE0043A8A1 /* WithdrawModel.swift
*/; };
- 4EB095632989CBFE0043A8A1 /* WithdrawAcceptView.swift in Sources
*/ = {isa = PBXBuildFile; fileRef = 4EB0953E2989CBFE0043A8A1 /*
WithdrawAcceptView.swift */; };
4EB095642989CBFE0043A8A1 /* WithdrawProgressView.swift in
Sources */ = {isa = PBXBuildFile; fileRef = 4EB0953F2989CBFE0043A8A1 /*
WithdrawProgressView.swift */; };
4EB095652989CBFE0043A8A1 /* WithdrawTOSView.swift in Sources */
= {isa = PBXBuildFile; fileRef = 4EB095402989CBFE0043A8A1 /*
WithdrawTOSView.swift */; };
4EB095662989CBFE0043A8A1 /* SideBarView.swift in Sources */ =
{isa = PBXBuildFile; fileRef = 4EB095422989CBFE0043A8A1 /* SideBarView.swift
*/; };
@@ -90,6 +89,8 @@
4EB095702989CBFE0043A8A1 /* PendingOpsListView.swift in Sources
*/ = {isa = PBXBuildFile; fileRef = 4EB0954E2989CBFE0043A8A1 /*
PendingOpsListView.swift */; };
4EB3136129FEE79B007D68BC /* SendNow.swift in Sources */ = {isa
= PBXBuildFile; fileRef = 4EB3136029FEE79B007D68BC /* SendNow.swift */; };
4EB431672A1E55C700C5690E /* ManualWithdrawDone.swift in Sources
*/ = {isa = PBXBuildFile; fileRef = 4EB431662A1E55C700C5690E /*
ManualWithdrawDone.swift */; };
+ 4EBA82AB2A3EB2CA00E5F39A /* TransactionButton.swift in Sources
*/ = {isa = PBXBuildFile; fileRef = 4EBA82AA2A3EB2CA00E5F39A /*
TransactionButton.swift */; };
+ 4EBA82AD2A3F580500E5F39A /* QuiteSomeCoins.swift in Sources */
= {isa = PBXBuildFile; fileRef = 4EBA82AC2A3F580500E5F39A /*
QuiteSomeCoins.swift */; };
4EC90C782A1B528B0071DC58 /* ExchangeSectionView.swift in
Sources */ = {isa = PBXBuildFile; fileRef = 4EC90C772A1B528B0071DC58 /*
ExchangeSectionView.swift */; };
4ECB62802A0BA6DF004ABBB7 /* Peer2peerModel.swift in Sources */
= {isa = PBXBuildFile; fileRef = 4ECB627F2A0BA6DF004ABBB7 /*
Peer2peerModel.swift */; };
4ECB62822A0BB01D004ABBB7 /* SelectDays.swift in Sources */ =
{isa = PBXBuildFile; fileRef = 4ECB62812A0BB01D004ABBB7 /* SelectDays.swift */;
};
@@ -202,7 +203,6 @@
4EB0953A2989CBFE0043A8A1 /* BalancesSectionView.swift */ = {isa
= PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift;
path = BalancesSectionView.swift; sourceTree = "<group>"; };
4EB0953C2989CBFE0043A8A1 /* WithdrawURIView.swift */ = {isa =
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path
= WithdrawURIView.swift; sourceTree = "<group>"; };
4EB0953D2989CBFE0043A8A1 /* WithdrawModel.swift */ = {isa =
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path
= WithdrawModel.swift; sourceTree = "<group>"; };
- 4EB0953E2989CBFE0043A8A1 /* WithdrawAcceptView.swift */ = {isa
= PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift;
path = WithdrawAcceptView.swift; sourceTree = "<group>"; };
4EB0953F2989CBFE0043A8A1 /* WithdrawProgressView.swift */ =
{isa = PBXFileReference; fileEncoding = 4; lastKnownFileType =
sourcecode.swift; path = WithdrawProgressView.swift; sourceTree = "<group>"; };
4EB095402989CBFE0043A8A1 /* WithdrawTOSView.swift */ = {isa =
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path
= WithdrawTOSView.swift; sourceTree = "<group>"; };
4EB095422989CBFE0043A8A1 /* SideBarView.swift */ = {isa =
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path
= SideBarView.swift; sourceTree = "<group>"; };
@@ -218,6 +218,8 @@
4EB0954E2989CBFE0043A8A1 /* PendingOpsListView.swift */ = {isa
= PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift;
path = PendingOpsListView.swift; sourceTree = "<group>"; };
4EB3136029FEE79B007D68BC /* SendNow.swift */ = {isa =
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path
= SendNow.swift; sourceTree = "<group>"; };
4EB431662A1E55C700C5690E /* ManualWithdrawDone.swift */ = {isa
= PBXFileReference; lastKnownFileType = sourcecode.swift; path =
ManualWithdrawDone.swift; sourceTree = "<group>"; };
+ 4EBA82AA2A3EB2CA00E5F39A /* TransactionButton.swift */ = {isa =
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path
= TransactionButton.swift; sourceTree = "<group>"; };
+ 4EBA82AC2A3F580500E5F39A /* QuiteSomeCoins.swift */ = {isa =
PBXFileReference; lastKnownFileType = sourcecode.swift; path =
QuiteSomeCoins.swift; sourceTree = "<group>"; };
4EC90C772A1B528B0071DC58 /* ExchangeSectionView.swift */ = {isa
= PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift;
path = ExchangeSectionView.swift; sourceTree = "<group>"; };
4ECB627F2A0BA6DF004ABBB7 /* Peer2peerModel.swift */ = {isa =
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path
= Peer2peerModel.swift; sourceTree = "<group>"; };
4ECB62812A0BB01D004ABBB7 /* SelectDays.swift */ = {isa =
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path
= SelectDays.swift; sourceTree = "<group>"; };
@@ -393,6 +395,7 @@
4EB095292989CBFE0043A8A1 /*
ExchangeListView.swift */,
4EC90C772A1B528B0071DC58 /*
ExchangeSectionView.swift */,
4E50B34F2A1BEE8000F9F01C /*
ManualWithdraw.swift */,
+ 4EBA82AC2A3F580500E5F39A /*
QuiteSomeCoins.swift */,
4EB431662A1E55C700C5690E /*
ManualWithdrawDone.swift */,
);
path = Exchange;
@@ -436,7 +439,6 @@
isa = PBXGroup;
children = (
4EB0953C2989CBFE0043A8A1 /*
WithdrawURIView.swift */,
- 4EB0953E2989CBFE0043A8A1 /*
WithdrawAcceptView.swift */,
4E5A88F62A3B9E5B00072618 /*
WithdrawAcceptDone.swift */,
4EB0953F2989CBFE0043A8A1 /*
WithdrawProgressView.swift */,
4EB095402989CBFE0043A8A1 /*
WithdrawTOSView.swift */,
@@ -467,6 +469,7 @@
4E5A88F42A38A4FD00072618 /*
QRCodeDetailView.swift */,
4E6EDD862A363D8D0031D520 /* ListStyle.swift */,
4EB095482989CBFE0043A8A1 /*
TextFieldAlert.swift */,
+ 4EBA82AA2A3EB2CA00E5F39A /*
TransactionButton.swift */,
4EB095492989CBFE0043A8A1 /* AmountView.swift */,
4EB0954A2989CBFE0043A8A1 /* LoadingView.swift
*/,
4EB095432989CBFE0043A8A1 /*
LaunchAnimationView.swift */,
@@ -701,6 +704,7 @@
4EB095032989C9BC0043A8A1 /* Controller.swift in
Sources */,
4EB095682989CBFE0043A8A1 /* MainView.swift in
Sources */,
4EB0956A2989CBFE0043A8A1 /* Buttons.swift in
Sources */,
+ 4EBA82AB2A3EB2CA00E5F39A /*
TransactionButton.swift in Sources */,
4EB095602989CBFE0043A8A1 /*
BalancesSectionView.swift in Sources */,
4EEC157329F8242800D46A03 /*
QRGeneratorView.swift in Sources */,
4E5A88F72A3B9E5B00072618 /*
WithdrawAcceptDone.swift in Sources */,
@@ -711,7 +715,6 @@
4EB095212989CBCB0043A8A1 /*
WalletBackendError.swift in Sources */,
4EB0955E2989CBFE0043A8A1 /*
PendingRowView.swift in Sources */,
4EB0955B2989CBFE0043A8A1 /* BalancesModel.swift
in Sources */,
- 4EB095632989CBFE0043A8A1 /*
WithdrawAcceptView.swift in Sources */,
4EB0956D2989CBFE0043A8A1 /* LoadingView.swift
in Sources */,
4E50B3502A1BEE8000F9F01C /*
ManualWithdraw.swift in Sources */,
4E5A88F52A38A4FD00072618 /*
QRCodeDetailView.swift in Sources */,
@@ -736,6 +739,7 @@
4EA1ABBE29A3833A008821EA /*
PublicConstants.swift in Sources */,
4EB3136129FEE79B007D68BC /* SendNow.swift in
Sources */,
4EB0956B2989CBFE0043A8A1 /*
TextFieldAlert.swift in Sources */,
+ 4EBA82AD2A3F580500E5F39A /*
QuiteSomeCoins.swift in Sources */,
4EB431672A1E55C700C5690E /*
ManualWithdrawDone.swift in Sources */,
4E9320472A164BC700A87B0E /*
ReceivePurpose.swift in Sources */,
4E753A082A0B6A5F002D9328 /* ShareSheet.swift in
Sources */,
diff --git a/TalerWallet1/Controllers/PublicConstants.swift
b/TalerWallet1/Controllers/PublicConstants.swift
index 94103a0..3a117ff 100644
--- a/TalerWallet1/Controllers/PublicConstants.swift
+++ b/TalerWallet1/Controllers/PublicConstants.swift
@@ -8,7 +8,8 @@ public let LAUNCHDURATION: Double = 1.60
public let SLIDEDURATION: Double = 0.45
public let HTTPS = "https://"
-public let DEMOBANK = HTTPS + "bAnK.dEmO.tAlEr.nEt" // should be
weird to read, but still work
+//public let DEMOBANK = HTTPS + "bAnK.dEmO.tAlEr.nEt" // should be
weird to read, but still work
+public let DEMOBANK = HTTPS + "bank.demo.taler.net"
public let DEMOSHOP = HTTPS + "shop.demo.taler.net"
public let DEMOBACKEND = HTTPS + "backend.demo.taler.net"
//public let DEMOEXCHANGE = HTTPS + "eXcHaNgE.dEmO.tAlEr.nEt"
diff --git a/TalerWallet1/Model/Peer2peerModel.swift
b/TalerWallet1/Model/Peer2peerModel.swift
index ded3d10..9074ec1 100644
--- a/TalerWallet1/Model/Peer2peerModel.swift
+++ b/TalerWallet1/Model/Peer2peerModel.swift
@@ -22,7 +22,7 @@ struct PeerContractTerms: Codable {
// MARK: -
/// The result from CheckPeerPushDebit
struct CheckPeerPushDebitResponse: Codable {
- let exchangeBaseUrl: String
+ let exchangeBaseUrl: String?
let amountRaw: Amount
let amountEffective: Amount
let maxExpirationDate: Timestamp? // TODO: limit expiration (30
days or 7 days)
@@ -43,8 +43,9 @@ fileprivate struct CheckPeerPushDebit:
WalletBackendFormattedRequest {
struct CheckPeerPullCreditResponse: Codable {
let scopeInfo: ScopeInfo?
let exchangeBaseUrl: String?
- let amountEffective: Amount
let amountRaw: Amount
+ let amountEffective: Amount
+ var numCoins: Int? // Number of coins this
amountEffective will create
}
/// A request to check fees before invoicing another wallet.
fileprivate struct CheckPeerPullCredit: WalletBackendFormattedRequest {
@@ -105,7 +106,7 @@ extension Peer2peerModel {
}
/// generate peer-push. Networking involved
@MainActor
- func initiatePeerPushDebitM(_ baseURL: String, terms: PeerContractTerms)
// M for MainActor
+ func initiatePeerPushDebitM(_ baseURL: String?, terms: PeerContractTerms)
// M for MainActor
async throws -> PeerPushResponse {
let request = InitiatePeerPushDebit(exchangeBaseUrl: baseURL,
partialContractTerms: terms)
@@ -116,15 +117,17 @@ extension Peer2peerModel {
// MARK: -
extension Peer2peerModel {
- private static var models: [Peer2peerModel] = [] // a list of models
even though I currently need only one
+ private static var exchanges: [String] = [] // names of exchanges
+ private static var models: [Peer2peerModel] = [] // one model per
exchange
- static func model() -> Peer2peerModel {
- if Peer2peerModel.models.count > 0 {
- let model = Peer2peerModel.models[0]
+ static func model(baseURL: String) -> Peer2peerModel {
+ if let index = Peer2peerModel.exchanges.firstIndex(of:baseURL) {
+ let model = Peer2peerModel.models[index]
return model
} else { // new model
let model = Peer2peerModel()
Peer2peerModel.models.append(model)
+ Peer2peerModel.exchanges.append(baseURL)
return model
}
}
diff --git a/TalerWallet1/Model/WithdrawModel.swift
b/TalerWallet1/Model/WithdrawModel.swift
index 28fed21..6198915 100644
--- a/TalerWallet1/Model/WithdrawModel.swift
+++ b/TalerWallet1/Model/WithdrawModel.swift
@@ -52,12 +52,12 @@ fileprivate struct GetWithdrawalDetailsForURI:
WalletBackendFormattedRequest {
// MARK: -
/// The result from getWithdrawalDetailsForAmount
struct ManualWithdrawalDetails: Decodable {
- var amountRaw: Amount
- var amountEffective: Amount
- var paytoUris: [String]
- var tosAccepted: Bool
- var ageRestrictionOptions: [Int]?
- var numCoins: Int?
+ var tosAccepted: Bool // Did the user accept the current
version of the exchange's terms of service?
+ var amountRaw: Amount // Amount that the user will transfer
to the exchange
+ var amountEffective: Amount // Amount that will be added to the
user's wallet balance
+ var paytoUris: [String] // Ways to pay the exchange
+ var ageRestrictionOptions: [Int]? // Array of ages
+ var numCoins: Int? // Number of coins this
amountEffective will create
}
/// A request to get an exchange's withdrawal details.
fileprivate struct GetWithdrawalDetailsForAmount:
WalletBackendFormattedRequest {
@@ -180,10 +180,10 @@ extension WithdrawModel {
}
@MainActor
func sendAcceptIntWithdrawalM(_ exchangeBaseUrl: String, withdrawURL:
String) // M for MainActor
- async throws -> String? {
+ async throws -> AcceptWithdrawalResponse? {
let request = AcceptBankIntegratedWithdrawal(talerWithdrawUri:
withdrawURL, exchangeBaseUrl: exchangeBaseUrl)
let response = try await sendRequest(request, ASYNCDELAY)
- return response.confirmTransferUrl
+ return response
}
@MainActor
func sendAcceptManualWithdrawalM(_ exchangeBaseUrl: String, amount:
Amount, restrictAge: Int?) // M for MainActor
@@ -196,7 +196,7 @@ extension WithdrawModel {
// MARK: -
extension WithdrawModel {
- private static var exchanges: [String] = [] // names of
exchanges
+ private static var exchanges: [String] = [] // names of exchanges
private static var models: [WithdrawModel] = [] // one model per
exchange
static func model(baseURL: String) -> WithdrawModel {
diff --git a/TalerWallet1/Views/Balances/BalancesListView.swift
b/TalerWallet1/Views/Balances/BalancesListView.swift
index cd9d667..43398ce 100644
--- a/TalerWallet1/Views/Balances/BalancesListView.swift
+++ b/TalerWallet1/Views/Balances/BalancesListView.swift
@@ -18,6 +18,7 @@ struct BalancesListView: View {
let hamburgerAction: () -> Void
@State private var centsToTransfer: UInt64 = 0
+ @State private var purpose: String = ""
@State private var showQRScanner: Bool = false
@State private var showCameraAlert: Bool = false
@@ -73,7 +74,8 @@ struct BalancesListView: View {
let _ = Self._printChanges()
let _ = symLog.vlog() // just to get the # to compare it with
.onAppear & onDisappear
#endif
- Content(symLog: symLog, balances: $balances, centsToTransfer:
$centsToTransfer,
+ Content(symLog: symLog, balances: $balances,
+ centsToTransfer: $centsToTransfer, purpose: $purpose,
reloadAction: reloadAction)
.navigationTitle(navTitle)
.navigationBarTitleDisplayMode(.automatic)
@@ -109,6 +111,7 @@ extension BalancesListView {
@AppStorage("myListStyle") var myListStyle: MyListStyle = .automatic
@Binding var balances: [Balance]
@Binding var centsToTransfer: UInt64
+ @Binding var purpose: String
var reloadAction: () async -> Void
var body: some View {
@@ -119,7 +122,10 @@ extension BalancesListView {
Group { // necessary for .backslide transition (bug in SwiftUI)
List(balances, id: \.self) { balance in
let model = TransactionsModel.model(currency:
balance.available.currencyStr)
- BalancesSectionView(balance: balance, centsToTransfer:
$centsToTransfer, model: model)
+ BalancesSectionView(balance: balance,
+ centsToTransfer: $centsToTransfer,
+ purpose: $purpose,
+ model: model)
}
.refreshable {
symLog?.log("refreshing")
diff --git a/TalerWallet1/Views/Balances/BalancesSectionView.swift
b/TalerWallet1/Views/Balances/BalancesSectionView.swift
index ce14f10..813e614 100644
--- a/TalerWallet1/Views/Balances/BalancesSectionView.swift
+++ b/TalerWallet1/Views/Balances/BalancesSectionView.swift
@@ -18,6 +18,7 @@ struct BalancesSectionView: View {
private let symLog = SymLogV()
var balance:Balance
@Binding var centsToTransfer: UInt64
+ @Binding var purpose: String
var model: TransactionsModel?
@State private var isShowingDetailView = false
@@ -29,7 +30,19 @@ struct BalancesSectionView: View {
@State private var uncompletedTransactions: [Transaction] = []
func dummyTransaction (_ transactionId: String) async throws {}
+ func reloadOneAction(_ transactionId: String) async throws -> Transaction {
+ if let model {
+ return try await model.getTransactionByIdT(transactionId)
+ } else {
+ throw WalletBackendError.walletCoreError
+ }
+ }
+
var body: some View {
+#if DEBUG
+ let _ = Self._printChanges()
+ let _ = symLog.vlog() // just to get the # to compare it with
.onAppear & onDisappear
+#endif
let currency = balance.available.currencyStr
let reloadCompleted = {
if let model {
@@ -52,6 +65,7 @@ struct BalancesSectionView: View {
let deleteAction = model?.deleteTransactionT ?? dummyTransaction
let abortAction = model?.abortTransactionT ?? dummyTransaction
+ let p2pModel = Peer2peerModel.model(baseURL: currency)
Section {
// if "KUDOS" == currency && !balance.available.isZero {
@@ -60,27 +74,33 @@ struct BalancesSectionView: View {
// }
HStack(spacing: 0) {
NavigationLink(destination: LazyView {
- SendAmount(amountAvailable: balance.available)
+ SendAmount(model: p2pModel,
+ amountAvailable: balance.available,
+ centsToTransfer: $centsToTransfer,
+ purpose: $purpose)
}, tag: 1, selection: $buttonSelected
) { EmptyView() }.frame(width: 0).opacity(0).hidden()
NavigationLink(destination: LazyView {
- RequestPayment(scopeInfo: balance.scopeInfo,
- centsToTransfer: $centsToTransfer)
+ RequestPayment(model: p2pModel,
+ scopeInfo: balance.scopeInfo,
+ centsToTransfer: $centsToTransfer,
+ purpose: $purpose)
}, tag: 2, selection: $buttonSelected
) { EmptyView() }.frame(width: 0).opacity(0).hidden()
NavigationLink(destination: LazyView {
TransactionsListView(navTitle: String(localized:
"Transactions"), currency: currency,
transactions: completedTransactions,
- reloadAction: reloadCompleted,
+ reloadAllAction: reloadCompleted,
+ reloadOneAction: reloadOneAction,
deleteAction: deleteAction,
abortAction: abortAction)
}, tag: 3, selection: $buttonSelected
) { EmptyView() }.frame(width: 0).opacity(0).hidden()
BalanceRowView(amount: balance.available, sendAction: {
-print("button: Send Coins: \(currency)")
+print("button: Send \(currency)")
buttonSelected = 1 // will trigger SendAmount
NavigationLink
}, recvAction: {
print("button: Request Payment: \(currency)")
@@ -99,7 +119,8 @@ let _ = print("button: Pending Transactions: \(currency)")
LazyView {
TransactionsListView(navTitle: String(localized:
"Pending"), currency: currency,
transactions: pendingTransactions,
- reloadAction: reloadPending,
+ reloadAllAction: reloadPending,
+ reloadOneAction: reloadOneAction,
deleteAction: deleteAction,
abortAction: abortAction)
}
@@ -121,9 +142,10 @@ let _ = print("button: Uncompleted Transactions:
\(currency)")
LazyView {
TransactionsListView(navTitle: String(localized:
"Uncompleted"), currency: currency,
transactions:
uncompletedTransactions,
- reloadAction: reloadUncompleted,
+ reloadAllAction: reloadUncompleted,
+ reloadOneAction: reloadOneAction,
deleteAction: deleteAction,
- abortAction: abortAction)
+ abortAction: abortAction)
}
} label: {
UncompletedRowView(uncompletedTransactions:
uncompletedTransactions)
@@ -146,6 +168,7 @@ let _ = print("button: Uncompleted Transactions:
\(currency)")
#if DEBUG
fileprivate struct BindingViewContainer : View {
@State var centsToTransfer: UInt64 = 333
+ @State private var purpose: String = "bla-bla"
var body: some View {
let scopeInfo = ScopeInfo(type: ScopeInfo.ScopeInfoType.exchange,
exchangeBaseUrl: DEMOEXCHANGE, currency: LONGCURRENCY)
@@ -156,7 +179,10 @@ fileprivate struct BindingViewContainer : View {
requiresUserInput: false,
scopeInfo: scopeInfo)
List {
- BalancesSectionView(balance: balance, centsToTransfer:
$centsToTransfer, model: nil)
+ BalancesSectionView(balance: balance,
+ centsToTransfer: $centsToTransfer,
+ purpose: $purpose,
+ model: nil)
}
}
}
diff --git a/TalerWallet1/Views/Exchange/ExchangeSectionView.swift
b/TalerWallet1/Views/Exchange/ExchangeSectionView.swift
index 725b6b9..a7c9fad 100644
--- a/TalerWallet1/Views/Exchange/ExchangeSectionView.swift
+++ b/TalerWallet1/Views/Exchange/ExchangeSectionView.swift
@@ -7,6 +7,7 @@ import taler_swift
struct ExchangeRowView: View {
let exchange: Exchange
+ let currency: String
@Binding var centsToTransfer: UInt64
@State private var buttonSelected: Int? = nil
@@ -30,15 +31,13 @@ struct ExchangeRowView: View {
}.listRowSeparator(.hidden)
HStack { // buttons just set "buttonSelected" so the
NavigationLink will trigger
- Button("Deposit\nCoins") { buttonSelected = 1 }
+ Button("Deposit\n\(currency)") { buttonSelected = 1 }
.multilineTextAlignment(.center)
- .lineLimit(2)
.buttonStyle(TalerButtonStyle(type: .bordered))
.disabled(true) // TODO: after implementing Deposit check
available
- Button("Withdraw\nCoins") { buttonSelected = 2 }
+ Button("Withdraw\n\(currency)") { buttonSelected = 2 }
.multilineTextAlignment(.center)
- .lineLimit(2)
.buttonStyle(TalerButtonStyle(type: .bordered))
}.listRowSeparator(.visible)
// .listRowSeparatorTint(.red)
@@ -61,7 +60,7 @@ struct ExchangeSectionView: View {
#endif
Section {
ForEach(exchanges) { exchange in
- ExchangeRowView(exchange: exchange, centsToTransfer:
$centsToTransfer)
+ ExchangeRowView(exchange: exchange, currency: currency,
centsToTransfer: $centsToTransfer)
}
.accessibilityElement(children: .combine)
} header: {
diff --git a/TalerWallet1/Views/Exchange/ManualWithdraw.swift
b/TalerWallet1/Views/Exchange/ManualWithdraw.swift
index 68a37bc..ab849a0 100644
--- a/TalerWallet1/Views/Exchange/ManualWithdraw.swift
+++ b/TalerWallet1/Views/Exchange/ManualWithdraw.swift
@@ -6,33 +6,18 @@ import SwiftUI
import taler_swift
import SymLog
+// Will be called by the user tapping "Withdraw Coins" in the exchange list
struct ManualWithdraw: View {
private let symLog = SymLogV()
- let navTitle = String(localized: "Withdraw Coins")
- var exchange: Exchange
- var model: WithdrawModel?
+ let exchange: Exchange
+ let model: WithdrawModel?
@Binding var centsToTransfer: UInt64
@State var manualWithdrawalDetails: ManualWithdrawalDetails? = nil
-// @State var numCoins: Int = 0
-
- // returns numCoins, 0 if invalid, -1 if unknown
- // either fees or empty string
- private func numAndFee(detailsForAmount: ManualWithdrawalDetails?) ->
(Int, String) {
- do {
- if let details = detailsForAmount {
- let fee = try details.amountRaw - details.amountEffective
- return (details.numCoins ?? -1, // either the number of
coins, or unknown
- fee.isZero ? "" : fee.readableDescription)
- }
- } catch {}
- symLog.log("invalid")
- return (0, "") // invalid
- }
- @State var ageMenuList: [Int] = []
- @State var selectedAge = 0
+// @State var ageMenuList: [Int] = []
+// @State var selectedAge = 0
var body: some View {
#if DEBUG
@@ -42,64 +27,32 @@ struct ManualWithdraw: View {
let currency = exchange.currency!
let navTitle = String(localized: "Withdraw \(currency)")
let currencyField = CurrencyField(value: $centsToTransfer, currency:
currency) // becomeFirstResponder
- let agePicker = AgePicker(ageMenuList: $ageMenuList, selectedAge:
$selectedAge)
+// let agePicker = AgePicker(ageMenuList: $ageMenuList, selectedAge:
$selectedAge)
ScrollView {
Text("from \(exchange.exchangeBaseUrl.trimURL())")
.font(.title3)
- CurrencyInputView(currencyField: currencyField, title:
String(localized: "Amount to withdraw:"))
-
- let (numCoins, fee) = numAndFee(detailsForAmount:
manualWithdrawalDetails)
- let unknown = (numCoins < 0)
- let invalid = (numCoins == 0)
- let manyCoins = (numCoins > 99)
- let quiteSome = (numCoins > 199)
- let tooMany = (numCoins > 999)
- let hasFee = (fee.count > 0)
- let shownFee = hasFee ? String(localized: "- \(fee)") :
String(localized: "No")
- Text(invalid ? "invalid amount"
- : tooMany ? "too many coins for a single withdrawal"
- : "\(shownFee) withdrawal fee")
- .foregroundColor((invalid || tooMany || hasFee) ? .red :
.primary)
- .padding()
+ CurrencyInputView(currencyField: currencyField,
+ title: String(localized: "Amount to withdraw:"))
- if !invalid {
- HStack {
- Text(unknown ? "Some" : "\(numCoins)")
- .foregroundColor(quiteSome ? .red : .primary)
- Text(tooMany ? "coins" : "coins to obtain:")
- .foregroundColor(tooMany ? .red : .primary)
+ let someCoins = SomeCoins(details: manualWithdrawalDetails)
+ QuiteSomeCoins(someCoins: someCoins, shouldShowFee: true,
+ currency: currency, amountEffective:
manualWithdrawalDetails?.amountEffective)
- Spacer()
- if !tooMany {
- let effective =
manualWithdrawalDetails?.amountEffective ?? Amount(currency: currency, value: 0)
- Text(effective.readableDescription)
- }
- } // xx coins to obtain: YYY currency
- .padding(.top)
-// .font(.title3)
-
- if !tooMany {
- if manyCoins {
- Text(quiteSome ? "Warning: It will take quite some
time\nto generate this many coins!"
- : "Warning: It will take some time\nto
generate this many coins.")
- .multilineTextAlignment(.leading)
- .padding(.top, 6)
- .foregroundColor(quiteSome ? .red : .primary)
- } // warnings
+ if !someCoins.invalid {
+ if !someCoins.tooMany {
+// agePicker
- agePicker
-
- if let tosAcc = manualWithdrawalDetails?.tosAccepted {
- if tosAcc {
- let restrictAge: Int? = (selectedAge == 0) ? nil
- :
selectedAge
-let _ = print(selectedAge, restrictAge)
+ if let tosAccepted = manualWithdrawalDetails?.tosAccepted {
+ if tosAccepted {
+// let restrictAge: Int? = (selectedAge == 0) ? nil
+// :
selectedAge
+//let _ = print(selectedAge, restrictAge)
NavigationLink(destination: LazyView {
ManualWithdrawDone(exchange: exchange,
model: model,
- centsToTransfer: centsToTransfer,
- restrictAge: restrictAge)
+ centsToTransfer: centsToTransfer)
+// restrictAge: restrictAge)
}) {
Text("Confirm Withdrawal") //
VIEW_WITHDRAW_ACCEPT
}.buttonStyle(TalerButtonStyle(type: .prominent))
@@ -144,15 +97,13 @@ let _ = print(selectedAge, restrictAge)
#if DEBUG
struct ManualWithdraw_Container : View {
@State private var centsToTransfer: UInt64 = 510
- @State private var manualWithdrawalDetails =
ManualWithdrawalDetails(amountRaw: try! Amount(fromString: LONGCURRENCY +
":5.1"),
-
amountEffective: try! Amount(fromString: LONGCURRENCY + ":5.0"),
-
paytoUris: [],
-
tosAccepted: false,
-
ageRestrictionOptions: [],
-
numCoins: 6)
-
+ @State private var details = ManualWithdrawalDetails(tosAccepted: false,
+ amountRaw: try!
Amount(fromString: LONGCURRENCY + ":5.1"),
+ amountEffective: try!
Amount(fromString: LONGCURRENCY + ":5.0"),
+ paytoUris: [],
+ ageRestrictionOptions: [],
+ numCoins: 6)
var body: some View {
- let model = WithdrawModel.model(baseURL: DEMOEXCHANGE)
let exchange = Exchange(exchangeBaseUrl: DEMOEXCHANGE,
currency: LONGCURRENCY,
paytoUris: [],
@@ -161,9 +112,9 @@ struct ManualWithdraw_Container : View {
ageRestrictionOptions: [],
permanent: false)
ManualWithdraw(exchange: exchange,
- model: model,
+ model: nil,
centsToTransfer: $centsToTransfer,
- manualWithdrawalDetails: manualWithdrawalDetails)
+ manualWithdrawalDetails: details)
}
}
diff --git a/TalerWallet1/Views/Exchange/ManualWithdrawDone.swift
b/TalerWallet1/Views/Exchange/ManualWithdrawDone.swift
index 2e771ac..27c4213 100644
--- a/TalerWallet1/Views/Exchange/ManualWithdrawDone.swift
+++ b/TalerWallet1/Views/Exchange/ManualWithdrawDone.swift
@@ -10,13 +10,22 @@ struct ManualWithdrawDone: View {
private let symLog = SymLogV()
let navTitle = String(localized: "Wire Transfer")
- var exchange: Exchange
- var model: WithdrawModel?
- var centsToTransfer: UInt64
- var restrictAge: Int?
+ let exchange: Exchange
+ let model: WithdrawModel?
+ let centsToTransfer: UInt64
+// let restrictAge: Int?
+
@State var acceptManualWithdrawalResult: AcceptManualWithdrawalResult?
@State var withdrawalTransaction: Transaction?
+ func reloadOneAction(_ transactionId: String) async throws -> Transaction {
+ if let model {
+ return try await model.getTransactionByIdT(transactionId)
+ } else {
+ throw WalletBackendError.walletCoreError
+ }
+ }
+
var body: some View {
#if DEBUG
let _ = Self._printChanges()
@@ -25,7 +34,8 @@ struct ManualWithdrawDone: View {
VStack {
if let transaction = withdrawalTransaction {
TransactionDetailView(transaction: transaction,
- doneAction:
{ViewState.shared.popToRootView()})
+ reloadAction: reloadOneAction,
+ doneAction:
ViewState.shared.popToRootView)
.navigationBarBackButtonHidden(true) // exit only
by Done-Button
.navigationTitle(navTitle)
} else {
@@ -40,11 +50,10 @@ struct ManualWithdrawDone: View {
if let model {
let amount = Amount.amountFromCents(exchange.currency!,
centsToTransfer)
let result = try await
model.sendAcceptManualWithdrawalM(exchange.exchangeBaseUrl,
-
amount: amount, restrictAge: restrictAge)
+
amount: amount, restrictAge: 0)
print(result as Any)
let transaction = try await
model.getTransactionByIdT(result!.transactionId)
withdrawalTransaction = transaction
-// acceptManualWithdrawalResult = result
}
} catch { // TODO: error
symLog.log(error.localizedDescription)
diff --git a/TalerWallet1/Views/Exchange/QuiteSomeCoins.swift
b/TalerWallet1/Views/Exchange/QuiteSomeCoins.swift
new file mode 100644
index 0000000..1c2febf
--- /dev/null
+++ b/TalerWallet1/Views/Exchange/QuiteSomeCoins.swift
@@ -0,0 +1,102 @@
+/*
+ * This file is part of GNU Taler, ©2022-23 Taler Systems S.A.
+ * See LICENSE.md
+ */
+import SwiftUI
+import taler_swift
+import SymLog
+
+struct SomeCoins {
+ let numCoins: Int // 0 == invalid, -1 == unknown
+ var unknown: Bool { numCoins < 0 }
+ var invalid: Bool { numCoins == 0 }
+ var manyCoins: Bool { numCoins > 99 }
+ var quiteSome: Bool { numCoins > 199 }
+ var tooMany: Bool { numCoins > 999 }
+
+ let fee: String
+ var hasFee: Bool { fee.count > 0 }
+}
+
+extension SomeCoins {
+ init(details: ManualWithdrawalDetails?) {
+ do {
+ if let details {
+ // Incoming: fee = raw - effective
+ let fee = try details.amountRaw - details.amountEffective
+ self.init(numCoins: details.numCoins ?? -1, // either the
number of coins, or unknown
+ fee: fee.isZero ? "" : fee.readableDescription)
+ return
+ }
+ } catch {}
+ self.init(numCoins: 0, fee:"") // invalid
+ }
+
+ init(details: CheckPeerPullCreditResponse?) {
+ do {
+ if let details {
+ // Incoming: fee = raw - effective
+ let fee = try details.amountRaw - details.amountEffective
+ self.init(numCoins: details.numCoins ?? -1, // either the
number of coins, or unknown
+ fee: fee.isZero ? "" : fee.readableDescription)
+ return
+ }
+ } catch {}
+ self.init(numCoins: 0, fee:"") // invalid
+ }
+}
+// MARK: -
+struct QuiteSomeCoins: View {
+ private let symLog = SymLogV()
+ let someCoins: SomeCoins
+ let shouldShowFee: Bool
+ let currency: String
+ let amountEffective: Amount?
+
+ var body: some View {
+ if shouldShowFee {
+ let shownFee = someCoins.hasFee ? String(localized: "-
\(someCoins.fee)")
+ : String(localized: "No")
+ Text(someCoins.invalid ? "invalid amount"
+ : someCoins.tooMany ? "too many coins for a single withdrawal"
+ : "\(shownFee) withdrawal fee")
+ .foregroundColor((someCoins.invalid || someCoins.tooMany ||
someCoins.hasFee) ? .red : .primary)
+ .padding(4)
+ }
+ if !someCoins.invalid {
+ HStack {
+ Text(someCoins.unknown ? "Some" : "\(someCoins.numCoins)")
+ .foregroundColor(someCoins.quiteSome ? .red : .primary)
+ Text(someCoins.tooMany ? "coins" : "coins to obtain:")
+ .foregroundColor(someCoins.tooMany ? .red : .primary)
+
+ Spacer()
+ if !someCoins.tooMany {
+ let effective = amountEffective ?? Amount(currency:
currency, value: 0)
+ Text(effective.readableDescription)
+ }
+ } // xx coins to obtain: YYY currency
+// .font(.title3)
+ .padding(.top)
+
+ if !someCoins.tooMany {
+ if someCoins.manyCoins {
+ Text(someCoins.quiteSome ? "Warning: It will take quite
some time\nto generate this many coins!"
+ : "Warning: It will take some
time\nto generate this many coins.")
+ .multilineTextAlignment(.leading)
+ .padding(.top, 6)
+ .foregroundColor(someCoins.quiteSome ? .red : .primary)
+ } // warnings
+ }
+ }
+ }
+}
+// MARK: -
+struct QuiteSomeCoins_Previews: PreviewProvider {
+ static var previews: some View {
+ QuiteSomeCoins(someCoins: SomeCoins(numCoins: 4, fee: "20 " +
LONGCURRENCY),
+ shouldShowFee: true,
+ currency: LONGCURRENCY,
+ amountEffective: nil)
+ }
+}
diff --git a/TalerWallet1/Views/HelperViews/TransactionButton.swift
b/TalerWallet1/Views/HelperViews/TransactionButton.swift
new file mode 100644
index 0000000..3c017e6
--- /dev/null
+++ b/TalerWallet1/Views/HelperViews/TransactionButton.swift
@@ -0,0 +1,88 @@
+/*
+ * This file is part of GNU Taler, ©2022-23 Taler Systems S.A.
+ * See LICENSE.md
+ */
+import SwiftUI
+import taler_swift
+import AVFoundation
+
+struct TransactionButton: View {
+ let transactionId : String
+ let command : TxAction
+ let action: (_ transactionId: String) async throws -> Void
+
+ @State var disabled: Bool = false
+ @State var executed: Bool = false
+ var body: some View {
+ let role: ButtonRole? = (command == .abort) ? .cancel
+ : (command == .delete) ? .destructive
+ : nil
+ Button(role: role, action: {
+ Task {
+ disabled = true // don't try this more than once
+ do {
+ try await action(transactionId)
+// symLog.log("\(executed) \(transactionId)")
+ executed = true
+ } catch { // TODO: error
+// symLog.log(error.localizedDescription)
+ }
+ }
+ }, label: {
+ HStack {
+ if executed {
+ switch command {
+ case .delete:
+ Text("Deleted from list")
+ case .abort:
+ Text("Abort pending...")
+ case .fail:
+ Text("Failing...")
+ case .suspend:
+ Text("Suspending...")
+ case .resume:
+ Text("Resuming...")
+ }
+ } else {
+ let spaces = " "
+ switch command {
+ case .delete:
+ Text("Delete from list" + spaces)
+ Image(systemName: "trash") //
+ case .abort:
+ Text("Abort" + spaces)
+ Image(systemName: "x.circle") //
+ case .fail:
+ Text("Fail" + spaces)
+ Image(systemName: "fanblades.slash") //
+ case .suspend:
+ Text("Suspend" + spaces)
+ Image(systemName: "clock.badge.xmark") //
+ case .resume:
+ Text("Resume" + spaces)
+ Image(systemName: "clock.arrow.circlepath") //
+ }
+ }
+ }
+ .font(.title)
+ .frame(maxWidth: .infinity)
+ })
+ .buttonStyle(.bordered)
+ .controlSize(.large)
+ .padding(.horizontal)
+ .disabled(disabled)
+ }
+
+}
+
+
+#if DEBUG
+struct TransactionButton_Previews: PreviewProvider {
+
+ static var previews: some View {
+ List {
+ TransactionButton(transactionId: "String", command: .abort,
action: {transactionId in })
+ }
+ }
+}
+#endif
diff --git a/TalerWallet1/Views/Peer2peer/ReceivePurpose.swift
b/TalerWallet1/Views/Peer2peer/ReceivePurpose.swift
index cbbafbf..16add0d 100644
--- a/TalerWallet1/Views/Peer2peer/ReceivePurpose.swift
+++ b/TalerWallet1/Views/Peer2peer/ReceivePurpose.swift
@@ -9,7 +9,6 @@ import SymLog
struct ReceivePurpose: View {
private let symLog = SymLogV()
@FocusState private var isFocused: Bool
- let model = Peer2peerModel.model()
@State var peerPullCheck: CheckPeerPullCreditResponse?
var scopeInfo: ScopeInfo
@@ -38,6 +37,7 @@ struct ReceivePurpose: View {
var body: some View {
let amount = Amount.amountFromCents(scopeInfo.currency,
centsToTransfer)
+ let model = Peer2peerModel.model(baseURL: scopeInfo.currency)
let fee = pullFee(ppCheck: peerPullCheck)
VStack (spacing: 6) {
diff --git a/TalerWallet1/Views/Peer2peer/RequestPayment.swift
b/TalerWallet1/Views/Peer2peer/RequestPayment.swift
index 1b18aed..d8d3be3 100644
--- a/TalerWallet1/Views/Peer2peer/RequestPayment.swift
+++ b/TalerWallet1/Views/Peer2peer/RequestPayment.swift
@@ -9,11 +9,12 @@ import SymLog
struct RequestPayment: View {
private let symLog = SymLogV()
+ let model: Peer2peerModel?
var scopeInfo: ScopeInfo
@Binding var centsToTransfer: UInt64
+ @Binding var purpose: String
@State private var peerPullCheck: CheckPeerPullCreditResponse? = nil
- @State private var purpose: String = ""
@State private var expireDays: UInt = 0
var body: some View {
@@ -29,6 +30,10 @@ struct RequestPayment: View {
CurrencyInputView(currencyField: currencyField,
title: String(localized: "Amount to receive:"))
+ let someCoins = SomeCoins(details: peerPullCheck)
+ QuiteSomeCoins(someCoins: someCoins, shouldShowFee: true,
+ currency: currency, amountEffective:
peerPullCheck?.amountEffective)
+
HStack {
let disabled = centsToTransfer == 0
@@ -59,10 +64,24 @@ struct RequestPayment: View {
.navigationTitle(navTitle)
.onAppear { // make CurrencyField show the keyboard
DebugViewC.shared.setViewID(VIEW_INVOICE_P2P)
- print("❗️Yikes \(navTitle) onAppear")
+ symLog.log("❗️Yikes \(navTitle) onAppear")
}
.onDisappear {
- print("❗️Yikes \(navTitle) onDisappear")
+ symLog.log("❗️Yikes \(navTitle) onDisappear")
+ }
+ .task(id: centsToTransfer) {
+ let amount = Amount.amountFromCents(currency, centsToTransfer)
+ do {
+ if let model {
+ let ppCheck = try await model.checkPeerPullCreditM(amount,
exchangeBaseUrl: nil)
+ peerPullCheck = ppCheck
+ // TODO: set from exchange
+// agePicker.setAges(ages: peerPushCheck?.ageRestrictionOptions)
+ }
+ } catch { // TODO: error
+ symLog.log(error.localizedDescription)
+ peerPullCheck = nil
+ }
}
}
}
diff --git a/TalerWallet1/Views/Peer2peer/SendAmount.swift
b/TalerWallet1/Views/Peer2peer/SendAmount.swift
index 47cd64c..17e7026 100644
--- a/TalerWallet1/Views/Peer2peer/SendAmount.swift
+++ b/TalerWallet1/Views/Peer2peer/SendAmount.swift
@@ -6,32 +6,29 @@ import SwiftUI
import taler_swift
import SymLog
+// Will be called by the user tapping "Send Coins" in the balances list
struct SendAmount: View {
private let symLog = SymLogV()
- let navTitle = String(localized: "Send Coins")
-// @ObservedObject private var keyboardResponder = KeyboardResponder()
-// @FocusState private var isFocused: Bool
- let model = Peer2peerModel.model()
- @State var peerPushCheck: CheckPeerPushDebitResponse?
+ let model: Peer2peerModel?
let amountAvailable: Amount
- let buttonFont: Font = .title2
+ @Binding var centsToTransfer: UInt64
+ @Binding var purpose: String
- @State private var centsToTransfer: UInt64 = 0
- @State private var purpose: String = ""
+ @State var peerPushCheck: CheckPeerPushDebitResponse?
@State private var expireDays: UInt = 0
private func fee(ppCheck: CheckPeerPushDebitResponse?) -> String {
do {
- if let p2pcheck = ppCheck {
- let fee = try p2pcheck.amountEffective - p2pcheck.amountRaw
+ if let ppCheck {
+ // Outgoing: fee = effective - raw
+ let fee = try ppCheck.amountEffective - ppCheck.amountRaw
return fee.readableDescription
}
} catch {}
return ""
}
-
var body: some View {
#if DEBUG
let _ = Self._printChanges()
@@ -51,15 +48,11 @@ struct SendAmount: View {
Text("+ \(fee) payment fee")
.foregroundColor(.red)
- Text("Choose where to send to:")
- .padding(.top)
- .font(.title3)
+ .padding(4)
+
HStack {
- let kbdShown: Bool = false //
keyboardResponder.keyboardHeight > 0
- let title2 = kbdShown ? "To wallet" : "To another\nwallet"
let disabled = centsToTransfer == 0 // TODO: check
amountAvailable
-
NavigationLink(destination: LazyView {
SendPurpose(model: model,
amountAvailable: amountAvailable,
@@ -82,19 +75,21 @@ struct SendAmount: View {
.background(WalletColors().backgroundColor.edgesIgnoringSafeArea(.all))
.navigationTitle(navTitle)
.onAppear { // make CurrencyField show the keyboard
- symLog.log("onAppear")
DebugViewC.shared.setViewID(VIEW_SEND_P2P)
- print("❗️Yikes SendAmount onAppear")
+ symLog.log("❗️Yikes SendAmount onAppear")
}
.onDisappear {
- print("❗️Yikes SendAmount onDisappear")
+ symLog.log("❗️Yikes SendAmount onDisappear")
}
.task(id: centsToTransfer) {
let amount = Amount.amountFromCents(currency, centsToTransfer)
do {
- peerPushCheck = try await model.checkPeerPushDebitM(amount)
- // TODO: set from exchange
-// agePicker.setAges(ages: peerPushCheck?.ageRestrictionOptions)
+ if let model {
+ let ppCheck = try await model.checkPeerPushDebitM(amount)
+ peerPushCheck = ppCheck
+ // TODO: set from exchange
+ // agePicker.setAges(ages:
peerPushCheck?.ageRestrictionOptions)
+ }
} catch { // TODO: error
symLog.log(error.localizedDescription)
peerPushCheck = nil
@@ -104,10 +99,22 @@ struct SendAmount: View {
}
// MARK: -
#if DEBUG
+struct SendAmount_Container : View {
+ @State private var centsToTransfer: UInt64 = 510
+ @State private var purpose: String = ""
+
+ var body: some View {
+ let amount = Amount(currency: LONGCURRENCY, integer: 10, fraction: 0)
+ SendAmount(model: nil,
+ amountAvailable: amount,
+ centsToTransfer: $centsToTransfer,
+ purpose: $purpose)
+ }
+}
+
struct SendAmount_Previews: PreviewProvider {
static var previews: some View {
- let amount = Amount(currency: "TaLeR", integer: 10, fraction: 0)
- SendAmount(amountAvailable: amount)
+ SendAmount_Container()
}
}
#endif
diff --git a/TalerWallet1/Views/Peer2peer/SendNow.swift
b/TalerWallet1/Views/Peer2peer/SendNow.swift
index 3ead004..8615341 100644
--- a/TalerWallet1/Views/Peer2peer/SendNow.swift
+++ b/TalerWallet1/Views/Peer2peer/SendNow.swift
@@ -53,8 +53,8 @@ struct SendNow: View {
if let model {
let timestamp = Timestamp.inSomeDays(expireDays)
let terms = PeerContractTerms(amount: amountToSend,
summary: purpose, purse_expiration: timestamp)
- let baseURL = DEMOEXCHANGE // TODO: use correct baseURL
- peerPushResponse = try await
model.initiatePeerPushDebitM(baseURL, terms: terms)
+ // TODO: user might choose baseURL
+ peerPushResponse = try await
model.initiatePeerPushDebitM(nil, terms: terms)
talerURI = peerPushResponse?.talerUri
}
} catch { // TODO: error
diff --git a/TalerWallet1/Views/Transactions/TransactionDetailView.swift
b/TalerWallet1/Views/Transactions/TransactionDetailView.swift
index c048cc0..d9e16c1 100644
--- a/TalerWallet1/Views/Transactions/TransactionDetailView.swift
+++ b/TalerWallet1/Views/Transactions/TransactionDetailView.swift
@@ -9,11 +9,15 @@ import SymLog
struct TransactionDetailView: View {
private let symLog = SymLogV()
@AppStorage("myListStyle") var myListStyle: MyListStyle = .automatic
+ @AppStorage("developerMode") var developerMode: Bool = false
- var transaction: Transaction
+ @State var transaction: Transaction
+ var reloadAction: ((_ transactionId: String) async throws -> Transaction)
var deleteAction: ((_ transactionId: String) async throws -> Void)?
var abortAction: ((_ transactionId: String) async throws -> Void)?
var doneAction: (() -> Void)?
+ var suspendAction: ((_ transactionId: String) async throws -> Void)?
+ var resumeAction: ((_ transactionId: String) async throws -> Void)?
var body: some View {
#if DEBUG
@@ -30,35 +34,49 @@ struct TransactionDetailView: View {
Text("\(dateString)")
.font(.title2)
// .listRowSeparator(.hidden)
- SwitchCase(transaction: transaction, common: common)
+ SwitchCase(transaction: $transaction)
if transaction.isAbortable { if let abortAction {
- AbortButton(common: common, abortAction: abortAction)
+ TransactionButton(transactionId: common.transactionId,
+ command: .abort, action: abortAction)
} }
if transaction.isDeleteable { if let deleteAction {
- DeleteButton(common: common, deleteAction: deleteAction)
+ TransactionButton(transactionId: common.transactionId,
+ command: .delete, action: deleteAction)
} }
if let doneAction {
DoneButton(doneAction: doneAction)
- .onNotification(.TransactionStateTransition) {
notification in
-print(notification.userInfo)
- if let transition =
notification.userInfo?[TRANSACTIONTRANSITION] as? TransactionTransition {
-print(transition.newTxState.major)
- if transition.transactionId ==
common.transactionId {
- doneAction()
- }
- }
- }
}
-// if transaction.isSuspendable { if let suspendAction {
-// SuspendButton(common: common, suspendAction:
suspendAction)
-// } }
-// if transaction.isResumable { if let resumeAction {
-// ResumeButton(common: common, resumeAction: resumeAction)
-// } }
+ if developerMode {
+ if transaction.isSuspendable { if let suspendAction {
+ TransactionButton(transactionId: common.transactionId,
+ command: .suspend, action:
suspendAction)
+ } }
+ if transaction.isResumable { if let resumeAction {
+ TransactionButton(transactionId: common.transactionId,
+ command: .resume, action:
resumeAction)
+ } }
+ }
+ }.listStyle(myListStyle.style).anyView
+ }.onNotification(.TransactionStateTransition) { notification in
+ if let transition = notification.userInfo?[TRANSACTIONTRANSITION]
as? TransactionTransition {
+ if transition.transactionId == common.transactionId {
+ let newState = transition.newTxState.major
+ if newState == .done { if let doneAction {
+ symLog.log("newTxState.major == done")
+ doneAction()
+ }} else { Task { do {
+ symLog.log("newState: \(newState), reloading
transaction")
+ let reloadedTransaction = try await
reloadAction(common.transactionId)
+ transaction = reloadedTransaction // redraw
+ } catch {
+ symLog.log(error.localizedDescription)
+ }}}
+ }
+ } else {
+ symLog.log(notification.userInfo as Any)
}
- .listStyle(myListStyle.style).anyView
}
.navigationTitle(navTitle)
.onAppear {
@@ -73,21 +91,34 @@ print(transition.newTxState.major)
//
//extension TransactionDetail {
struct SwitchCase: View {
- let transaction: Transaction
- let common: TransactionCommon
+ @Binding var transaction: Transaction
var body: some View {
- let pending = (common.txState.major ==
TransactionMajorState.pending)
+ let common = transaction.common
+ let pending = transaction.isPending
switch transaction {
case .withdrawal(let withdrawalTransaction):
let details = withdrawalTransaction.details
if pending {
- switch details.withdrawalDetails.type {
- case .manual:
- ManualDetails(common: common, details:
details.withdrawalDetails)
+ let withdrawalDetails = details.withdrawalDetails
+ switch withdrawalDetails.type {
+ case .manual: // "Make a wire
transfer of \(amount) to"
+ ManualDetails(common: common, details:
withdrawalDetails)
+
+ case .bankIntegrated: // "Confirm with bank"
+ VStack {
+ if let confirmationUrl =
withdrawalDetails.bankConfirmationUrl {
+ if let destination = URL(string:
confirmationUrl) {
+ // Show Hint that User should
Confirm on bank website
+ Text("Waiting for bank
confirmation")
+ .listRowSeparator(.hidden)
+ Link("Confirm with bank",
destination: destination)
+
.buttonStyle(TalerButtonStyle(type: .prominent, narrow: false, aligned:
.center))
+ .padding(.horizontal)
- case .bankIntegrated:
- QRCodeDetails(transaction: transaction)
+ }
+ }
+ }
}
}
ThreeAmounts(common: common, topTitle: String(localized:
"Chosen amount to withdraw:"),
@@ -148,78 +179,6 @@ print(transition.newTxState.major)
}
}
}
- struct DeleteButton: View {
- var common : TransactionCommon
- var deleteAction: (_ transactionId: String) async throws -> Void
-
- @State var disabled: Bool = false
- @State var deleted: Bool = false
- var body: some View {
- Button(role: .destructive, action: {
- Task { // delete from wallet-core
- disabled = true // don't try this more than once
- do {
- try await deleteAction(common.transactionId)
-// symLog.log("deleted \(common.transactionId)")
- deleted = true
- } catch { // TODO: error
-// symLog.log(error.localizedDescription)
- }
- }
- }, label: {
- HStack {
- if deleted {
- Text("Deleted from list")
- } else {
- Text("Delete from list" + " ")
- Image(systemName: "trash")
- }
- }
- .font(.title)
- .frame(maxWidth: .infinity)
- })
- .buttonStyle(.bordered)
- .controlSize(.large)
- .padding(.horizontal)
- .disabled(disabled)
- }
- }
- struct AbortButton: View {
- var common : TransactionCommon
- var abortAction: (_ transactionId: String) async throws -> Void
-
- @State var disabled: Bool = false
- @State var aborting: Bool = false
- var body: some View {
- Button(role: .cancel, action: {
- Task { // delete from wallet-core
- disabled = true // don't try this more than once
- do {
- try await abortAction(common.transactionId)
-// symLog.log("aborted \(common.transactionId)")
- aborting = true
- } catch { // TODO: error
-// symLog.log(error.localizedDescription)
- }
- }
- }, label: {
- HStack {
- if aborting {
- Text("Abort pending...")
- } else {
- Text("Abort" + " ")
- Image(systemName: "x.circle")
- }
- }
- .font(.title)
- .frame(maxWidth: .infinity)
- })
- .buttonStyle(.bordered)
- .controlSize(.large)
- .padding(.horizontal)
- .disabled(disabled)
- }
- }
struct DoneButton: View {
var doneAction: () -> Void
@@ -245,10 +204,11 @@ struct TransactionDetail_Previews: PreviewProvider {
pending: false,
id: "some payment ID",
time: Timestamp(from:
1_666_666_000_000))
+ static func reloadActionDummy(transactionId: String) async -> Transaction
{ return withdrawal }
static var previews: some View {
Group {
- TransactionDetailView(transaction: withdrawal, doneAction:
doneActionDummy)
- TransactionDetailView(transaction: payment, deleteAction:
deleteTransactionDummy)
+ TransactionDetailView(transaction: withdrawal, reloadAction:
reloadActionDummy, doneAction: doneActionDummy)
+ TransactionDetailView(transaction: payment, reloadAction:
reloadActionDummy, deleteAction: deleteTransactionDummy)
}
}
}
diff --git a/TalerWallet1/Views/Transactions/TransactionsListView.swift
b/TalerWallet1/Views/Transactions/TransactionsListView.swift
index 0404d62..218bf75 100644
--- a/TalerWallet1/Views/Transactions/TransactionsListView.swift
+++ b/TalerWallet1/Views/Transactions/TransactionsListView.swift
@@ -12,7 +12,8 @@ struct TransactionsListView: View {
let currency: String
let transactions: [Transaction]
- var reloadAction: () async -> ()
+ let reloadAllAction: () async -> ()
+ let reloadOneAction: ((_ transactionId: String) async throws ->
Transaction)
let deleteAction: (_ transactionId: String) async throws -> ()
let abortAction: (_ transactionId: String) async throws -> ()
@@ -26,7 +27,8 @@ struct TransactionsListView: View {
// let title = AttributedString(localized: "^[\(count) Ticket](inflect:
true)")
let title: String = "\(count) \(navTitle)"
Content(symLog: symLog, currency: currency, transactions:
transactions, myListStyle: $myListStyle,
- reloadAction: reloadAction, deleteAction: deleteAction,
abortAction: abortAction)
+ reloadAllAction: reloadAllAction, reloadOneAction:
reloadOneAction,
+ deleteAction: deleteAction, abortAction: abortAction)
.navigationTitle(title)
.navigationBarTitleDisplayMode(.large) // .inline
.onAppear {
@@ -34,7 +36,7 @@ struct TransactionsListView: View {
}
.task {
symLog.log(".task ")
- await reloadAction()
+ await reloadAllAction()
}
}
}
@@ -45,7 +47,8 @@ extension TransactionsListView {
let currency: String
let transactions: [Transaction]
@Binding var myListStyle: MyListStyle
- let reloadAction: () async -> ()
+ let reloadAllAction: () async -> ()
+ let reloadOneAction: ((_ transactionId: String) async throws ->
Transaction)
let deleteAction: (_ transactionId: String) async throws -> ()
let abortAction: (_ transactionId: String) async throws -> ()
@@ -87,6 +90,7 @@ extension TransactionsListView {
NavigationLink { LazyView { // whole row like
in a tableView
// pending may not be deleted, but only aborted
TransactionDetailView(transaction: transaction,
+ reloadAction: reloadOneAction,
deleteAction: deleteAction,
abortAction: abortAction)
}} label: {
@@ -97,7 +101,7 @@ extension TransactionsListView {
}
.refreshable {
symLog?.log("refreshing")
- await reloadAction()
+ await reloadAllAction()
}
.listStyle(myListStyle.style).anyView
.onAppear {
diff --git a/TalerWallet1/Views/WithdrawBankIntegrated/WithdrawAcceptDone.swift
b/TalerWallet1/Views/WithdrawBankIntegrated/WithdrawAcceptDone.swift
index 9e9ff1e..766ee8d 100644
--- a/TalerWallet1/Views/WithdrawBankIntegrated/WithdrawAcceptDone.swift
+++ b/TalerWallet1/Views/WithdrawBankIntegrated/WithdrawAcceptDone.swift
@@ -8,54 +8,61 @@ import SymLog
struct WithdrawAcceptDone: View {
private let symLog = SymLogV()
- @AppStorage("myListStyle") var myListStyle: MyListStyle = .automatic
+ let navTitle = String(localized: "Confirm with Bank")
- let confirmTransferUrl: String?
+ let exchangeBaseUrl: String
+ let model: WithdrawModel?
+ let url: URL
- let navTitle = String(localized: "Confirm with Bank")
+ @State private var confirmTransferUrl: String? = nil
+ @State private var transaction: Transaction? = nil
+
+ func reloadOneAction(_ transactionId: String) async throws -> Transaction {
+ if let model {
+ return try await model.getTransactionByIdT(transactionId)
+ } else {
+ throw WalletBackendError.walletCoreError
+ }
+ }
var body: some View {
+#if DEBUG
+ let _ = Self._printChanges()
+ let _ = symLog.vlog() // just to get the # to compare it with
.onAppear & onDisappear
+#endif
VStack {
- Text(navTitle)
- .font(.title)
- .padding()
- List {
- if let confirmTransferUrl {
- let destination = URL(string: confirmTransferUrl)!
- // Show Hint that User should Confirm on bank website
- Text("Waiting for bank confirmation")
- .listRowSeparator(.hidden)
-
-
- Link("Confirm with bank", destination: destination)
- .buttonStyle(TalerButtonStyle(type: .prominent,
narrow: false, aligned: .center))
- // balances will be updated by TransactionStateTransition
- }
+ if let transaction {
+ TransactionDetailView(transaction: transaction,
+ reloadAction: reloadOneAction,
+ doneAction: { dismissTop() })
+ .navigationBarBackButtonHidden(true)
+ .interactiveDismissDisabled() // can only use "Done"
button to dismiss
+ .navigationTitle(navTitle)
+ } else {
+ WithdrawProgressView(message: "Bank Confirmation")
+ .navigationTitle("Loading...")
}
- .listStyle(myListStyle.style).anyView
-
- }
- .interactiveDismissDisabled() // can only use "Done" button to
dismiss
- .navigationBarHidden(true) // no back button, no title
- .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .leading)
- .background(WalletColors().backgroundColor.edgesIgnoringSafeArea(.all))
-
- .safeAreaInset(edge: .bottom) {
- Button("Done", action: { dismissTop() })
- .lineLimit(2)
- .disabled(false)
- .buttonStyle(TalerButtonStyle(type: .bordered, narrow: false,
aligned: .center))
- .padding()
- }
- .navigationTitle(navTitle)
- .onAppear() {
+ }.onAppear() {
+ symLog.log("onAppear")
DebugViewC.shared.setSheetID(SHEET_WITHDRAW_CONFIRM)
+ }.task {
+ do {
+ if let model {
+ let result = try await
model.sendAcceptIntWithdrawalM(exchangeBaseUrl, withdrawURL: url.absoluteString)
+ confirmTransferUrl = result!.confirmTransferUrl
+ transaction = try await
model.getTransactionByIdT(result!.transactionId)
+ }
+ } catch { // TODO: error
+ symLog.log(error.localizedDescription)
+ }
}
}
}
// MARK: -
struct WithdrawAcceptDone_Previews: PreviewProvider {
static var previews: some View {
- WithdrawAcceptDone(confirmTransferUrl: DEMOBANK)
+ WithdrawAcceptDone(exchangeBaseUrl: DEMOEXCHANGE,
+ model: nil,
+ url: URL(string: DEMOSHOP)!)
}
}
diff --git a/TalerWallet1/Views/WithdrawBankIntegrated/WithdrawAcceptView.swift
b/TalerWallet1/Views/WithdrawBankIntegrated/WithdrawAcceptView.swift
index 630f33d..ada134f 100644
--- a/TalerWallet1/Views/WithdrawBankIntegrated/WithdrawAcceptView.swift
+++ b/TalerWallet1/Views/WithdrawBankIntegrated/WithdrawAcceptView.swift
@@ -8,23 +8,26 @@ import SymLog
struct WithdrawAcceptView: View {
private let symLog = SymLogV()
- let url: URL
- var model: WithdrawModel?
-
let navTitle = String(localized: "Accept Withdrawal")
- let detailsForAmount: ManualWithdrawalDetails
- let baseURL: String
+
+ let exchangeBaseUrl: String
+ let model: WithdrawModel?
+ let amount: Amount?
+ let url: URL
@State private var buttonSelected: Int? = nil
@State private var confirmTransferUrl: String? = nil
+ @State private var transactionId: String? = nil
+ @State var manualWithdrawalDetails: ManualWithdrawalDetails?
func acceptAction() -> () {
Task {
do {
if let model {
- if let transferUrl = try await
model.sendAcceptIntWithdrawalM(baseURL, withdrawURL: url.absoluteString) {
- symLog.log(transferUrl)
- confirmTransferUrl = transferUrl
+ if let acceptWithdrawalResponse = try await
model.sendAcceptIntWithdrawalM(exchangeBaseUrl, withdrawURL:
url.absoluteString) {
+ confirmTransferUrl =
acceptWithdrawalResponse.confirmTransferUrl
+ transactionId = acceptWithdrawalResponse.transactionId
+ symLog.log(confirmTransferUrl ?? "❗️Yikes: No
confirmTransferUrl")
buttonSelected = 1 // trigger NavigationLink
} else {
// TODO: error sendAcceptIntWithdrawal failed
@@ -37,35 +40,37 @@ struct WithdrawAcceptView: View {
}
var body: some View {
- List {
- let raw = detailsForAmount.amountRaw
- let effective = detailsForAmount.amountEffective
- let fee = try! Amount.diff(raw, effective) // TODO: different
currencies
- let outColor = WalletColors().transactionColor(false)
- let inColor = WalletColors().transactionColor(true)
+ VStack {
+ if let manualWithdrawalDetails {
+ List {
- HStack(spacing: 0) {
- NavigationLink(destination: LazyView {
- WithdrawAcceptDone(confirmTransferUrl: confirmTransferUrl)
- }, tag: 1, selection: $buttonSelected
- ) { EmptyView() }.frame(width: 0).opacity(0).hidden()
-
- ThreeAmountsView(topTitle: String(localized: "Chosen amount to
withdraw:"),
- topAmount: raw, fee: fee,
- bottomTitle: String(localized: "Coins to be
withdrawn:"),
- bottomAmount: effective,
- large: false, pending: false, incoming: true,
- baseURL: baseURL)
+ HStack(spacing: 0) {
+ NavigationLink(destination: LazyView {
+ WithdrawAcceptDone(model: model,
confirmTransferUrl: confirmTransferUrl, transactionId: transactionId)
+ }, tag: 1, selection: $buttonSelected
+ ) { EmptyView() }.frame(width: 0).opacity(0).hidden()
+
+ ThreeAmountsView(topTitle: String(localized: "Chosen
amount to withdraw:"),
+ topAmount: raw, fee: fee,
+ bottomTitle: String(localized: "Coins
to be withdrawn:"),
+ bottomAmount: effective,
+ large: false, pending: false,
incoming: true,
+ baseURL: exchangeBaseUrl)
+ }
+ }
+ .safeAreaInset(edge: .bottom) {
+ Button("Confirm Withdrawal", action: acceptAction)
+ .lineLimit(2)
+ .disabled(false)
+ .buttonStyle(TalerButtonStyle(type: .prominent,
narrow: false, aligned: .center))
+ .padding()
+ }
+ .navigationTitle(navTitle)
+ } else {
+ WithdrawProgressView(message: exchangeBaseUrl.trimURL())
+ .navigationTitle("Found Exchange")
}
}
- .safeAreaInset(edge: .bottom) {
- Button("Confirm Withdrawal", action: acceptAction)
- .lineLimit(2)
- .disabled(false)
- .buttonStyle(TalerButtonStyle(type: .prominent, narrow: false,
aligned: .center))
- .padding()
- }
- .navigationTitle(navTitle)
// .overlay {
// VStack {
// ErrorView(errortext: "unknown state") // TODO: Error
@@ -75,18 +80,32 @@ struct WithdrawAcceptView: View {
.onAppear() {
DebugViewC.shared.setSheetID(SHEET_WITHDRAW_ACCEPT)
}
+ .task { if let amount, let model {
+ do { // TODO: cancelled
+ symLog.log(".task")
+ if exchangeBaseUrl.hasPrefix(HTTPS) {
+ symLog.log("amount: \(amount), baseURL:
\(String(describing: exchangeBaseUrl))")
+ // TODO: let user choose exchange from list
+ manualWithdrawalDetails = try await
model.loadWithdrawalDetailsForAmountM(exchangeBaseUrl, amount: amount)
+ symLog.log("raw: \(manualWithdrawalDetails!.amountRaw),
effective: \(manualWithdrawalDetails!.amountEffective)")
+ } else {
+ // TODO: error no exchange!
+ }
+ } catch { // TODO: error
+ symLog.log(error.localizedDescription)
+ }
+ } else {
+ // TODO: error no amount!
+ } }
}
}
// MARK: -
struct WithdrawAcceptView_Previews: PreviewProvider {
static var previews: some View {
- let details = ManualWithdrawalDetails(amountRaw: try!
Amount(fromString: LONGCURRENCY + ":2.4"),
- amountEffective: try!
Amount(fromString: LONGCURRENCY + ":2.2"),
- paytoUris: [],
- tosAccepted: true)
- WithdrawAcceptView(url: URL(string: DEMOSHOP)!,
- model: nil,
- detailsForAmount: details,
- baseURL: DEMOEXCHANGE)
+ let amount = try! Amount(fromString: LONGCURRENCY + ":2.4")
+ WithdrawAcceptView(exchangeBaseUrl: DEMOEXCHANGE,
+ model: nil,
+ amount: amount,
+ url: URL(string: DEMOSHOP)!)
}
}
diff --git
a/TalerWallet1/Views/WithdrawBankIntegrated/WithdrawProgressView.swift
b/TalerWallet1/Views/WithdrawBankIntegrated/WithdrawProgressView.swift
index 3599a9b..f623c3a 100644
--- a/TalerWallet1/Views/WithdrawBankIntegrated/WithdrawProgressView.swift
+++ b/TalerWallet1/Views/WithdrawBankIntegrated/WithdrawProgressView.swift
@@ -8,12 +8,16 @@ struct WithdrawProgressView: View {
let message: String
var body: some View {
- Form {
+ VStack {
Spacer()
ProgressView()
Spacer()
- Text(message)
- .font(.title)
+ HStack {
+ Spacer()
+ Text(message)
+ .font(.title)
+ Spacer()
+ }
Spacer()
Spacer()
}
diff --git a/TalerWallet1/Views/WithdrawBankIntegrated/WithdrawURIView.swift
b/TalerWallet1/Views/WithdrawBankIntegrated/WithdrawURIView.swift
index 5a51dfb..6f851ce 100644
--- a/TalerWallet1/Views/WithdrawBankIntegrated/WithdrawURIView.swift
+++ b/TalerWallet1/Views/WithdrawBankIntegrated/WithdrawURIView.swift
@@ -3,6 +3,7 @@
* 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 bank's website
@@ -10,41 +11,67 @@ import SymLog
// after the user confirmed the withdrawal, we remind them to return to the
bank website to confirm there, too
struct WithdrawURIView: View {
private let symLog = SymLogV()
+ let navTitle = String(localized: "Accept Withdrawal")
+
// the URL from the bank website
- var url: URL
+ let url: URL
let model = WithdrawModel.model(baseURL: "global") // TODO: get
baseURL from URL
// the exchange used for this withdrawal.
- @State var exchangeBaseUrl: String = ""
- @State var manualWithdrawalDetails: ManualWithdrawalDetails?
- @State var didAcceptTOS: Bool = false
+ @State private var exchangeBaseUrl: String? = nil
+ @State private var manualWithdrawalDetails: ManualWithdrawalDetails?
var body: some View {
let badURL = "Error in URL: \(url)"
VStack {
- if !didAcceptTOS { // user must accept ToS first
- WithdrawTOSView(exchangeBaseUrl: exchangeBaseUrl,
- model: model,
- viewID: SHEET_WITHDRAW_TOS) {
- didAcceptTOS = true
+ if let manualWithdrawalDetails, let exchangeBaseUrl {
+ List {
+ let raw = manualWithdrawalDetails.amountRaw
+ let effective = manualWithdrawalDetails.amountEffective
+ let currency = raw.currencyStr
+ let fee = try! Amount.diff(raw, effective)
+ let outColor = WalletColors().transactionColor(false)
+ let inColor = WalletColors().transactionColor(true)
+
+ ThreeAmountsView(topTitle: String(localized: "Chosen
amount to withdraw:"),
+ topAmount: raw, fee: fee,
+ bottomTitle: String(localized: "\(currency)
to be withdrawn:"),
+ bottomAmount: effective,
+ large: false, pending: false,
incoming: true,
+ baseURL: exchangeBaseUrl)
+ let someCoins = SomeCoins(details: manualWithdrawalDetails)
+ QuiteSomeCoins(someCoins: someCoins, shouldShowFee: false,
+ currency: raw.currencyStr, amountEffective:
effective)
}
- } else { // show Amount details and let user accept
- WithdrawAcceptView(url: url, model: model,
- detailsForAmount: manualWithdrawalDetails!,
- baseURL: exchangeBaseUrl)
- }
- }
- .overlay {
- if !exchangeBaseUrl.hasPrefix(HTTPS) {
- WithdrawProgressView(message: url.host ?? badURL)
- .navigationTitle("Contacting Exchange")
- } else if manualWithdrawalDetails == nil {
- WithdrawProgressView(message: exchangeBaseUrl.trimURL())
- .navigationTitle("Found Exchange")
+ .navigationTitle(navTitle)
+ let tosAccepted = manualWithdrawalDetails.tosAccepted
+ if tosAccepted {
+ NavigationLink(destination: LazyView {
+ WithdrawAcceptDone(exchangeBaseUrl: exchangeBaseUrl,
model: model, url: url)
+ }) {
+ Text("Confirm Withdrawal") //
SHEET_WITHDRAW_ACCEPT
+ }.buttonStyle(TalerButtonStyle(type: .prominent))
+ .padding()
+ } else {
+ NavigationLink(destination: LazyView {
+ WithdrawTOSView(exchangeBaseUrl: exchangeBaseUrl,
+ model: model,
+ viewID: SHEET_WITHDRAW_TOS,
+ acceptAction: nil) // pop
back to here
+ }) {
+ Text("Check Terms of Service") // VIEW_WITHDRAW_TOS
+ }.buttonStyle(TalerButtonStyle(type: .prominent))
+ .padding()
+ }
+ } else {
+ // Yikes no details or no baseURL
+// WithdrawProgressView(message: url.host ?? badURL)
+// .navigationTitle("Contacting Exchange")
}
}
.onAppear() {
+ symLog.log("onAppear")
DebugViewC.shared.setSheetID(SHEET_WITHDRAWAL)
}
.task {
@@ -57,19 +84,17 @@ struct WithdrawURIView: View {
} else if let first = withdrawUriInfo.possibleExchanges.first {
exchangeBaseUrl = first.exchangeBaseUrl
}
- if exchangeBaseUrl.hasPrefix(HTTPS) {
- symLog.log("amount: \(amount), baseURL:
\(String(describing: exchangeBaseUrl))")
- // TODO: let user choose exchange from list
- manualWithdrawalDetails = try await
model.loadWithdrawalDetailsForAmountM(exchangeBaseUrl, amount: amount)
- symLog.log("raw: \(manualWithdrawalDetails!.amountRaw),
effective: \(manualWithdrawalDetails!.amountEffective)")
- if manualWithdrawalDetails!.tosAccepted {
- didAcceptTOS = true
- }
- } else {
- // TODO: error no exchange!
+ if let exchangeBaseUrl {
+ let details = try await
model.loadWithdrawalDetailsForAmountM(exchangeBaseUrl, amount: amount)
+ manualWithdrawalDetails = details
+// agePicker.setAges(ages: details?.ageRestrictionOptions)
+ } else { // TODO: error
+ symLog.log("no exchangeBaseUrl")
+ manualWithdrawalDetails = nil
}
} catch { // TODO: error
symLog.log(error.localizedDescription)
+ manualWithdrawalDetails = nil
}
}
}
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.
- [taler-taler-ios] branch master updated (7ce9180 -> f7f01e5), gnunet, 2023/06/30
- [taler-taler-ios] 02/54: Moved AgePicker in its own file, gnunet, 2023/06/30
- [taler-taler-ios] 05/54: cleanup, back to Swift 5.8 (for now until Xcode 15 is usable), gnunet, 2023/06/30
- [taler-taler-ios] 04/54: PopToRoot instead of dismiss sheet, gnunet, 2023/06/30
- [taler-taler-ios] 03/54: Cleaned up buttons, gnunet, 2023/06/30
- [taler-taler-ios] 11/54: Accessibility, gnunet, 2023/06/30
- [taler-taler-ios] 18/54: remove loaded, gnunet, 2023/06/30
- [taler-taler-ios] 09/54: Launch animation, SideBarView, gnunet, 2023/06/30
- [taler-taler-ios] 01/54: Big update after DD37, gnunet, 2023/06/30
- [taler-taler-ios] 13/54: Overhaul withdraw + p2p,
gnunet <=
- [taler-taler-ios] 17/54: for debugging time-outs, gnunet, 2023/06/30
- [taler-taler-ios] 10/54: Reduce Logging, gnunet, 2023/06/30
- [taler-taler-ios] 12/54: Localization, gnunet, 2023/06/30
- [taler-taler-ios] 08/54: Preparations for localization + accessability, gnunet, 2023/06/30
- [taler-taler-ios] 19/54: remove dismissFirst, gnunet, 2023/06/30
- [taler-taler-ios] 14/54: Made Model a Singleton, gnunet, 2023/06/30
- [taler-taler-ios] 40/54: TransactionType, gnunet, 2023/06/30
- [taler-taler-ios] 26/54: PeerPullDebit, gnunet, 2023/06/30
- [taler-taler-ios] 16/54: Dummy, gnunet, 2023/06/30
- [taler-taler-ios] 34/54: sizeCategory, task, gnunet, 2023/06/30