[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[taler-taler-ios] branch master updated (be6a335 -> 989c5ea)
From: |
gnunet |
Subject: |
[taler-taler-ios] branch master updated (be6a335 -> 989c5ea) |
Date: |
Tue, 05 Dec 2023 16:25:56 +0100 |
This is an automated email from the git hooks/post-receive script.
marc-stibane pushed a change to branch master
in repository taler-ios.
from be6a335 Bump version to 0.9.3 (28)
new 95c1c61 Logging
new 5c3654d New "flags"
new ecb2d78 Fix KYC/Confirm
new 5cc946b ViewThatFits
new 6482d33 Refund
new ced4d03 Exchange: ToS
new 0ab51f8 Only main title
new 07efeed talerURI only sent if valid
new cfd6c03 cleanup
new ce739ae increasedContrast
new d0d5a75 Payment: show what to pay for
new f00e31a Preparation for withdraw-exchange
new 957c7ee Exchange icon
new 6c89fb8 Bump version to 0.9.3 (29)
new b08eb3a bugfix for inputDigits=0
new 820d8b3 cleanup
new a881bb8 currency & -Info
new 6af1cf7 cleanup, en/disable button
new 7516be0 use #0042b3
new e1bf44f Bump version to 0.9.3 (30)
new dee6404 amountToTransfer
new fa2041e cleanup
new 390fce1 shortcutAction
new 989c5ea Debugging
The 24 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
TalerWallet.xcodeproj/project.pbxproj | 24 +++-
.../taler-logo-2023-blue.svg | 2 +-
TalerWallet1/Backend/WalletCore.swift | 6 +-
TalerWallet1/Controllers/Controller.swift | 18 ++-
TalerWallet1/Controllers/DebugViewC.swift | 24 ++--
TalerWallet1/Model/Model+Balances.swift | 31 +++--
TalerWallet1/Model/Model+P2P.swift | 2 +-
TalerWallet1/Model/Model+Refund.swift | 54 +++++++++
TalerWallet1/Model/Model+Withdraw.swift | 21 +++-
TalerWallet1/Model/Transaction.swift | 5 +-
TalerWallet1/Views/Balances/BalanceRowView.swift | 60 +++++----
TalerWallet1/Views/Balances/BalancesListView.swift | 2 +-
.../Views/Balances/BalancesSectionView.swift | 69 ++++-------
TalerWallet1/Views/Balances/TwoRowButtons.swift | 53 ++++----
TalerWallet1/Views/Exchange/ExchangeRowView.swift | 134 +++++++++++----------
.../Views/Exchange/ExchangeSectionView.swift | 14 +--
TalerWallet1/Views/Exchange/ManualWithdraw.swift | 132 +++++++++++---------
TalerWallet1/Views/HelperViews/AmountRowV.swift | 2 +-
.../Views/HelperViews/CurrencyInputView.swift | 16 ++-
TalerWallet1/Views/Main/MainView.swift | 4 +-
TalerWallet1/Views/Peer2peer/P2PReadyV.swift | 18 +--
TalerWallet1/Views/Peer2peer/P2PSubjectV.swift | 67 ++++++++---
TalerWallet1/Views/Peer2peer/RequestPayment.swift | 65 +++++-----
TalerWallet1/Views/Peer2peer/SendAmount.swift | 69 ++++++-----
.../Views/Sheets/Payment/PayTemplateView.swift | 2 +-
.../Views/Sheets/Payment/PaymentView.swift | 3 +
.../Views/Sheets/Refund/RefundURIView.swift | 60 +++++++++
TalerWallet1/Views/Sheets/URLSheet.swift | 6 +
.../WithdrawBankIntegrated/WithdrawTOSView.swift | 18 ++-
.../Views/Transactions/TransactionDetailView.swift | 96 +++++++++------
.../Views/Transactions/TransactionRowView.swift | 19 ++-
TestFlight/WhatToTest.en-US.txt | 23 +++-
taler-swift/Sources/taler-swift/Amount.swift | 58 +++++----
33 files changed, 736 insertions(+), 441 deletions(-)
create mode 100644 TalerWallet1/Model/Model+Refund.swift
create mode 100644 TalerWallet1/Views/Sheets/Refund/RefundURIView.swift
diff --git a/TalerWallet.xcodeproj/project.pbxproj
b/TalerWallet.xcodeproj/project.pbxproj
index 5df7760..2b59bc8 100644
--- a/TalerWallet.xcodeproj/project.pbxproj
+++ b/TalerWallet.xcodeproj/project.pbxproj
@@ -246,6 +246,10 @@
4EFA39612AA7946B00742548 /* ToSButtonView.swift in Sources */ =
{isa = PBXBuildFile; fileRef = 4EFA395F2AA7946B00742548 /* ToSButtonView.swift
*/; };
ABC13AA32859962800D23185 /* taler-swift in Frameworks */ = {isa
= PBXBuildFile; productRef = ABC13AA22859962800D23185 /* taler-swift */; };
ABE97B1D286D82BF00580772 /* AnyCodable in Frameworks */ = {isa
= PBXBuildFile; productRef = ABE97B1C286D82BF00580772 /* AnyCodable */; };
+ E37AA62A2AF197E5003850CF /* Model+Refund.swift in Sources */ =
{isa = PBXBuildFile; fileRef = E37AA6292AF197E5003850CF /* Model+Refund.swift
*/; };
+ E37AA62B2AF197E5003850CF /* Model+Refund.swift in Sources */ =
{isa = PBXBuildFile; fileRef = E37AA6292AF197E5003850CF /* Model+Refund.swift
*/; };
+ E37AA62E2AF19BE0003850CF /* RefundURIView.swift in Sources */ =
{isa = PBXBuildFile; fileRef = E37AA62D2AF19BE0003850CF /* RefundURIView.swift
*/; };
+ E37AA62F2AF19BE0003850CF /* RefundURIView.swift in Sources */ =
{isa = PBXBuildFile; fileRef = E37AA62D2AF19BE0003850CF /* RefundURIView.swift
*/; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -413,6 +417,8 @@
D14AFD1D24D232B300C51073 /* Taler_Wallet.app */ = {isa =
PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0;
path = Taler_Wallet.app; sourceTree = BUILT_PRODUCTS_DIR; };
D14AFD3324D232B500C51073 /* TalerTests.xctest */ = {isa =
PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path
= TalerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
D14AFD3E24D232B500C51073 /* TalerUITests.xctest */ = {isa =
PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path
= TalerUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
+ E37AA6292AF197E5003850CF /* Model+Refund.swift */ = {isa =
PBXFileReference; lastKnownFileType = sourcecode.swift; path =
"Model+Refund.swift"; sourceTree = "<group>"; };
+ E37AA62D2AF19BE0003850CF /* RefundURIView.swift */ = {isa =
PBXFileReference; lastKnownFileType = sourcecode.swift; path =
RefundURIView.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -607,6 +613,7 @@
4ECB627F2A0BA6DF004ABBB7 /* Model+P2P.swift */,
4EB0954C2989CBFE0043A8A1 /* Model+Pending.swift
*/,
4EB0952C2989CBFE0043A8A1 /* Model+Payment.swift
*/,
+ E37AA6292AF197E5003850CF /* Model+Refund.swift */,
4EB095102989CBB00043A8A1 /*
Model+Settings.swift */,
4EB095322989CBFE0043A8A1 /*
Model+Transactions.swift */,
4EB0953D2989CBFE0043A8A1 /*
Model+Withdraw.swift */,
@@ -765,6 +772,7 @@
4EB095332989CBFE0043A8A1 /* URLSheet.swift */,
4EB0953B2989CBFE0043A8A1 /*
WithdrawBankIntegrated */,
4EB0952A2989CBFE0043A8A1 /* Payment */,
+ E37AA62C2AF19BA6003850CF /* Refund */,
4E3B4BBF2A41E64000CC88B8 /* P2P_Sheets */,
);
path = Sheets;
@@ -813,6 +821,14 @@
path = TalerUITests;
sourceTree = "<group>";
};
+ E37AA62C2AF19BA6003850CF /* Refund */ = {
+ isa = PBXGroup;
+ children = (
+ E37AA62D2AF19BE0003850CF /* RefundURIView.swift
*/,
+ );
+ path = Refund;
+ sourceTree = "<group>";
+ };
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@@ -1091,6 +1107,7 @@
4E3EAE5C2A990778009F1BE8 /* Model+Pending.swift
in Sources */,
4E3EAE5D2A990778009F1BE8 /*
ExchangeListView.swift in Sources */,
4E3EAE5E2A990778009F1BE8 /*
WithdrawProgressView.swift in Sources */,
+ E37AA62E2AF19BE0003850CF /* RefundURIView.swift
in Sources */,
4E3EAE5F2A990778009F1BE8 /* QRSheet.swift in
Sources */,
4E3EAE602A990778009F1BE8 /*
P2pReceiveURIView.swift in Sources */,
4E3EAE612A990778009F1BE8 /* ListStyle.swift in
Sources */,
@@ -1098,6 +1115,7 @@
4E3EAE632A990778009F1BE8 /* WalletCore.swift in
Sources */,
4E3EAE642A990778009F1BE8 /*
LaunchAnimationView.swift in Sources */,
4E3EAE652A990778009F1BE8 /* SideBarView.swift
in Sources */,
+ E37AA62A2AF197E5003850CF /* Model+Refund.swift
in Sources */,
4E3EAE682A990778009F1BE8 /* WalletModel.swift
in Sources */,
4E3EAE692A990778009F1BE8 /* URLSheet.swift in
Sources */,
4E3EAE6A2A990778009F1BE8 /* ThreeAmountsV.swift
in Sources */,
@@ -1196,6 +1214,7 @@
4EB0956E2989CBFE0043A8A1 /* Model+Pending.swift
in Sources */,
4EB095522989CBFE0043A8A1 /*
ExchangeListView.swift in Sources */,
4EB095642989CBFE0043A8A1 /*
WithdrawProgressView.swift in Sources */,
+ E37AA62F2AF19BE0003850CF /* RefundURIView.swift
in Sources */,
4EEC157A29F9427F00D46A03 /* QRSheet.swift in
Sources */,
4E3B4BC12A41E6C200CC88B8 /*
P2pReceiveURIView.swift in Sources */,
4E6EDD872A363D8D0031D520 /* ListStyle.swift in
Sources */,
@@ -1203,6 +1222,7 @@
4EB095202989CBCB0043A8A1 /* WalletCore.swift in
Sources */,
4EB095672989CBFE0043A8A1 /*
LaunchAnimationView.swift in Sources */,
4EB095662989CBFE0043A8A1 /* SideBarView.swift
in Sources */,
+ E37AA62B2AF197E5003850CF /* Model+Refund.swift
in Sources */,
4EB095162989CBB00043A8A1 /* WalletModel.swift
in Sources */,
4EB0955A2989CBFE0043A8A1 /* URLSheet.swift in
Sources */,
4ED2F94B2A278F5100453B40 /* ThreeAmountsV.swift
in Sources */,
@@ -1464,7 +1484,7 @@
CODE_SIGN_ENTITLEMENTS =
"$(TARGET_NAME).entitlements";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 28;
+ CURRENT_PROJECT_VERSION = 30;
DEVELOPMENT_TEAM = GUDDQ9428Y;
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
@@ -1506,7 +1526,7 @@
CODE_SIGN_ENTITLEMENTS =
"$(TARGET_NAME).entitlements";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 28;
+ CURRENT_PROJECT_VERSION = 30;
DEVELOPMENT_TEAM = GUDDQ9428Y;
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
diff --git
a/TalerWallet1/Assets.xcassets/taler-logo-2023-blue.imageset/taler-logo-2023-blue.svg
b/TalerWallet1/Assets.xcassets/taler-logo-2023-blue.imageset/taler-logo-2023-blue.svg
index b6d9918..39877da 100644
---
a/TalerWallet1/Assets.xcassets/taler-logo-2023-blue.imageset/taler-logo-2023-blue.svg
+++
b/TalerWallet1/Assets.xcassets/taler-logo-2023-blue.imageset/taler-logo-2023-blue.svg
@@ -1,5 +1,5 @@
<svg viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg">
-<g id="aa" style="fill:blue;fill-rule:evenodd">
+<g id="aa" style="fill:#0042b3;fill-rule:evenodd">
<!-- 90% -->
<path d="M57.6 43.4
c-25.5 4.3-44.9 28-44.9 56.5 0 31.5 23.9 57.2 53.3 57.2
diff --git a/TalerWallet1/Backend/WalletCore.swift
b/TalerWallet1/Backend/WalletCore.swift
index 8c8ebde..76ba1ab 100644
--- a/TalerWallet1/Backend/WalletCore.swift
+++ b/TalerWallet1/Backend/WalletCore.swift
@@ -153,7 +153,7 @@ extension WalletCore {
userInfo: [AnyHashable: Any]? = nil) {
Task { // runs on MainActor
await postNotificationM(aName, object: anObject, userInfo:
userInfo)
- logger.log("Notification sent: \(aName.rawValue)")
+ logger.info("Notification sent: \(aName.rawValue)")
}
}
@@ -200,7 +200,7 @@ extension WalletCore {
postNotification(.TransactionDone, userInfo:
[TRANSACTIONTRANSITION: decoded])
return
case .expired:
- logger.log("Expired: \(decoded.transactionId,
privacy: .private(mask: .hash))")
+ logger.warning("Expired: \(decoded.transactionId,
privacy: .private(mask: .hash))")
Controller.shared.playSound(0)
postNotification(.TransactionExpired, userInfo:
[TRANSACTIONTRANSITION: decoded])
return
@@ -224,7 +224,7 @@ extension WalletCore {
logger.log("Pending: \(decoded.transactionId,
privacy: .private(mask: .hash))")
postNotification(.TransactionStateTransition,
userInfo: [TRANSACTIONTRANSITION: decoded])
default:
- logger.log("Yikes: \(decoded.transactionId,
privacy: .private(mask: .hash))")
+ logger.warning("Unknow transition:
\(decoded.transactionId, privacy: .private(mask: .hash))")
postNotification(.TransactionStateTransition,
userInfo: [TRANSACTIONTRANSITION: decoded])
} // switch
} // type
diff --git a/TalerWallet1/Controllers/Controller.swift
b/TalerWallet1/Controllers/Controller.swift
index 23964cc..05f5d77 100644
--- a/TalerWallet1/Controllers/Controller.swift
+++ b/TalerWallet1/Controllers/Controller.swift
@@ -20,10 +20,12 @@ enum BackendState {
enum UrlCommand {
case unknown
case withdraw
+ case withdrawExchange
case pay
case payPull
case payPush
case payTemplate
+ case refund
case reward
}
@@ -157,18 +159,22 @@ extension Controller {
}
switch command {
case "withdraw":
- return UrlCommand.withdraw
+ return .withdraw
+ case "withdraw-exchange":
+ return .withdrawExchange
case "pay":
- return UrlCommand.pay
+ return .pay
case "pay-pull":
- return UrlCommand.payPull
+ return .payPull
case "pay-push":
- return UrlCommand.payPush
+ return .payPush
case "pay-template":
- return UrlCommand.payTemplate
+ return .payTemplate
+ case "refund":
+ return .refund
default:
symLog.log("unknown command taler://\(command)")
}
- return UrlCommand.unknown
+ return .unknown
}
}
diff --git a/TalerWallet1/Controllers/DebugViewC.swift
b/TalerWallet1/Controllers/DebugViewC.swift
index b135dfd..fd6551b 100644
--- a/TalerWallet1/Controllers/DebugViewC.swift
+++ b/TalerWallet1/Controllers/DebugViewC.swift
@@ -170,31 +170,29 @@ class DebugViewC: ObservableObject {
logger.log("\(newID, privacy: .public) stays")
// don't set viewID to the same value, it would just trigger
an unneccessary redraw
}
- } else if viewID > 0 {
- logger.log("switching OFF, will not use \(newID, privacy:
.public)")
- viewID = 0 // publish OFF
} else {
- logger.log("off, will not use \(newID, privacy: .public)")
- // don't set viewID from 0 to 0 again, it would just trigger an
unneccessary redraw
+ logger.log("view \(newID, privacy: .public)")
+ if viewID > 0 {
+ viewID = 0 // publish OFF
+ }
}
}
@MainActor func setSheetID(_ newID: Int) -> Void {
if developerMode {
if sheetID != newID {
- logger.log("switching from \(self.sheetID, privacy: .public)
to \(newID, privacy: .public) for sheet")
+ logger.log("sheet switching from \(self.sheetID, privacy:
.public) to \(newID, privacy: .public)")
sheetID = newID // publish new
sheetID
} else {
- logger.log("\(newID, privacy: .public) stays for sheet")
+ logger.log("sheet \(newID, privacy: .public) stays")
// don't set sheetID to the same value, it would just trigger
an unneccessary redraw
}
- } else if sheetID > 0 {
- // might happen after switching DevMode off, if sheetID still has
the old value of the last sheet
- logger.log("switching OFF, will not use \(newID, privacy: .public)
for sheet")
- sheetID = 0 // publish OFF
} else {
- logger.log("off, will not use \(newID, privacy: .public) for
sheet")
- // don't set sheetID from 0 to 0 again, it would just trigger an
unneccessary redraw
+ logger.log("sheet \(newID, privacy: .public)")
+ if sheetID > 0 {
+ // might happen after switching DevMode off, if sheetID still
has the old value of the last sheet
+ sheetID = 0 // publish OFF
+ }
}
}
}
diff --git a/TalerWallet1/Model/Model+Balances.swift
b/TalerWallet1/Model/Model+Balances.swift
index 1bab4ca..6d4be7f 100644
--- a/TalerWallet1/Model/Model+Balances.swift
+++ b/TalerWallet1/Model/Model+Balances.swift
@@ -7,25 +7,36 @@ import taler_swift
fileprivate let ASYNCDELAY: UInt = 0 //set e.g to 6 or 9 seconds for
debugging
// MARK: -
+
+enum BalanceFlag: String, Codable {
+ case incomingAml = "incoming-aml"
+ case incomingConfirmation = "incoming-confirmation"
+ case incomingKyc = "incoming-kyc"
+ case outgoingKyc = "outgoing-kyc"
+}
+
/// A currency balance
struct Balance: Decodable, Hashable, Sendable {
- var available: Amount
var scopeInfo: ScopeInfo
- var requiresUserInput: Bool
- var hasPendingTransactions: Bool
+ var available: Amount
+ var pendingIncoming: Amount
+ var pendingOutgoing: Amount
+ var flags: [BalanceFlag]
public static func == (lhs: Balance, rhs: Balance) -> Bool {
- return lhs.available == rhs.available &&
- lhs.scopeInfo == rhs.scopeInfo &&
- lhs.requiresUserInput == rhs.requiresUserInput &&
- lhs.hasPendingTransactions == rhs.hasPendingTransactions
+ lhs.scopeInfo == rhs.scopeInfo
+ && lhs.available == rhs.available
+ && lhs.pendingIncoming == rhs.pendingIncoming
+ && lhs.pendingOutgoing == rhs.pendingOutgoing
+ && lhs.flags == rhs.flags
}
public func hash(into hasher: inout Hasher) {
- hasher.combine(available)
hasher.combine(scopeInfo)
- hasher.combine(requiresUserInput)
- hasher.combine(hasPendingTransactions)
+ hasher.combine(available)
+ hasher.combine(pendingIncoming)
+ hasher.combine(pendingOutgoing)
+ hasher.combine(flags)
}
}
// MARK: -
diff --git a/TalerWallet1/Model/Model+P2P.swift
b/TalerWallet1/Model/Model+P2P.swift
index 82e5bc4..8a0d003 100644
--- a/TalerWallet1/Model/Model+P2P.swift
+++ b/TalerWallet1/Model/Model+P2P.swift
@@ -72,7 +72,7 @@ struct InitiatePeerPushDebitResponse: Codable {
let mergePriv: String
let pursePub: String
let exchangeBaseUrl: String
- let talerUri: String
+ let talerUri: String?
let transactionId: String
}
fileprivate struct InitiatePeerPushDebit: WalletBackendFormattedRequest {
diff --git a/TalerWallet1/Model/Model+Refund.swift
b/TalerWallet1/Model/Model+Refund.swift
new file mode 100644
index 0000000..4892c61
--- /dev/null
+++ b/TalerWallet1/Model/Model+Refund.swift
@@ -0,0 +1,54 @@
+/*
+ * This file is part of GNU Taler, ©2022-23 Taler Systems S.A.
+ * See LICENSE.md
+ */
+import Foundation
+fileprivate let ASYNCDELAY: UInt = 0 //set e.g to 6 or 9 seconds for
debugging
+
+// MARK: -
+/// A request to prepare a refund with an obtained URI
+struct StartRefundURIRequest: WalletBackendFormattedRequest {
+ func operation() -> String { "startRefundQueryForUri" }
+ func args() -> Args { Args(talerRefundUri: talerRefundUri) }
+
+ var talerRefundUri: String
+
+ struct Args: Encodable {
+ var talerRefundUri: String
+ }
+
+ /// returns the txID of the new refund
+ struct Response: Decodable {
+ var transactionId: String
+ }
+}
+
+/// A request to prepare a refund with a transactionID
+struct StartRefundQueryRequest: WalletBackendFormattedRequest {
+ func operation() -> String { "startRefundQuery" }
+ func args() -> Args { Args(transactionId: transactionId) }
+
+ var transactionId: String
+
+ struct Args: Encodable {
+ var transactionId: String
+ }
+
+ /// no error means the refunds was successful
+ struct Response: Decodable {}
+}
+// MARK: -
+extension WalletModel {
+ @MainActor
+ func startRefundForUriM(url: String) async throws -> String {
+ let request = StartRefundURIRequest(talerRefundUri: url)
+ let response = try await sendRequest(request, ASYNCDELAY)
+ return response.transactionId
+ }
+
+ @MainActor
+ func startRefundM(transactionId: String) async throws {
+ let request = StartRefundQueryRequest(transactionId: transactionId)
+ let _ = try await sendRequest(request, ASYNCDELAY)
+ }
+}
diff --git a/TalerWallet1/Model/Model+Withdraw.swift
b/TalerWallet1/Model/Model+Withdraw.swift
index e86f394..8563df4 100644
--- a/TalerWallet1/Model/Model+Withdraw.swift
+++ b/TalerWallet1/Model/Model+Withdraw.swift
@@ -7,6 +7,21 @@ import taler_swift
import SymLog
fileprivate let ASYNCDELAY: UInt = 0 //set e.g to 6 or 9 seconds for
debugging
+enum AccountRestrictionType: String, Decodable {
+ case deny
+ case regex
+}
+struct AccountRestriction: Decodable {
+ var type: AccountRestrictionType
+ var payto_regex: String?
+ var human_hint: String?
+ var human_hint_i18n: String?
+}
+struct WithdrawalExchangeAccountDetails: Decodable {
+ var paytoUri: String
+ var transferAmount: Amount
+ var creditRestrictions: [AccountRestriction]?
+}
// MARK: -
/// The result from getWithdrawalDetailsForUri
struct WithdrawUriInfoResponse: Decodable {
@@ -31,9 +46,10 @@ struct WithdrawalAmountDetails: Decodable {
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
+ var withdrawalAccountsList: [WithdrawalExchangeAccountDetails]?
+ var ageRestrictionOptions: [Int]? // Array of ages
+ var scopeInfo: ScopeInfo
}
/// A request to get an exchange's withdrawal details.
fileprivate struct GetWithdrawalDetailsForAmount:
WalletBackendFormattedRequest {
@@ -117,6 +133,7 @@ fileprivate struct AcceptBankIntegratedWithdrawal:
WalletBackendFormattedRequest
struct AcceptManualWithdrawalResult: Decodable {
var reservePub: String
var exchangePaytoUris: [String]
+ var withdrawalAccountsList: [WithdrawalExchangeAccountDetails]
var transactionId: String
}
/// A request to accept a manual withdrawl.
diff --git a/TalerWallet1/Model/Transaction.swift
b/TalerWallet1/Model/Transaction.swift
index a834698..75c88a3 100644
--- a/TalerWallet1/Model/Transaction.swift
+++ b/TalerWallet1/Model/Transaction.swift
@@ -266,13 +266,14 @@ struct WithdrawalTransaction : Sendable{
}
struct PaymentTransactionDetails: Decodable {
+ var info: OrderShortInfo
var proposalId: String
var totalRefundRaw: Amount
var totalRefundEffective: Amount
var refundPending: Amount?
+ var refunds: [String]? // array of refund txIDs for this payment
var refundQueryActive: Bool?
- var refunds: [String]? // TODO: array type?
- var info: OrderShortInfo
+ var posConfirmation: String?
}
struct PaymentTransaction : Sendable{
diff --git a/TalerWallet1/Views/Balances/BalanceRowView.swift
b/TalerWallet1/Views/Balances/BalanceRowView.swift
index 962f2fa..37222f0 100644
--- a/TalerWallet1/Views/Balances/BalanceRowView.swift
+++ b/TalerWallet1/Views/Balances/BalanceRowView.swift
@@ -30,7 +30,6 @@ struct BalanceButton: View {
Text(title)
.accessibilityFont(.title2)
.foregroundColor(colorSchemeContrast == .increased
? .primary : .secondary)
-// .foregroundColor(moreContrast ? .primary :
.secondary)
}
}
}
@@ -59,48 +58,45 @@ struct BalanceRowView: View {
let sendTitle0 = String(localized: "SendButton_Short", defaultValue:
"Send",
comment: "Abbreviation of button `Send Money´")
- let sendTitle1 = String(localized: "SendButton_Top", defaultValue: "Send",
- comment: "Top (first half) of button `Send
Money´")
- let sendTitle2 = String(localized: "SendButton_Bottom", defaultValue:
"Money",
- comment: "Bottom (second half) of button `Send
Money´")
+ let sendTitle1 = String(localized: "SendButton_Full", defaultValue:
"Send\tMoney",
+ comment: "`Send Money´ in Balances - set exactly
1 \\t for line break")
+
let requestTitle0 = String(localized: "RequestButton_Short", defaultValue:
"Request",
comment: "Abbreviation of button `Request
Payment´")
- let requestTitle1 = String(localized: "RequestButton_Top", defaultValue:
"Request",
- comment: "Top (first half) of button `Request
Payment´")
- let requestTitle2 = String(localized: "RequestButton_Bottom",
defaultValue: "Payment",
- comment: "Bottom (second half) of button
`Request Payment´")
-
+ let requestTitle1 = String(localized: "RequestButton_Full", defaultValue:
"Request\tPayment",
+ comment: "`Request Payment´ in Balances - set
exactly 1 \\t for line break")
var body: some View {
- SingleAxisGeometryReader { width in
- VStack (alignment: .trailing) {
- let currencyInfo = controller.info(for: amount.currencyStr,
controller.currencyTicker)
- let amountStr = amount.string(currencyInfo)
- BalanceButton(amountStr: amountStr,
- sizeCategory: sizeCategory,
- rowAction: rowAction)
- let uiFont = TalerFont.uiFont(.title3)
- let titles = iconOnly ? [(sendTitle0, uiFont), (requestTitle0,
uiFont)]
- : [(sendTitle1, uiFont), (sendTitle2, uiFont),
(requestTitle1, uiFont), (requestTitle2, uiFont)]
- let fitsSideBySide = Self.fitsSideBySide(titles,
availableWidth: width, sizeCategory: sizeCategory, padding: 10)
- let twoRowButtons = TwoRowButtons(sendTitles: iconOnly ?
(sendTitle0, nil) : (sendTitle1, sendTitle2),
- recvTitles: iconOnly ?
(requestTitle0, nil) : (requestTitle1, requestTitle2),
- fitsSideBySide: fitsSideBySide,
- lineLimit: 5,
- sendDisabled: amount.isZero,
- sendAction: sendAction,
- recvAction: recvAction)
- if fitsSideBySide {
- HStack(spacing: HSPACING) { twoRowButtons }
- } else {
+ VStack (alignment: .trailing) {
+ let currencyInfo = controller.info(for: amount.currencyStr,
controller.currencyTicker)
+ let amountStr = amount.string(currencyInfo)
+ BalanceButton(amountStr: amountStr,
+ sizeCategory: sizeCategory,
+ rowAction: rowAction)
+
+ let sendTitle = iconOnly ? sendTitle0 : sendTitle1
+ let requTitle = iconOnly ? requestTitle0 : requestTitle1
+ let twoRowButtons = TwoRowButtons(sendTitle: sendTitle,
+ recvTitle: requTitle,
+ fitsSideBySide: false,
+ lineLimit: 5,
+ sendDisabled: amount.isZero,
+ sendAction: sendAction,
+ recvAction: recvAction)
+ if #available(iOS 16.0, *) {
+ ViewThatFits(in: .horizontal) {
+ HStack(spacing: HSPACING) {
+ twoRowButtons.makeCopy(fitsSideBySide: true)
+ }
VStack { twoRowButtons }
}
+ } else { // view for iOS 15
+ VStack { twoRowButtons }
}
}
}
}
// MARK: -
#if DEBUG
-
struct BalanceRowView_Previews: PreviewProvider {
@MainActor
struct StateContainer: View {
diff --git a/TalerWallet1/Views/Balances/BalancesListView.swift
b/TalerWallet1/Views/Balances/BalancesListView.swift
index f7ee719..b425948 100644
--- a/TalerWallet1/Views/Balances/BalancesListView.swift
+++ b/TalerWallet1/Views/Balances/BalancesListView.swift
@@ -22,7 +22,7 @@ struct BalancesListView: View {
@EnvironmentObject private var model: WalletModel
@State private var lastReloadedBalances = 0
- @State private var amountToTransfer = Amount.zero(currency: "")
// Update currency when used
+ @State private var amountToTransfer = Amount.zero(currency: EMPTYSTRING)
// Update currency when used
@State private var summary: String = ""
@State private var showQRScanner: Bool = false
@State private var showCameraAlert: Bool = false
diff --git a/TalerWallet1/Views/Balances/BalancesSectionView.swift
b/TalerWallet1/Views/Balances/BalancesSectionView.swift
index 5b07055..f6306d1 100644
--- a/TalerWallet1/Views/Balances/BalancesSectionView.swift
+++ b/TalerWallet1/Views/Balances/BalancesSectionView.swift
@@ -78,7 +78,7 @@ extension BalancesSectionView: View {
if pendingTransactions.count > 0 {
BalancesPendingRowView(symLog: symLog,
stack: stack.push(),
- currency: currency,
+ balance: balance,
pendingTransactions: $pendingTransactions,
reloadPending: reloadPending,
reloadOneAction: reloadOneAction)
@@ -113,7 +113,7 @@ extension BalancesSectionView: View {
if !iconOnly {
Text("Recent transactions")
.accessibilityFont(.callout)
-// .foregroundColor(moreContrast ? .primary :
.secondary)
+// .foregroundColor(colorSchemeContrast == .increased ?
.primary : .secondary)
}
}
} // recent transactions
@@ -123,62 +123,46 @@ extension BalancesSectionView: View {
fileprivate struct BalancesPendingRowView: View {
let symLog: SymLogV?
let stack: CallStack
- let currency: String // = currencyInfo.scope.currency
+// let currency: String // = currencyInfo.scope.currency
+ let balance: Balance // this is the currency to
be used
@Binding var pendingTransactions: [Transaction]
let reloadPending: (_ stack: CallStack) async -> ()
let reloadOneAction: ((_ transactionId: String) async throws ->
Transaction)
- func computePending(currency: String) -> (Amount, Amount) {
- var incoming = Amount(currency: currency, cent: 0)
- var outgoing = Amount(currency: currency, cent: 0)
- for transaction in pendingTransactions {
- let effective = transaction.common.amountEffective
- if currency == effective.currencyStr {
- do {
- if transaction.common.incoming() {
- incoming = try incoming + effective
- } else {
- outgoing = try outgoing + effective
- }
- } catch {
- // TODO: log error
- symLog?.log(error.localizedDescription)
- }
- }
- }
- return (incoming, outgoing)
- }
-
var body: some View {
- let (pendingIncoming, pendingOutgoing) = computePending(currency:
currency)
+ let pendingIncoming = balance.pendingIncoming
+ let pendingOutgoing = balance.pendingOutgoing
+ let needsKYCin = balance.flags.contains(.incomingKyc)
+ let needsKYCout = balance.flags.contains(.outgoingKyc)
+ let shouldConfirm = balance.flags.contains(.incomingConfirmation)
NavigationLink {
//let _ = print("button: Pending Transactions: \(currency)")
LazyView {
TransactionsListView(stack: stack.push(),
navTitle: String(localized: "Pending",
comment: "ViewTitle of TransactionList"),
- currency: currency,
+ currency: balance.scopeInfo.currency,
transactions: pendingTransactions,
showUpDown: false,
reloadAllAction: reloadPending,
reloadOneAction: reloadOneAction)
}
} label: {
- let needsKYC = true
- let shouldConfirm = false
+ let needsKYC = needsKYCin || needsKYCout
let needsKYCStr = String(localized: ". Needs K Y C", comment:
"VoiceOver")
let needsConfStr = String(localized: ". Needs bank confirmation",
comment: "VoiceOver")
VStack(spacing: 6) {
- var rows = 0
- if !pendingIncoming.isZero {
- PendingRowView(amount: pendingIncoming, incoming: true,
shouldConfirm: false, needsKYC: false) // TODO: !!!
- let _ = (rows+=1)
+ let hasIncoming = !pendingIncoming.isZero
+ if hasIncoming {
+ PendingRowView(amount: pendingIncoming, incoming: true,
+ shouldConfirm: shouldConfirm, needsKYC: needsKYCin)
}
- if !pendingOutgoing.isZero {
- PendingRowView(amount: pendingOutgoing, incoming: false,
shouldConfirm: false, needsKYC: false)
- let _ = (rows+=1)
+ let hasOutgoing = !pendingOutgoing.isZero
+ if hasOutgoing {
+ PendingRowView(amount: pendingOutgoing, incoming: false,
+ shouldConfirm: false, needsKYC: needsKYCout)
}
- if rows == 0 {
+ if !hasIncoming && !hasOutgoing { // should never
happen
Text("Some pending transactions")
.accessibilityFont(.body)
}
@@ -189,9 +173,7 @@ fileprivate struct BalancesPendingRowView: View {
shouldConfirm ? needsConfStr
: EMPTYSTRING)
.accessibilityHint("Will go to Pending transactions.")
-
- }
-
+ } // NavLinkLabel
} // body
} // BalancesPendingRowView
@@ -211,7 +193,7 @@ fileprivate struct BalancesNavigationLinksView: View {
func selectAndUpdate(_ button: Int) {
let currency = balance.scopeInfo.currency
- amountToTransfer.setCurrency(currency)
+ amountToTransfer.setCurrency(currency) // replace wrong currency
here
symLog?.log("balance.scopeInfo.currency: \(currency)")
buttonSelected = button // will trigger NavigationLink
@@ -274,10 +256,9 @@ fileprivate struct BindingViewContainer: View {
var body: some View {
let scopeInfo = ScopeInfo(type: ScopeInfo.ScopeInfoType.exchange, url:
DEMOEXCHANGE, currency: LONGCURRENCY)
- let balance = Balance(available: Amount(currency: LONGCURRENCY,
cent:1),
- scopeInfo: scopeInfo,
- requiresUserInput: false,
- hasPendingTransactions: true)
+ let balance = Balance(scopeInfo: scopeInfo,
+ available: Amount(currency: LONGCURRENCY,
cent:1),
+ hasPendingTransactions: true)
BalancesSectionView(balance: balance,
sectionCount: 2,
amountToTransfer: $amountToTransfer,
diff --git a/TalerWallet1/Views/Balances/TwoRowButtons.swift
b/TalerWallet1/Views/Balances/TwoRowButtons.swift
index 20d87c8..f057936 100644
--- a/TalerWallet1/Views/Balances/TwoRowButtons.swift
+++ b/TalerWallet1/Views/Balances/TwoRowButtons.swift
@@ -5,42 +5,41 @@
import SwiftUI
import taler_swift
-extension View {
- func accessTitles(_ titles: (String, String?), _ fitsSideBySide: Bool) ->
(String, String) {
- let space = " "
- let delimiter = fitsSideBySide ? "\n" : space
- let (title1, title2) = titles
- if let title2 {
- return (title1 + delimiter + title2, title1 + space + title2)
- } else {
- return (title1, title1)
- }
- }
-}
struct TwoRowButtons: View {
- let sendTitles: (String, String?)
- let recvTitles: (String, String?)
+ let sendTitle: String
+ let recvTitle: String
let fitsSideBySide: Bool
let lineLimit: Int
let sendDisabled: Bool
let sendAction: () -> Void
let recvAction: () -> Void
- @Environment(\.sizeCategory) var sizeCategory
+// @Environment(\.sizeCategory) var sizeCategory
+ func makeCopy(fitsSideBySide: Bool) -> TwoRowButtons {
+ TwoRowButtons(sendTitle: sendTitle,
+ recvTitle: recvTitle,
+ fitsSideBySide: fitsSideBySide,
+ lineLimit: lineLimit,
+ sendDisabled: sendDisabled,
+ sendAction: sendAction,
+ recvAction: recvAction)
+ }
var body: some View {
Group {
- let sendAccTitles = accessTitles(sendTitles, fitsSideBySide)
- Button(sendAccTitles.0, action: sendAction)
- .accessibilityLabel(Text(sendAccTitles.1))
+ let sendButtonTitle = sendTitle.tabbed(oneLine: !fitsSideBySide)
+ let sendVoiceOverTitle = sendTitle.tabbed(oneLine: true)
+ Button(sendButtonTitle, action: sendAction)
+ .accessibilityLabel(Text(sendVoiceOverTitle))
.lineLimit(lineLimit)
.disabled(sendDisabled)
.buttonStyle(TalerButtonStyle(type: .bordered,
dimmed: false,
aligned: .center))
- let recvAccTitles = accessTitles(recvTitles, fitsSideBySide)
- Button(recvAccTitles.0, action: recvAction)
- .accessibilityLabel(Text(recvAccTitles.1))
+ let recvButtonTitle = recvTitle.tabbed(oneLine: !fitsSideBySide)
+ let recvVoiceOverTitle = recvTitle.tabbed(oneLine: true)
+ Button(recvButtonTitle, action: recvAction)
+ .accessibilityLabel(Text(recvVoiceOverTitle))
.lineLimit(lineLimit)
.disabled(false)
.buttonStyle(TalerButtonStyle(type: .bordered,
@@ -49,18 +48,19 @@ struct TwoRowButtons: View {
}
}
}
-
+// MARK: -
+#if DEBUG
struct TwoRowButtons_Previews: PreviewProvider {
static var previews: some View {
List {
- TwoRowButtons(sendTitles: ("Send", TESTCURRENCY),
- recvTitles: ("Receive", LONGCURRENCY),
+ TwoRowButtons(sendTitle: "Send " + TESTCURRENCY,
+ recvTitle: "Request" + LONGCURRENCY,
fitsSideBySide: false,
lineLimit: 2, sendDisabled: true,
sendAction: {}, recvAction: {})
.listRowSeparator(.hidden)
- TwoRowButtons(sendTitles: ("Send", DEMOCURRENCY),
- recvTitles: ("Receive", DEMOCURRENCY),
+ TwoRowButtons(sendTitle: "Send" + DEMOCURRENCY,
+ recvTitle: "Request" + DEMOCURRENCY,
fitsSideBySide: true,
lineLimit: 2, sendDisabled: true,
sendAction: {}, recvAction: {})
@@ -68,3 +68,4 @@ struct TwoRowButtons_Previews: PreviewProvider {
}
}
}
+#endif
diff --git a/TalerWallet1/Views/Exchange/ExchangeRowView.swift
b/TalerWallet1/Views/Exchange/ExchangeRowView.swift
index afea32c..15e9c2a 100644
--- a/TalerWallet1/Views/Exchange/ExchangeRowView.swift
+++ b/TalerWallet1/Views/Exchange/ExchangeRowView.swift
@@ -4,18 +4,23 @@
*/
import SwiftUI
import taler_swift
+import SymLog
struct ExchangeRowView: View {
+ private let symLog = SymLogV(0)
let stack: CallStack
let exchange: Exchange
- let currency: String
- @Binding var amountToTransfer: Amount
+ let currency: String // this is the currency to be
used
+ @Binding var amountToTransfer: Amount // does still have the wrong
currency
@Environment(\.sizeCategory) var sizeCategory
+ @EnvironmentObject private var controller: Controller
+ @EnvironmentObject private var model: WalletModel
@AppStorage("iconOnly") var iconOnly: Bool = false
@State private var buttonSelected: Int? = nil
func selectAndUpdate(_ button: Int) {
+ amountToTransfer.setCurrency(currency)
buttonSelected = button // will trigger NavigationLink
// TODO: after user tapped a button, while navigation animation runs,
contact Exchange to update Fees
// cannot be uncommented yet since there is no scopeInfo
@@ -28,83 +33,90 @@ struct ExchangeRowView: View {
// }
}
- func titles(_ title: String) -> (String, String?) {
- if let separatorIndex = title.firstIndex(of: "\n") {
- let title1 = String(title[..<separatorIndex])
- let title2 = String(title[title.index(separatorIndex, offsetBy:
1)...])
- return (title1, title2)
- }
- return (title, nil)
- }
-
- func titles(_ titles: (String, String?), uiFont: UIFont) -> [(String,
UIFont)] {
- let (title1, title2) = titles
- if let title2 {
- return [(title1, uiFont), (title2, uiFont)]
- }
- return [(title1, uiFont)]
- }
-
var body: some View {
+#if DEBUG
+ let _ = Self._printChanges()
+ let _ = symLog.vlog() // just to get the # to compare it with
.onAppear & onDisappear
+ let delay: UInt = 0 // set to 5 to test delayed currency
information
+#else
+ let delay: UInt = 0
+#endif
let depositTitle0 = String(localized: "DepositButton_Short",
defaultValue: "Deposit",
comment: "Abbreviation of `Deposit
(currency)´")
- // TODO: deal with \t
let depositTitle1 = String(localized: "Deposit\t\(currency)",
comment: "Button `Deposit (currency)´, must
have ONE \\t and ONE %@")
+
let withdrawTitle0 = String(localized: "WithdrawButton_Short",
defaultValue: "Withdraw",
comment: "Abbreviation of `Withdraw
(currency)´")
let withdrawTitle1 = String(localized: "Withdraw\t\(currency)",
comment: "Button `Withdraw (currency)´,
must have ONE \\t and ONE %@")
let baseURL = exchange.exchangeBaseUrl
-
- HStack(spacing: 0) { // can't use the built in Label because it
adds the accessory arrow
- Text(baseURL.trimURL())
- .accessibilityFont(.body)
-
- NavigationLink(destination: LazyView {
- EmptyView() // TODO: Deposit
- }, tag: 1, selection: $buttonSelected
- ) { EmptyView() }.frame(width: 0).opacity(0)
- NavigationLink(destination: LazyView {
- ManualWithdraw(stack: stack.push(),
- exchange: exchange,
- amountToTransfer: $amountToTransfer)
- }, tag: 2, selection: $buttonSelected
- ) { EmptyView() }.frame(width: 0).opacity(0)
- }.listRowSeparator(.hidden)
-
- SingleAxisGeometryReader { width in
- Group {
- let uiFont = TalerFont.uiFont(.title3)
- let (deposit1, deposit2) = titles(depositTitle1)
- let (withdraw1, withdraw2) = titles(withdrawTitle1)
- let titles = iconOnly ? [(depositTitle0, uiFont),
(withdrawTitle0, uiFont)]
- : titles((deposit1, deposit2), uiFont:
uiFont) +
- titles((withdraw1, withdraw2), uiFont:
uiFont)
- let fitsSideBySide = Self.fitsSideBySide(titles,
availableWidth: width,
- sizeCategory:
sizeCategory, padding: 10)
-
// TODO: amount.currencyStr
- let twoRowButtons = TwoRowButtons(sendTitles: iconOnly ?
(depositTitle0, nil) : (deposit1, deposit2),
- recvTitles: iconOnly ?
(withdrawTitle0, nil) : (withdraw1, withdraw2),
- fitsSideBySide: fitsSideBySide,
- lineLimit: 5,
- sendDisabled: true,
// TODO: availableAmount.isZero
- sendAction: {
selectAndUpdate(1) },
- recvAction: {
selectAndUpdate(2) })
- if fitsSideBySide {
- HStack(spacing: HSPACING) { twoRowButtons }
- } else {
+ let deposit = LazyView {
+ EmptyView() // TODO: Deposit
+ }
+ let manualWithdraw = LazyView {
+ ManualWithdraw(stack: stack.push(),
+// url: nil,
+ exchange: exchange,
+ amountToTransfer: $amountToTransfer)
+ }
+ let showToS = LazyView {
+ WithdrawTOSView(stack: stack.push(),
+ exchangeBaseUrl: baseURL,
+ viewID: VIEW_WITHDRAW_TOS,
+ acceptAction: nil) // pop back to here
+ }
+ let twoRowButtons = TwoRowButtons(sendTitle: iconOnly ? depositTitle0
: depositTitle1,
+ recvTitle: iconOnly ? withdrawTitle0
: withdrawTitle1,
+ fitsSideBySide: false,
+ lineLimit: 5,
+ sendDisabled: true, //
TODO: availableAmount.isZero
+ sendAction: { selectAndUpdate(1) },
+ recvAction: { selectAndUpdate(2) })
+ Group {
+ HStack(spacing: 0) { // can't use the built in Label because it
adds the accessory arrow
+ Text(baseURL.trimURL())
+ .accessibilityFont(.headline)
+ NavigationLink(destination: deposit, tag: 1, selection:
$buttonSelected)
+ { EmptyView() }.frame(width: 0).opacity(0)
+ NavigationLink(destination: manualWithdraw, tag: 2, selection:
$buttonSelected)
+ { EmptyView() }.frame(width: 0).opacity(0)
+ }.listRowSeparator(.hidden)
+ NavigationLink(destination: showToS) {
+ Text("Terms of Service") // VIEW_WITHDRAW_TOS
+ .accessibilityFont(.body)
+ }.listRowSeparator(.hidden)
+ if #available(iOS 16.0, *) {
+ ViewThatFits(in: .horizontal) {
+ HStack(spacing: HSPACING) {
+ twoRowButtons.makeCopy(fitsSideBySide: true)
+ }
VStack { twoRowButtons }
}
+ } else { // view for iOS 15
+ VStack { twoRowButtons }
+ }
+ }
+ .task {
+ if !controller.hasInfo(for: currency) {
+ symLog.log("fetching info for \(currency)")
+ // FIXME: remove fake ScopeInfo once the REAL one is in
exchange.scopeInfo
+ let scopeInfo = exchange.scopeInfo ?? ScopeInfo(type: .global,
currency: currency)
+ do {
+ let info = try await model.getCurrencyInfo(scope:
scopeInfo, delay: delay)
+// logger.info("got info: \(scope.currency, privacy:
.public)")
+ await controller.setInfo(info)
+ } catch { // TODO: error handling - couldn't get
CurrencyInfo
+// logger.error("Couldn't get info for: \(scope.currency,
privacy: .public)\n\(error)")
+ }
}
}
}
}
-
// MARK: -
#if DEBUG
fileprivate struct ExchangeRow_Container : View {
- @State private var amountToTransfer = Amount(currency: LONGCURRENCY, cent:
1234)
+ @State private var amountToPreview = Amount(currency: LONGCURRENCY, cent:
1234)
// let amount = Amount(currency: LONGCURRENCY, cent: 123456)
var body: some View {
@@ -125,7 +137,7 @@ fileprivate struct ExchangeRow_Container : View {
ExchangeRowView(stack: CallStack("Preview"),
exchange: exchange1,
currency: LONGCURRENCY,
- amountToTransfer: $amountToTransfer)
+ amountToTransfer: $amountToPreview)
}
}
diff --git a/TalerWallet1/Views/Exchange/ExchangeSectionView.swift
b/TalerWallet1/Views/Exchange/ExchangeSectionView.swift
index 4664d50..0f48133 100644
--- a/TalerWallet1/Views/Exchange/ExchangeSectionView.swift
+++ b/TalerWallet1/Views/Exchange/ExchangeSectionView.swift
@@ -14,23 +14,17 @@ struct ExchangeSectionView: View {
let exchanges: [Exchange]
@Binding var amountToTransfer: Amount // does still have the wrong
currency
- func setCurrency() -> String {
- amountToTransfer.setCurrency(currency)
- return currency
- }
-
var body: some View {
#if DEBUG
let _ = Self._printChanges()
// let _ = symLog.vlog() // just to get the # to compare it with
.onAppear & onDisappear
#endif
- let currency2 = setCurrency() // update currency in
amountToTransfer
Section {
ForEach(exchanges) { exchange in
ExchangeRowView(stack: stack.push(),
exchange: exchange,
- currency: currency2, // TODO:
(balance.available) amount.isZero to disable Deposit-button
- amountToTransfer: $amountToTransfer)
+ currency: currency, // TODO:
(balance.available) amount.isZero to disable Deposit-button
+ amountToTransfer: $amountToTransfer) // does still have
the wrong currency
}
} header: {
BarGraphHeader(stack: stack.push(), currency: currency)
@@ -41,7 +35,7 @@ struct ExchangeSectionView: View {
#if DEBUG
fileprivate struct ExchangeSection_Previews: PreviewProvider {
fileprivate struct ExchangeRow_Container : View {
- @State private var amountToTransfer = Amount(currency: LONGCURRENCY, cent:
1234)
+ @State private var amountToPreview = Amount(currency: LONGCURRENCY, cent:
1234)
// let amount = Amount(currency: LONGCURRENCY, cent: 123456)
var body: some View {
@@ -61,7 +55,7 @@ fileprivate struct ExchangeRow_Container : View {
ageRestrictionOptions: [])
ExchangeSectionView(stack: CallStack("Preview"), currency:
LONGCURRENCY,
exchanges: [exchange1, exchange2],
- amountToTransfer: $amountToTransfer)
+ amountToTransfer: $amountToPreview)
}
}
diff --git a/TalerWallet1/Views/Exchange/ManualWithdraw.swift
b/TalerWallet1/Views/Exchange/ManualWithdraw.swift
index dc33b2c..da6e34b 100644
--- a/TalerWallet1/Views/Exchange/ManualWithdraw.swift
+++ b/TalerWallet1/Views/Exchange/ManualWithdraw.swift
@@ -11,6 +11,8 @@ struct ManualWithdraw: View {
private let symLog = SymLogV(0)
let stack: CallStack
+// let url: URL?
+// let exchange: Exchange?
let exchange: Exchange
@Binding var amountToTransfer: Amount
@@ -18,6 +20,7 @@ struct ManualWithdraw: View {
@EnvironmentObject private var model: WalletModel
@AppStorage("iconOnly") var iconOnly: Bool = false
+ @State var tosAccepted = false
@State var withdrawalAmountDetails: WithdrawalAmountDetails? = nil
// @State var ageMenuList: [Int] = []
// @State var selectedAge = 0
@@ -32,67 +35,75 @@ struct ManualWithdraw: View {
let navTitle = String(localized: "NavTitle_Withdraw (currency)",
defaultValue: "Withdraw \(currency)")
// let agePicker = AgePicker(ageMenuList: $ageMenuList, selectedAge:
$selectedAge)
- ScrollView { VStack {
- CurrencyInputView(amount: $amountToTransfer,
- available: nil,
- title: iconOnly ? String(localized: "How
much:")
- : String(localized: "Amount
to withdraw:"))
- let someCoins = SomeCoins(details: withdrawalAmountDetails)
- QuiteSomeCoins(someCoins: someCoins,
- shouldShowFee: true, // TODO: set to
false if we never charge withdrawal fees
- currency: currency,
- currencyInfo: currencyInfo,
- amountEffective:
withdrawalAmountDetails?.amountEffective)
- Text(exchange.exchangeBaseUrl.trimURL())
- .multilineTextAlignment(.center)
- .accessibilityFont(.body)
-
- let disabled = amountToTransfer.isZero || someCoins.invalid ||
someCoins.tooMany
- if !disabled {
-// agePicker
-
- if let tosAccepted = withdrawalAmountDetails?.tosAccepted {
- if tosAccepted {
-// let restrictAge: Int? = (selectedAge == 0) ? nil
-// :
selectedAge
-//let _ = print(selectedAge, restrictAge)
- NavigationLink(destination: LazyView {
- ManualWithdrawDone(stack: stack.push(),
- exchange: exchange,
- amountToTransfer: amountToTransfer)
-// restrictAge: restrictAge)
- }) {
- Text("Confirm Withdrawal") //
VIEW_WITHDRAW_ACCEPT
- }
- .buttonStyle(TalerButtonStyle(type: .prominent))
- .padding(.horizontal)
- } else {
- ToSButtonView(stack: stack.push(),
- exchangeBaseUrl: exchange.exchangeBaseUrl,
- viewID: VIEW_WITHDRAW_TOS,
- p2p: false)
- }
- }
- } // disabled
+ let someCoins = SomeCoins(details: withdrawalAmountDetails)
+// let restrictAge: Int? = (selectedAge == 0) ? nil
+// : selectedAge
+// let _ = print(selectedAge, restrictAge)
+ let destination = LazyView {
+ ManualWithdrawDone(stack: stack.push(),
+ exchange: exchange,
+ amountToTransfer: amountToTransfer)
+// restrictAge: restrictAge)
+ }
+ let disabled = amountToTransfer.isZero || someCoins.invalid ||
someCoins.tooMany
+ ScrollView { VStack(alignment: .trailing) {
+ Text("via \(exchange.exchangeBaseUrl.trimURL())")
+ .multilineTextAlignment(.center)
+ .accessibilityFont(.body)
+ CurrencyInputView(amount: $amountToTransfer,
+ available: nil,
+ title: iconOnly ? String(localized: "How much:")
+ : String(localized: "Amount to
withdraw:"),
+ shortcutAction: nil)
+ .padding(.top)
+ QuiteSomeCoins(someCoins: someCoins,
+ shouldShowFee: true, // TODO: set to false if
we never charge withdrawal fees
+ currency: currency,
+ currencyInfo: currencyInfo,
+ amountEffective: withdrawalAmountDetails?.amountEffective)
+// agePicker
+ if tosAccepted {
+ NavigationLink(destination: destination) {
+ Text("Confirm Withdrawal") // VIEW_WITHDRAW_ACCEPT
+ }
+ .buttonStyle(TalerButtonStyle(type: .prominent))
+ .disabled(disabled)
+ .padding(.top)
+ } else {
+ ToSButtonView(stack: stack.push(),
+ exchangeBaseUrl: exchange.exchangeBaseUrl,
+ viewID: VIEW_WITHDRAW_TOS,
+ p2p: false)
+ .padding(.top)
+ }
} } // ScrollVStack
.frame(maxWidth: .infinity, alignment: .leading)
.padding(.horizontal)
.background(WalletColors().backgroundColor.edgesIgnoringSafeArea(.all))
.navigationTitle(navTitle)
.onAppear {
- symLog.log("onAppear")
DebugViewC.shared.setViewID(VIEW_WITHDRAWAL, stack: stack.push())
+ symLog.log("❗️ \(navTitle) onAppear")
+ }
+ .onDisappear {
+ symLog.log("❗️ \(navTitle) onDisappear")
}
.task(id: amountToTransfer.value) { // re-run this whenever
amountToTransfer changes
- if !amountToTransfer.isZero {
- do {
- withdrawalAmountDetails = try await
model.loadWithdrawalDetailsForAmountM(exchange.exchangeBaseUrl,
-
amount: amountToTransfer)
+ do {
+ let amount = amountToTransfer.isZero ? Amount(currency:
currency, cent: 100)
+ : amountToTransfer
+// if amountToTransfer.isZero {
+// tosAccepted = GetTosStatus(exchange.exchangeBaseUrl)
+// } else {
+ let details = try await
model.loadWithdrawalDetailsForAmountM(exchange.exchangeBaseUrl,
+
amount: amount)
+ tosAccepted = details.tosAccepted
+ withdrawalAmountDetails = amountToTransfer.isZero ? nil :
details
// agePicker.setAges(ages:
withdrawalAmountDetails?.ageRestrictionOptions)
- } catch { // TODO: error
- symLog.log(error.localizedDescription)
- withdrawalAmountDetails = nil
- }
+// }
+ } catch { // TODO: error
+ symLog.log(error.localizedDescription)
+ withdrawalAmountDetails = nil
}
}
}
@@ -102,13 +113,9 @@ struct ManualWithdraw: View {
struct ManualWithdraw_Previews: PreviewProvider {
struct StateContainer : View {
@State private var amountToTransfer = Amount(currency: LONGCURRENCY, cent:
510)
- @State private var details = WithdrawalAmountDetails(tosAccepted: false,
- amountRaw:
Amount(currency: LONGCURRENCY, cent: 510),
- amountEffective:
Amount(currency: LONGCURRENCY, cent: 500),
- paytoUris: [],
- ageRestrictionOptions: [],
- numCoins: 6)
- var body: some View {
+
+ var body: some View {
+ let scopeInfo = ScopeInfo(type: ScopeInfo.ScopeInfoType.exchange, url:
DEMOEXCHANGE, currency: LONGCURRENCY)
let exchange = Exchange(exchangeBaseUrl: DEMOEXCHANGE,
currency: LONGCURRENCY,
paytoUris: [],
@@ -116,7 +123,16 @@ struct ManualWithdraw_Previews: PreviewProvider {
exchangeEntryStatus: .preset,
exchangeUpdateStatus: .initial,
ageRestrictionOptions: [])
+ let details = WithdrawalAmountDetails(tosAccepted: false,
+ amountRaw: Amount(currency:
LONGCURRENCY, cent: 510),
+ amountEffective: Amount(currency:
LONGCURRENCY, cent: 500),
+ numCoins: 6,
+// paytoUris: [],
+ withdrawalAccountsList: [],
+ ageRestrictionOptions: [],
+ scopeInfo: scopeInfo)
ManualWithdraw(stack: CallStack("Preview"),
+// url: nil,
exchange: exchange,
amountToTransfer: $amountToTransfer,
withdrawalAmountDetails: details)
diff --git a/TalerWallet1/Views/HelperViews/AmountRowV.swift
b/TalerWallet1/Views/HelperViews/AmountRowV.swift
index 7fb6298..19f99dc 100644
--- a/TalerWallet1/Views/HelperViews/AmountRowV.swift
+++ b/TalerWallet1/Views/HelperViews/AmountRowV.swift
@@ -22,7 +22,7 @@ struct AmountRowV<Content: View>: View {
var body: some View {
let text = Text(amountStr)
- .strikethrough(!doneOrPending)
+// .strikethrough(!doneOrPending)
.foregroundColor(amountColor)
.accessibilityFont(largeAmountFont ? .title : .title2)
.monospacedDigit()
diff --git a/TalerWallet1/Views/HelperViews/CurrencyInputView.swift
b/TalerWallet1/Views/HelperViews/CurrencyInputView.swift
index 8c3f7c2..3c9cbae 100644
--- a/TalerWallet1/Views/HelperViews/CurrencyInputView.swift
+++ b/TalerWallet1/Views/HelperViews/CurrencyInputView.swift
@@ -55,6 +55,7 @@ struct CurrencyInputView: View {
@Binding var amount: Amount // the `value´
let available: Amount?
let title: String
+ let shortcutAction: ((_ amount: Amount) -> Void)?
@EnvironmentObject private var controller: Controller
@@ -63,11 +64,15 @@ struct CurrencyInputView: View {
@State private var useShortcut = 0
func action(shortcut: Int, currencyField: CurrencyField) {
- useShortcut = shortcut
let shortie = Amount(currency: amount.currencyStr, cent:
UInt64(shortcut)) // TODO: adapt for ¥
- currencyField.updateText(amount: shortie)
- amount = shortie
- currencyField.resignFirstResponder()
+ if let shortcutAction {
+ shortcutAction(shortie)
+ } else {
+ useShortcut = shortcut
+ currencyField.updateText(amount: shortie)
+ amount = shortie
+ currencyField.resignFirstResponder()
+ }
}
var body: some View {
@@ -168,7 +173,8 @@ fileprivate struct Previews: PreviewProvider {
// Preview_Content()
CurrencyInputView(amount: $amountToTransfer,
available: nil,
- title: "Amount to withdraw:")
+ title: "Amount to withdraw:",
+ shortcutAction: nil)
.environmentObject(controller)
}
}
diff --git a/TalerWallet1/Views/Main/MainView.swift
b/TalerWallet1/Views/Main/MainView.swift
index 839b546..43c6906 100644
--- a/TalerWallet1/Views/Main/MainView.swift
+++ b/TalerWallet1/Views/Main/MainView.swift
@@ -146,7 +146,7 @@ extension MainView {
hamburgerAction: hamburgerAction)
)),
SidebarItem(name: exchangesTitle,
- sysImage: "building.columns",
+ sysImage: "arrow.triangle.2.circlepath",
view: AnyView(ExchangeListView(stack:
stack.push(exchangesTitle),
// balances: $balances,
navTitle: exchangesTitle,
@@ -201,7 +201,7 @@ extension MainView {
navTitle: exchangesTitle)
}.navigationViewStyle(.stack)
.tabItem {
- Image(systemName: "building.columns")
+ Image(systemName: "arrow.triangle.2.circlepath")
.accessibilityLabel(exchangesTitle)
if !iconOnly { Text(exchangesTitle) }
}
diff --git a/TalerWallet1/Views/Peer2peer/P2PReadyV.swift
b/TalerWallet1/Views/Peer2peer/P2PReadyV.swift
index 682e207..b448eaa 100644
--- a/TalerWallet1/Views/Peer2peer/P2PReadyV.swift
+++ b/TalerWallet1/Views/Peer2peer/P2PReadyV.swift
@@ -8,12 +8,12 @@ import SymLog
// Called when initiating a P2P transaction: Send coins or Send
Request(Invoice)
struct P2PReadyV: View {
- private let symLog = SymLogV()
+ private let symLog = SymLogV(0)
let stack: CallStack
- let amountToSend: Amount?
- let amountToReceive: Amount?
let summary: String
let expireDays: UInt
+ let amountToSend: Bool
+ let amountToTransfer: Amount
@Binding var transactionStarted: Bool
@EnvironmentObject private var model: WalletModel
@@ -62,7 +62,7 @@ struct P2PReadyV: View {
.onDisappear {
// print("❗️ P2PReadyV onDisappear")
}
- .task {
+ .task(id: amountToTransfer.value) {
symLog.log(".task")
do {
guard transactionStarted == false else {
@@ -74,23 +74,23 @@ struct P2PReadyV: View {
let timestamp = developerMode ?
Timestamp.inSomeMinutes(expireDays > 20 ? (24*60)
:
expireDays > 5 ? 60 : 3)
:
Timestamp.inSomeDays(expireDays)
- if let amountToSend {
- let terms = PeerContractTerms(amount: amountToSend,
+ if amountToSend {
+ let terms = PeerContractTerms(amount: amountToTransfer,
summary: summary,
purse_expiration: timestamp)
// TODO: let user choose baseURL
let response = try await model.initiatePeerPushDebitM(nil,
terms: terms)
// will switch from WithdrawProgressView to
TransactionDetailView
transactionId = response.transactionId
- } else if let amountToReceive {
- let terms = PeerContractTerms(amount: amountToReceive,
+ } else {
+ let terms = PeerContractTerms(amount: amountToTransfer,
summary: summary,
purse_expiration: timestamp)
// TODO: let user choose baseURL
let response = try await
model.initiatePeerPullCreditM(nil, terms: terms)
// will switch from WithdrawProgressView to
TransactionDetailView
transactionId = response.transactionId
- } else { fatalError() }
+ }
} catch { // TODO: error
symLog.log(error.localizedDescription)
}
diff --git a/TalerWallet1/Views/Peer2peer/P2PSubjectV.swift
b/TalerWallet1/Views/Peer2peer/P2PSubjectV.swift
index aa6c13b..d6a788c 100644
--- a/TalerWallet1/Views/Peer2peer/P2PSubjectV.swift
+++ b/TalerWallet1/Views/Peer2peer/P2PSubjectV.swift
@@ -6,35 +6,61 @@ import SwiftUI
import taler_swift
import SymLog
+func p2pFee(ppCheck: CheckPeerPushDebitResponse) -> Amount? {
+ do {
+ // Outgoing: fee = effective - raw
+ let fee = try ppCheck.amountEffective - ppCheck.amountRaw
+ return fee
+ } catch {}
+ return nil
+}
+
struct P2PSubjectV: View {
private let symLog = SymLogV(0)
let stack: CallStack
-
- let amountToSend: Amount?
- let amountToReceive: Amount?
-// let amountToTransfer: Amount
- let navTitle: String
- let buttonTitle: String
- let feeLabel: String
+ let feeLabel: String?
let currencyInfo: CurrencyInfo
+ let amountToSend: Bool
+ @Binding var amountToTransfer: Amount
@Binding var summary: String
@Binding var expireDays: UInt
+ @EnvironmentObject private var model: WalletModel
@AppStorage("iconOnly") var iconOnly: Bool = false
+ @State private var myFeeLabel: String = EMPTYSTRING
@State private var transactionStarted: Bool = false
@FocusState private var isFocused: Bool
+ private func buttonTitle(_ amount: Amount, _ currencyInfo: CurrencyInfo)
-> String {
+ let amountWithCurrency = amount.string(currencyInfo, useSymbol: false)
+ return amountToSend ? String(localized: "Send \(amountWithCurrency)
now",
+ comment: "amount with currency")
+ : String(localized: "Request
\(amountWithCurrency)",
+ comment: "amount with currency")
+ }
+
+ private func subjectTitle(_ amount: Amount, _ currencyInfo: CurrencyInfo)
-> String {
+ let amountStr = amount.string(currencyInfo)
+ return amountToSend ? String(localized: "NavTitle_Send_AmountStr",
+ defaultValue: "Send \(amountStr)",
+ comment: "NavTitle: Send 'amountStr'")
+ : String(localized: "NavTitle_Request_AmountStr",
+ defaultValue: "Request \(amountStr)",
+ comment: "NavTitle: Request
'amountStr'")
+ }
+
var body: some View {
#if DEBUG
let _ = Self._printChanges()
- let _ = symLog.vlog() // just to get the # to compare it with
.onAppear & onDisappear
+ let _ = symLog.vlog(amountToTransfer.readableDescription) //
just to get the # to compare it with .onAppear & onDisappear
#endif
ScrollView { VStack (alignment: .leading, spacing: 6) {
- if feeLabel.count > 0 {
+ let label = feeLabel ?? myFeeLabel
+ if label.count > 0 {
HStack {
Spacer()
- Text(feeLabel)
+ Text(label)
.foregroundColor(.red)
.accessibilityFont(.body)
}
@@ -81,19 +107,19 @@ struct P2PSubjectV: View {
let disabled = (expireDays == 0) || (summary.count < 1) //
TODO: check amountAvailable
NavigationLink(destination: LazyView {
P2PReadyV(stack: stack.push(),
- amountToSend: amountToSend,
- amountToReceive: amountToReceive,
summary: summary,
expireDays: expireDays,
+ amountToSend: amountToSend,
+ amountToTransfer: amountToTransfer,
transactionStarted: $transactionStarted)
}) {
- Text(buttonTitle)
+ Text(buttonTitle(amountToTransfer, currencyInfo))
}
.buttonStyle(TalerButtonStyle(type: .prominent))
.disabled(disabled)
.accessibilityHint(disabled ? "enabled when subject and
expiration are set" : EMPTYSTRING)
}.padding(.horizontal) } // ScrollVStack
- .navigationTitle(navTitle)
+ .navigationTitle(subjectTitle(amountToTransfer, currencyInfo))
.background(WalletColors().backgroundColor.edgesIgnoringSafeArea(.all))
.onAppear {
DebugViewC.shared.setViewID(VIEW_P2P_SUBJECT, stack: stack.push())
@@ -102,6 +128,19 @@ struct P2PSubjectV: View {
.onDisappear {
// print("❗️ P2PSubjectV onDisappear")
}
+ .task(id: amountToTransfer.value) {
+ if feeLabel == nil {
+ do {
+ let ppCheck = try await
model.checkPeerPushDebitM(amountToTransfer)
+ if let feeAmount = p2pFee(ppCheck: ppCheck) {
+ let feeStr = feeAmount.string(currencyInfo)
+ myFeeLabel = String(localized: "+ \(feeStr) send fee")
+ } else { myFeeLabel = EMPTYSTRING }
+ } catch { // TODO: error
+ symLog.log(error.localizedDescription)
+ }
+ }
+ }
}
}
// MARK: -
diff --git a/TalerWallet1/Views/Peer2peer/RequestPayment.swift
b/TalerWallet1/Views/Peer2peer/RequestPayment.swift
index a16f3c8..45c0441 100644
--- a/TalerWallet1/Views/Peer2peer/RequestPayment.swift
+++ b/TalerWallet1/Views/Peer2peer/RequestPayment.swift
@@ -20,6 +20,13 @@ struct RequestPayment: View {
@State private var peerPullCheck: CheckPeerPullCreditResponse? = nil
@State private var expireDays: UInt = 0
+ @State private var buttonSelected = false
+ @State private var amountShortcut = Amount.zero(currency: EMPTYSTRING)
// Update currency when used
+
+ private func shortcutAction(_ shortcut: Amount) {
+ amountShortcut = shortcut
+ buttonSelected = true
+ }
var body: some View {
#if DEBUG
@@ -32,54 +39,56 @@ struct RequestPayment: View {
let navTitle = String(localized: "NavTitle_Request_Currency",
defaultValue: "Request \(currencySymbol)",
comment: "NavTitle: Request 'currencySymbol'")
- let amountStr = amountToTransfer.string(currencyInfo)
- let amountWithCurrency = amountToTransfer.string(currencyInfo,
useSymbol: false)
- let buttonTitle = String(localized: "Request \(amountWithCurrency)",
comment: "amount with currency")
- let navTitle2 = String(localized: "NavTitle_Request_AmountStr",
- defaultValue: "Request \(amountStr)",
- comment: "NavTitle: Request 'amountStr'")
-
+ let someCoins = SomeCoins(details: peerPullCheck)
let _ = symLog.log("currency: \(currency)")
+ let inputDestination = LazyView {
+ P2PSubjectV(stack: stack.push(),
+ feeLabel: someCoins.feeLabel(currencyInfo),
+ currencyInfo: currencyInfo,
+ amountToSend: false,
+ amountToTransfer: $amountToTransfer,
+ summary: $summary,
+ expireDays: $expireDays)
+ }
+ let shortcutDestination = LazyView {
+ P2PSubjectV(stack: stack.push(),
+ feeLabel: nil,
+ currencyInfo: currencyInfo,
+ amountToSend: false,
+ amountToTransfer: $amountShortcut,
+ summary: $summary,
+ expireDays: $expireDays)
+ }
+ let disabled = amountToTransfer.isZero || someCoins.invalid ||
someCoins.tooMany
ScrollView { VStack(alignment: .trailing) {
CurrencyInputView(amount: $amountToTransfer,
available: nil,
title: iconOnly ? String(localized: "How much:")
- : String(localized: "Amount to
request:"))
- .padding(.top)
- let someCoins = SomeCoins(details: peerPullCheck)
+ : String(localized: "Amount to
request:"),
+ shortcutAction: shortcutAction)
+ .padding(.top)
QuiteSomeCoins(someCoins: someCoins,
shouldShowFee: true, // always true since the
requester pays fees
currency: currency,
currencyInfo: currencyInfo,
amountEffective: peerPullCheck?.amountEffective)
-
- let disabled = amountToTransfer.isZero || someCoins.invalid ||
someCoins.tooMany
-
- NavigationLink(destination: LazyView {
- P2PSubjectV(stack: stack.push(),
- amountToSend: nil,
- amountToReceive: amountToTransfer,
- navTitle: navTitle2,
- buttonTitle: buttonTitle,
- feeLabel: someCoins.feeLabel(currencyInfo),
- currencyInfo: currencyInfo,
- summary: $summary,
- expireDays: $expireDays)
- }) { Text("Next") }
+ NavigationLink(destination: inputDestination) { Text("Next") }
.buttonStyle(TalerButtonStyle(type: .prominent))
.disabled(disabled)
-// Spacer()
+ .background(NavigationLink(destination: shortcutDestination,
isActive: $buttonSelected)
+ { EmptyView() }.frame(width: 0).opacity(0).hidden()
+ )
} } // ScrollVStack
.frame(maxWidth: .infinity, alignment: .leading)
- .padding(.horizontal)
+ .padding(.horizontal) // Lists do this automatically, but this is a
VStack
.background(WalletColors().backgroundColor.edgesIgnoringSafeArea(.all))
.navigationTitle(navTitle)
.onAppear {
DebugViewC.shared.setViewID(VIEW_P2P_REQUEST, stack: stack.push())
- symLog.log("❗️Yikes \(navTitle) onAppear")
+ symLog.log("❗️ \(navTitle) onAppear")
}
.onDisappear {
- symLog.log("❗️Yikes \(navTitle) onDisappear")
+ symLog.log("❗️ \(navTitle) onDisappear")
}
.task(id: amountToTransfer.value) {
if amountToTransfer.isZero {
diff --git a/TalerWallet1/Views/Peer2peer/SendAmount.swift
b/TalerWallet1/Views/Peer2peer/SendAmount.swift
index b63da48..d66f41c 100644
--- a/TalerWallet1/Views/Peer2peer/SendAmount.swift
+++ b/TalerWallet1/Views/Peer2peer/SendAmount.swift
@@ -20,9 +20,11 @@ struct SendAmount: View {
@AppStorage("iconOnly") var iconOnly: Bool = false
@State var peerPushCheck: CheckPeerPushDebitResponse? = nil
- @State private var expireDays: UInt = SEVENDAYS
- @State private var insufficient: Bool = false
+ @State private var expireDays = SEVENDAYS
+ @State private var insufficient = false
@State private var feeStr: String = EMPTYSTRING
+ @State private var buttonSelected = false
+ @State private var amountShortcut = Amount.zero(currency: EMPTYSTRING)
// Update currency when used
private func fee(ppCheck: CheckPeerPushDebitResponse?) -> Amount? {
do {
@@ -37,6 +39,11 @@ struct SendAmount: View {
var feeLabel: String { feeStr.count > 0 ? String(localized: "+ \(feeStr)
send fee") : EMPTYSTRING }
+ private func shortcutAction(_ shortcut: Amount) {
+ amountShortcut = shortcut
+ buttonSelected = true
+ }
+
var body: some View {
#if DEBUG
let _ = Self._printChanges()
@@ -48,49 +55,52 @@ struct SendAmount: View {
let navTitle = String(localized: "NavTitle_Send_Currency",
defaultValue: "Send \(currencySymbol)",
comment: "NavTitle: Send 'currencySymbol'")
- let amountStr = amountToTransfer.string(currencyInfo)
- let amountWithCurrency = amountToTransfer.string(currencyInfo,
useSymbol: false)
- let buttonTitle = String(localized: "Send \(amountWithCurrency) now",
comment: "amount with currency")
- let navTitle2 = String(localized: "NavTitle_Send_AmountStr",
- defaultValue: "Send \(amountStr)",
- comment: "NavTitle: Send 'amountStr'")
-
let available = amountAvailable.string(currencyInfo)
+// let _ = print("available: \(available)")
let _ = symLog.log("currency: \(currency), available: \(available)")
let amountVoiceOver = amountToTransfer.string(currencyInfo)
let insufficientLabel = String(localized: "You don't have enough
\(currency).")
let insufficientLabel2 = String(localized: "but you only have
\(available) to send.")
+ let inputDestination = LazyView {
+ P2PSubjectV(stack: stack.push(),
+ feeLabel: feeLabel,
+ currencyInfo: currencyInfo,
+ amountToSend: true,
+ amountToTransfer: $amountToTransfer,
+ summary: $summary,
+ expireDays: $expireDays)
+ }
+ let shortcutDestination = LazyView {
+ P2PSubjectV(stack: stack.push(),
+ feeLabel: nil,
+ currencyInfo: currencyInfo,
+ amountToSend: true,
+ amountToTransfer: $amountShortcut,
+ summary: $summary,
+ expireDays: $expireDays)
+ }
+ let disabled = insufficient || amountToTransfer.isZero
ScrollView { VStack(alignment: .trailing) {
-// let _ = print("available: \(available)")
Text("Available:\t\(available)")
.accessibilityFont(.title3)
.padding(.bottom, 2)
CurrencyInputView(amount: $amountToTransfer,
available: amountAvailable,
title: iconOnly ? String(localized: "How much:")
- : String(localized: "Amount to
send:"))
- let disabled = insufficient || amountToTransfer.isZero
+ : String(localized: "Amount to
send:"),
+ shortcutAction: shortcutAction)
Text(insufficient ? insufficientLabel
: feeLabel)
.accessibilityFont(.body)
.foregroundColor(.red)
.padding(4)
-
- NavigationLink(destination: LazyView {
- P2PSubjectV(stack: stack.push(),
- amountToSend: amountToTransfer,
- amountToReceive: nil,
- navTitle: navTitle2,
- buttonTitle: buttonTitle,
- feeLabel: feeLabel,
- currencyInfo: currencyInfo,
- summary: $summary,
- expireDays: $expireDays)
- }) { Text("Next") }
+ NavigationLink(destination: inputDestination) { Text("Next") }
.buttonStyle(TalerButtonStyle(type: .prominent))
.disabled(disabled)
-// Spacer()
+ .background(NavigationLink(destination: shortcutDestination,
isActive: $buttonSelected)
+ { EmptyView() }.frame(width: 0).opacity(0).hidden()
+ )
} } // ScrollVStack
.frame(maxWidth: .infinity, alignment: .leading)
.padding(.horizontal)
@@ -98,15 +108,14 @@ struct SendAmount: View {
.navigationTitle(navTitle)
.onAppear {
DebugViewC.shared.setViewID(VIEW_P2P_SEND, stack: stack.push())
- symLog.log("❗️Yikes SendAmount onAppear")
+ symLog.log("❗️ \(navTitle) onAppear")
}
.onDisappear {
- symLog.log("❗️Yikes SendAmount onDisappear")
+ symLog.log("❗️ \(navTitle) onDisappear")
}
.task(id: amountToTransfer.value) {
do {
insufficient = try amountToTransfer > amountAvailable
- print("amountStr: \(amountVoiceOver)")
} catch {
print("Yikes❗️ insufficient failed❗️")
insufficient = true
@@ -137,14 +146,14 @@ struct SendAmount: View {
// MARK: -
#if DEBUG
fileprivate struct Preview_Content: View {
- @State private var amountToTransfer = Amount(currency: TESTCURRENCY, cent:
510)
+ @State private var amountToPreview = Amount(currency: TESTCURRENCY, cent:
510)
@State private var summary: String = ""
var body: some View {
let amount = Amount(currency: TESTCURRENCY, integer: 10, fraction: 0)
SendAmount(stack: CallStack("Preview"),
amountAvailable: amount,
- amountToTransfer: $amountToTransfer,
+ amountToTransfer: $amountToPreview,
summary: $summary)
}
}
diff --git a/TalerWallet1/Views/Sheets/Payment/PayTemplateView.swift
b/TalerWallet1/Views/Sheets/Payment/PayTemplateView.swift
index 5a66006..0a7028e 100644
--- a/TalerWallet1/Views/Sheets/Payment/PayTemplateView.swift
+++ b/TalerWallet1/Views/Sheets/Payment/PayTemplateView.swift
@@ -9,7 +9,7 @@ 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 payment details
struct PayTemplateView: View {
- private let symLog = SymLogV()
+ private let symLog = SymLogV(0)
let stack: CallStack
let navTitle = String(localized: "Confirm Payment", comment:"pay merchant")
diff --git a/TalerWallet1/Views/Sheets/Payment/PaymentView.swift
b/TalerWallet1/Views/Sheets/Payment/PaymentView.swift
index 534a7d4..4ce2970 100644
--- a/TalerWallet1/Views/Sheets/Payment/PaymentView.swift
+++ b/TalerWallet1/Views/Sheets/Payment/PaymentView.swift
@@ -43,7 +43,10 @@ struct PaymentView: View {
var body: some View {
if let preparePayResult {
let effective = preparePayResult.amountEffective
+ let terms = preparePayResult.contractTerms
List {
+ Text(terms.summary)
+ .accessibilityFont(.title3)
let baseURL =
preparePayResult.contractTerms.exchanges.first?.url
let raw = preparePayResult.amountRaw
let currency = raw.currencyStr
diff --git a/TalerWallet1/Views/Sheets/Refund/RefundURIView.swift
b/TalerWallet1/Views/Sheets/Refund/RefundURIView.swift
new file mode 100644
index 0000000..edebcff
--- /dev/null
+++ b/TalerWallet1/Views/Sheets/Refund/RefundURIView.swift
@@ -0,0 +1,60 @@
+/*
+ * This file is part of GNU Taler, ©2022-23 Taler Systems S.A.
+ * See LICENSE.md
+ */
+import SwiftUI
+import SymLog
+import taler_swift
+
+struct RefundURIView: View {
+ private let symLog = SymLogV(0)
+ let stack: CallStack
+ let url: URL
+
+ @EnvironmentObject private var model: WalletModel
+
+// let navTitle = String(localized: "Refund", comment:"receive refund")
+
+ @State var refundTransactionId: String? = nil
+
+ func reloadOneAction(_ transactionId: String) async throws -> Transaction {
+ return try await model.getTransactionByIdT(transactionId)
+ }
+
+ var body: some View {
+ if let refundTransactionId {
+ TransactionDetailView(stack: stack.push(),
+ transactionId: refundTransactionId,
+ reloadAction: reloadOneAction,
+ navTitle: nil, // navTitle,
+ doneAction: ViewState.shared.popToRootView,
+ abortAction: model.abortTransaction,
+ deleteAction: model.deleteTransaction,
+ failAction: model.failTransaction,
+ suspendAction: model.suspendTransaction,
+ resumeAction: model.resumeTransaction)
+ } else {
+ let badURL = "Error in Link: \(url)"
+ WithdrawProgressView(message: url.host ?? badURL)
+ .navigationTitle("Find Exchange")
+ .task {
+ do {
+ symLog.log(".task")
+ let result = try await model.startRefundForUriM(url:
url.absoluteString)
+ refundTransactionId = result
+ } catch { // TODO: error
+ symLog.log(error.localizedDescription)
+ }
+ }
+ }
+ }
+}
+
+// MARK: -
+struct RefundURIView_Previews: PreviewProvider {
+ static var previews: some View {
+ let transactionId = "txn:refund:12345"
+ let url = URL(string: "taler://reward/survey")!
+ RefundURIView(stack: CallStack("Preview"), url: url,
refundTransactionId: transactionId)
+ }
+}
diff --git a/TalerWallet1/Views/Sheets/URLSheet.swift
b/TalerWallet1/Views/Sheets/URLSheet.swift
index 4c9f99d..8e38872 100644
--- a/TalerWallet1/Views/Sheets/URLSheet.swift
+++ b/TalerWallet1/Views/Sheets/URLSheet.swift
@@ -3,6 +3,7 @@
* See LICENSE.md
*/
import SwiftUI
+import taler_swift
import SymLog
struct URLSheet: View {
@@ -12,6 +13,7 @@ struct URLSheet: View {
var urlToOpen: URL
@EnvironmentObject private var controller: Controller
+ @State private var amountToTransfer = Amount.zero(currency: "")
var body: some View {
#if DEBUG
@@ -24,6 +26,8 @@ struct URLSheet: View {
switch urlCommand {
case .withdraw:
WithdrawURIView(stack: stack.push(), url: urlToOpen)
+// case .withdrawExchange:
+// ManualWithdraw(stack: stack.push(), url: urlToOpen,
exchange: nil, amountToTransfer: $amountToTransfer)
case .pay:
PaymentView(stack: stack.push(), url: urlToOpen)
case .payPull:
@@ -32,6 +36,8 @@ struct URLSheet: View {
P2pReceiveURIView(stack: stack.push(), url: urlToOpen)
case .payTemplate:
PayTemplateView(stack: stack.push(), url: urlToOpen)
+ case .refund:
+ RefundURIView(stack: stack.push(), url: urlToOpen)
// case .reward:
// RewardURIView(url: urlToOpen)
default: // Error view
diff --git
a/TalerWallet1/Views/Sheets/WithdrawBankIntegrated/WithdrawTOSView.swift
b/TalerWallet1/Views/Sheets/WithdrawBankIntegrated/WithdrawTOSView.swift
index 0142d42..0eba89c 100644
--- a/TalerWallet1/Views/Sheets/WithdrawBankIntegrated/WithdrawTOSView.swift
+++ b/TalerWallet1/Views/Sheets/WithdrawBankIntegrated/WithdrawTOSView.swift
@@ -26,13 +26,15 @@ struct WithdrawTOSView: View {
Content(symLog: symLog, exchangeTOS: exchangeTOS, myListStyle:
$myListStyle) {
Task { // runs on MainActor
do {
- if let exchangeBaseUrl {
- _ = try await
model.setExchangeTOSAcceptedM(exchangeBaseUrl, etag: exchangeTOS!.currentEtag)
+ if let exchangeBaseUrl, let exchangeTOS {
+ _ = try await
model.setExchangeTOSAcceptedM(exchangeBaseUrl, etag: exchangeTOS.currentEtag)
if acceptAction != nil {
acceptAction!()
} else { // just go back - caller will reload
self.presentationMode.wrappedValue.dismiss()
}
+ } else {
+ // TODO: error
}
} catch { // TODO: Show Error
symLog.log(error.localizedDescription)
@@ -110,9 +112,15 @@ extension WithdrawTOSView {
}
}
}.safeAreaInset(edge: .bottom) {
- Button(String(localized: "Accept Terms of Service",
comment: "Button"), action: acceptAction)
- .buttonStyle(TalerButtonStyle(type: .prominent))
- .padding(.horizontal)
+ let currentEtag = tos.currentEtag
+ let showButton = tos.acceptedEtag == nil ? true
+ : tos.acceptedEtag! == tos.currentEtag ?
false
+ :
true
+ if showButton {
+ Button(String(localized: "Accept Terms of Service",
comment: "Button"), action: acceptAction)
+ .buttonStyle(TalerButtonStyle(type: .prominent))
+ .padding(.horizontal)
+ }
}
.listStyle(myListStyle.style).anyView
} else {
diff --git a/TalerWallet1/Views/Transactions/TransactionDetailView.swift
b/TalerWallet1/Views/Transactions/TransactionDetailView.swift
index 4dd575f..666c4e1 100644
--- a/TalerWallet1/Views/Transactions/TransactionDetailView.swift
+++ b/TalerWallet1/Views/Transactions/TransactionDetailView.swift
@@ -22,7 +22,7 @@ extension Transaction { // for Dummys
}
// MARK: -
struct TransactionDetailView: View {
- private let symLog = SymLogV()
+ private let symLog = SymLogV(0)
let stack: CallStack
let transactionId: String
let reloadAction: ((_ transactionId: String) async throws -> Transaction)
@@ -76,6 +76,8 @@ struct TransactionDetailView: View {
return true
}
}
+ } else { // no sheet but the details view -> reload
+ checkReload(notification, logStr)
}
return false
}
@@ -124,7 +126,6 @@ struct TransactionDetailView: View {
.accessibilityFont(.body)
.accessibilityLabel(accessibilityDate)
.foregroundColor(colorSchemeContrast == .increased ?
.primary : .secondary)
-// .foregroundColor(moreContrast ? .primary : .secondary)
.listRowSeparator(.hidden)
HStack {
Text(verbatim: "|") // only reason for this
leading-aligned text is to get a nice full length listRowSeparator
@@ -134,7 +135,7 @@ struct TransactionDetailView: View {
Text("Status: \(common.txState.major.localizedState)")
} .listRowSeparator(.automatic)
.accessibilityFont(.title)
- SwitchCase(transaction: $transaction, hasDone: doneAction !=
nil)
+ TypeDetail(transaction: $transaction, hasDone: doneAction !=
nil)
if transaction.isAbortable { if let abortAction {
TransactionButton(transactionId: common.transactionId,
@@ -192,10 +193,47 @@ struct TransactionDetailView: View {
//}
//
//extension TransactionDetail {
- struct SwitchCase: View {
+ struct KycButton: View {
+ let destination: URL
+ @AppStorage("iconOnly") var iconOnly: Bool = false
+
+ var body: some View {
+ VStack(alignment: .leading) { // Show Hint that User must pass
KYC on website
+ if !iconOnly {
+ Text("You need to pass a KYC procedure")
+ .fixedSize(horizontal: false, vertical: true) //
wrap in scrollview
+ .multilineTextAlignment(.leading) //
otherwise
+ .listRowSeparator(.hidden)
+ }
+ Link("Open KYC website", destination: destination)
+ .buttonStyle(TalerButtonStyle(type: .prominent, badge:
NEEDS_KYC))
+ .accessibilityHint("Will go to KYC website to confirm this
withdrawal.")
+ }
+ }
+ }
+
+ struct ConfirmationButton: View {
+ let destination: URL
+ @AppStorage("iconOnly") var iconOnly: Bool = false
+
+ var body: some View {
+ VStack(alignment: .leading) { // Show Hint that User should
Confirm on bank website
+ if !iconOnly {
+ Text("Waiting for bank confirmation")
+ .fixedSize(horizontal: false, vertical: true) //
wrap in scrollview
+ .multilineTextAlignment(.leading) //
otherwise
+ .listRowSeparator(.hidden)
+ }
+ Link("Confirm with bank", destination: destination)
+ .buttonStyle(TalerButtonStyle(type: .prominent, badge:
CONFIRM_BANK))
+ .accessibilityHint("Will go to bank website to confirm
this withdrawal.")
+ }
+ }
+ }
+
+ struct TypeDetail: View {
@Binding var transaction: Transaction
let hasDone: Bool
- @AppStorage("iconOnly") var iconOnly: Bool = false
var body: some View {
let common = transaction.common
@@ -209,43 +247,25 @@ struct TransactionDetailView: View {
case .withdrawal(let withdrawalTransaction):
let details = withdrawalTransaction.details
if pending {
+ if transaction.isPendingKYC {
+ if let kycUrl = common.kycUrl {
+ if let destination = URL(string: kycUrl) {
+ KycButton(destination: destination)
+ }
+ }
+ }
let withdrawalDetails = details.withdrawalDetails
switch withdrawalDetails.type {
case .manual: // "Make a wire
transfer of \(amount) to"
- if transaction.isPendingKYC {
- if let kycUrl = common.kycUrl {
- if let destination = URL(string:
kycUrl) {
- VStack(alignment: .leading) {
// Show Hint that User must pass KYC on website
- if !iconOnly {
- Text("You need to pass
a KYC procedure")
-
.fixedSize(horizontal: false, vertical: true) // wrap in scrollview
-
.multilineTextAlignment(.leading) // otherwise
-
.listRowSeparator(.hidden)
- }
- Link("Open KYC website",
destination: destination)
-
.buttonStyle(TalerButtonStyle(type: .prominent, badge: NEEDS_KYC))
-
.accessibilityHint("Will go to KYC website to confirm this withdrawal.")
- }
- }
- }
- }
ManualDetailsV(common: common, details:
withdrawalDetails)
case .bankIntegrated: // "Confirm with
bank"
- let confirmed =
withdrawalDetails.confirmed ?? false
- if !confirmed {
- if let confirmationUrl =
withdrawalDetails.bankConfirmationUrl {
- if let destination = URL(string:
confirmationUrl) {
- VStack(alignment: .leading) {
// Show Hint that User should Confirm on bank website
- if !iconOnly {
- Text("Waiting for bank
confirmation")
-
.fixedSize(horizontal: false, vertical: true) // wrap in scrollview
-
.multilineTextAlignment(.leading) // otherwise
-
.listRowSeparator(.hidden)
- }
- Link("Confirm with bank",
destination: destination)
-
.buttonStyle(TalerButtonStyle(type: .prominent, badge: CONFIRM_BANK))
-
.accessibilityHint("Will go to bank website to confirm this withdrawal.")
+ if !transaction.isPendingKYC {
// both should never happen, but...
+ let confirmed =
withdrawalDetails.confirmed ?? false
+ if !confirmed {
+ if let confirmationUrl =
withdrawalDetails.bankConfirmationUrl {
+ if let destination =
URL(string: confirmationUrl) {
+
ConfirmationButton(destination: destination)
}
}
}
@@ -258,9 +278,7 @@ struct TransactionDetailView: View {
case .payment(let paymentTransaction):
let details = paymentTransaction.details
Text(details.info.summary)
- .accessibilityFont(.title2)
- .lineLimit(4)
- .padding(.bottom)
+ .accessibilityFont(.title3)
ThreeAmountsSheet(common: common, topAbbrev:
String(localized: "Pay:"),
topTitle: String(localized: "Sum to be
paid:"),
baseURL: nil, large: true) //
TODO: baseURL
diff --git a/TalerWallet1/Views/Transactions/TransactionRowView.swift
b/TalerWallet1/Views/Transactions/TransactionRowView.swift
index f4a6aa4..aafc403 100644
--- a/TalerWallet1/Views/Transactions/TransactionRowView.swift
+++ b/TalerWallet1/Views/Transactions/TransactionRowView.swift
@@ -46,6 +46,8 @@ struct TransactionRowContentV: View {
let done: Bool
let foreColor:Color
+ @Environment(\.colorSchemeContrast) private var colorSchemeContrast
+
public static func width(titles: (String, String?), isHorizontal: Bool,
sizeCategory: ContentSizeCategory) -> CGFloat {
let imageFont = TalerFont.uiFont(.largeTitle)
@@ -74,16 +76,21 @@ struct TransactionRowContentV: View {
let iconBadge = IconBadge(foreColor: foreColor, done: done, incoming:
incoming,
shouldConfirm: shouldConfirm, needsKYC: needsKYC)
let doneOrPending = done || pending
+ let increasedContrast = colorSchemeContrast == .increased
+ let textColor = doneOrPending ? .primary :
+ increasedContrast ? .secondary : WalletColors().gray3
HStack(spacing: 8) {
iconBadge
VStack(alignment: .leading) {
Text(centerTop)
- .strikethrough(!doneOrPending)
+ .foregroundColor(textColor)
+ .strikethrough(!doneOrPending, color: .red)
.accessibilityFont(.headline)
// .fontWeight(.medium) iOS 16
.padding(.bottom, -2.0)
+ .accessibilityLabel(doneOrPending ? centerTop : centerTop
+ ", canceled")
Text(centerBottom)
- .strikethrough(!doneOrPending)
+ .foregroundColor(textColor)
.accessibilityFont(.callout)
}
}
@@ -190,10 +197,10 @@ extension Transaction { // for PreViews
merchant: merchant,
summary: "some product summary",
products: [])
- let pDetails = PaymentTransactionDetails(proposalId: "some
proposal ID",
- totalRefundRaw:
Amount(currency: LONGCURRENCY, cent: 300),
- totalRefundEffective:
Amount(currency: LONGCURRENCY, cent: 280),
- info: info)
+ let pDetails = PaymentTransactionDetails(info: info,
+ proposalId: "some proposal ID",
+ totalRefundRaw: Amount(currency:
LONGCURRENCY, cent: 300),
+ totalRefundEffective: Amount(currency:
LONGCURRENCY, cent: 280))
self = .payment(PaymentTransaction(common: common, details:
pDetails))
}
}
diff --git a/TestFlight/WhatToTest.en-US.txt b/TestFlight/WhatToTest.en-US.txt
index b91d35f..452b0d7 100644
--- a/TestFlight/WhatToTest.en-US.txt
+++ b/TestFlight/WhatToTest.en-US.txt
@@ -1,4 +1,17 @@
+Version 0.9.3 (30)
+
+• New feature:
+- Bugfix: Manual withdrawal works again (was broken in 29)
+- Bugfix: Currency input with zero fractional digits (test.taler.net)
+
+
+Version 0.9.3 (29)
+
+• New feature: ToS in Exchanges Tab
+- Bugfix: P2P Send works again (was broken in 28)
+
+
Version 0.9.3 (28)
• Unsuccessful (Incomplete) transactions no longer have their own list, but
are now
@@ -14,7 +27,7 @@ Version 0.9.3 (27)
Notice the difference in the Pending list
• KYC in pending transactions accessible from details
-- BugFix: after P2P no QR code was shown
+- Bugfix: after P2P no QR code was shown
- Layout improvements iOS16+. We'll continue to support iOS15, it just won't
look so nice as on iOS 16+.
@@ -23,7 +36,7 @@ Version 0.9.3 (26)
• New feature: KYC Support. But you won't get a second chance if you don't use
the first one.
(KYC will be added to pending transactions in the next version)
-- BugFix: With more than one exchange currencies were mixed in P2P
+- Bugfix: With more than one exchange currencies were mixed in P2P
- The whole textfield can now be used to bring up the keyboard in P2P
@@ -32,7 +45,7 @@ Version 0.9.3 (25)
• New feature: Shortcuts Buttons (50,25,10,5) for P2P + Withdrawal
- CurrencyFormatter for P2P + Withdrawal
-- BugFix: Accessibility announcements always did reset the focus to start of
view
+- Bugfix: Accessibility announcements always did reset the focus to start of
view
A/B test result: Nobody liked GNU Taler (with SideView & Hamburger-button)
better,
thus we concentrate on Taler Wallet (with TabBar)
@@ -43,7 +56,7 @@ Version 0.9.3 (24)
• Sound & Haptics ON by default
• Blue Taler Logo
- Lots of Accessibility improvements
-- BugFix: P2P Transactions were started twice
+- Bugfix: P2P Transactions were started twice
- Incomplete Transactions no longer show "Obtained" or "Paid"
@@ -60,7 +73,7 @@ Version 0.9.3 (22)
Version 0.9.3 (21)
-- BugFix: P2P payments should work again
+- Bugfix: P2P payments should work again
- CurrencyFormatter for Balance
diff --git a/taler-swift/Sources/taler-swift/Amount.swift
b/taler-swift/Sources/taler-swift/Amount.swift
index 0d5a9ba..301f555 100644
--- a/taler-swift/Sources/taler-swift/Amount.swift
+++ b/taler-swift/Sources/taler-swift/Amount.swift
@@ -312,33 +312,43 @@ public final class Amount: Codable, Hashable, @unchecked
Sendable, CustomStringC
/// Multiplies by ten, then adds digit
public func shiftLeft(add digit: UInt8, _ inputDigits: UInt) {
- // how many digits to shift right (e.g. inputD=2 ==> shift:=6)
- let shift = Self.fractionalBaseDigits - inputDigits
- // mask to zero out fractions smaller than inputDigits
- let shiftMask = fractionalBase(shift)
-
- let carryMask = fractionalBase(Self.fractionalBaseDigits - 1)
- // get biggest fractional digit
- let carry = fraction / carryMask
- var remainder = fraction % carryMask
-// print("fraction: \(fraction) = \(carry) + \(remainder)")
-
- let shiftedInt = integer * 10 + UInt64(carry)
- if shiftedInt < Self.maxValue {
- self.integer = shiftedInt
-// print("remainder: \(remainder) / shiftMask \(shiftMask) =
\(remainder / shiftMask)")
- remainder = (remainder / shiftMask) * 10
- } else { // will get too big
- // Just swap the last significant digit for the one the user typed
last
- if shiftMask >= 10 {
- remainder = (remainder / (shiftMask / 10)) * 10
+ if inputDigits > 0 {
+ // how many digits to shift right (e.g. inputD=2 ==> shift:=6)
+ let shift = Self.fractionalBaseDigits - inputDigits
+ // mask to zero out fractions smaller than inputDigits
+ let shiftMask = fractionalBase(shift)
+
+ let carryMask = fractionalBase(Self.fractionalBaseDigits - 1)
+ // get biggest fractional digit
+ let carry = fraction / carryMask
+ var remainder = fraction % carryMask
+// print("fraction: \(fraction) = \(carry) + \(remainder)")
+
+ let shiftedInt = integer * 10 + UInt64(carry)
+ if shiftedInt < Self.maxValue {
+ self.integer = shiftedInt
+// print("remainder: \(remainder) / shiftMask \(shiftMask) =
\(remainder / shiftMask)")
+ remainder = (remainder / shiftMask) * 10
+ } else { // will get too big
+ // Just swap the last significant digit for the one the
user typed last
+ if shiftMask >= 10 {
+ remainder = (remainder / (shiftMask / 10)) * 10
+ } else {
+ remainder = (remainder / 10) * 10
+ }
+ }
+ let sum = remainder + UInt32(digit)
+ self.fraction = sum * shiftMask
+ // print("(remainder: \(remainder) + \(digit)) * base(shift)
\(shiftMask) = fraction \(fraction)")
+ } else {
+ let shiftedInt = integer * 10 + UInt64(digit)
+ if shiftedInt < Self.maxValue {
+ self.integer = shiftedInt
} else {
- remainder = (remainder / 10) * 10
+ self.integer = Self.maxValue
}
+ self.fraction = 0
}
- let sum = remainder + UInt32(digit)
- self.fraction = sum * shiftMask
-// print("(remainder: \(remainder) + \(digit)) * base(shift)
\(shiftMask) = fraction \(fraction)")
}
/// Sets all fractional digits after inputDigits to 0
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.
- [taler-taler-ios] branch master updated (be6a335 -> 989c5ea),
gnunet <=
- [taler-taler-ios] 03/24: Fix KYC/Confirm, gnunet, 2023/12/05
- [taler-taler-ios] 05/24: Refund, gnunet, 2023/12/05
- [taler-taler-ios] 07/24: Only main title, gnunet, 2023/12/05
- [taler-taler-ios] 06/24: Exchange: ToS, gnunet, 2023/12/05
- [taler-taler-ios] 04/24: ViewThatFits, gnunet, 2023/12/05
- [taler-taler-ios] 02/24: New "flags", gnunet, 2023/12/05
- [taler-taler-ios] 09/24: cleanup, gnunet, 2023/12/05
- [taler-taler-ios] 23/24: shortcutAction, gnunet, 2023/12/05
- [taler-taler-ios] 01/24: Logging, gnunet, 2023/12/05
- [taler-taler-ios] 21/24: amountToTransfer, gnunet, 2023/12/05