[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[taler-taler-ios] 25/36: amountToTransfer Currency
From: |
gnunet |
Subject: |
[taler-taler-ios] 25/36: amountToTransfer Currency |
Date: |
Mon, 13 Nov 2023 21:27:30 +0100 |
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 02e39080f1d77fdfa82cc3ec7c29570d83ec7311
Author: Marc Stibane <marc@taler.net>
AuthorDate: Sun Nov 12 18:22:39 2023 +0100
amountToTransfer Currency
---
TalerWallet1/Views/Exchange/ManualWithdraw.swift | 5 +-
TalerWallet1/Views/HelperViews/CurrencyField.swift | 98 ++++++++++------------
.../Views/HelperViews/CurrencyInputView.swift | 26 +++---
TalerWallet1/Views/Peer2peer/RequestPayment.swift | 3 +-
TalerWallet1/Views/Peer2peer/SendAmount.swift | 3 +-
taler-swift/Sources/taler-swift/Amount.swift | 39 ++++++---
6 files changed, 87 insertions(+), 87 deletions(-)
diff --git a/TalerWallet1/Views/Exchange/ManualWithdraw.swift
b/TalerWallet1/Views/Exchange/ManualWithdraw.swift
index 524ac3a..d94d5ae 100644
--- a/TalerWallet1/Views/Exchange/ManualWithdraw.swift
+++ b/TalerWallet1/Views/Exchange/ManualWithdraw.swift
@@ -28,13 +28,12 @@ struct ManualWithdraw: View {
#endif
let currency = exchange.currency ?? String(localized: "Unknown",
comment: "unknown currency")
let navTitle = String(localized: "NavTitle_Withdraw (currency)",
defaultValue: "Withdraw \(currency)")
- let currencyField = CurrencyField(amount: $amountToTransfer) //
becomeFirstResponder
// let agePicker = AgePicker(ageMenuList: $ageMenuList, selectedAge:
$selectedAge)
ScrollView {
VStack {
- CurrencyInputView(currencyField: currencyField,
- title: String(localized: "Amount to
withdraw:"))
+ CurrencyInputView(amount: $amountToTransfer,
+ title: String(localized: "Amount to
withdraw:"))
let someCoins = SomeCoins(details: withdrawalAmountDetails)
QuiteSomeCoins(someCoins: someCoins, shouldShowFee: true,
currency: currency, amountEffective:
withdrawalAmountDetails?.amountEffective)
diff --git a/TalerWallet1/Views/HelperViews/CurrencyField.swift
b/TalerWallet1/Views/HelperViews/CurrencyField.swift
index c8bbf09..33c065d 100644
--- a/TalerWallet1/Views/HelperViews/CurrencyField.swift
+++ b/TalerWallet1/Views/HelperViews/CurrencyField.swift
@@ -22,10 +22,14 @@
import SwiftUI
import UIKit
import taler_swift
+import SymLog
@MainActor
-public struct CurrencyField: View {
+struct CurrencyField: View {
+ private let symLog = SymLogV(0)
@Binding var amount: Amount // the `value´
+ let currencyInfo: CurrencyInfo
+
private var currencyInputField: CurrencyInputField! = nil
public func becomeFirstResponder() -> Void {
@@ -36,34 +40,22 @@ public struct CurrencyField: View {
currencyInputField.resignFirstResponder()
}
- private var label: String {
- let mag = pow(10, formatter.maximumFractionDigits)
- return formatter.string(for: Decimal(value) / mag) ?? ""
- }
-
- public init(value: Binding<UInt64>, currency: String, formatter:
NumberFormatter) {
- self._value = value
- self.currency = currency
- self.formatter = formatter
- self.currencyInputField = CurrencyInputField(value: $value, formatter:
formatter)
+ public init(amount: Binding<Amount>, currencyInfo: CurrencyInfo) {
+ self._amount = amount
+ self.currencyInfo = currencyInfo
+ self.currencyInputField = CurrencyInputField(amount: self.$amount,
+ currencyInfo: currencyInfo)
}
- public init(value: Binding<UInt64>, currency: String) {
- let formatter = NumberFormatter()
- formatter.locale = .current
- formatter.numberStyle = .currency
- formatter.currencySymbol = currency
- formatter.minimumFractionDigits = 2
- formatter.maximumFractionDigits = 2
-
- self.init(value: value, currency: currency, formatter: formatter)
- }
-
- public var body: some View {
+ var body: some View {
+#if DEBUG
+ let _ = Self._printChanges()
+ let _ = symLog.vlog(amount.description) // just to get the # to
compare it with .onAppear & onDisappear
+#endif
ZStack {
// Text view to display the formatted currency
// Set as priority so CurrencyInputField size doesn't affect parent
- Text(label)
+ Text(amount.string(currencyInfo))
.layoutPriority(1)
// Input text field to handle UI
@@ -90,8 +82,8 @@ class NoCaretTextField: UITextField {
@MainActor
struct CurrencyInputField: UIViewRepresentable {
- @Binding var value: UInt64
- var formatter: NumberFormatter
+ @Binding var amount: Amount
+ let currencyInfo: CurrencyInfo
private let textField = NoCaretTextField(frame: .zero)
func makeCoordinator() -> Coordinator {
@@ -126,7 +118,7 @@ struct CurrencyInputField: UIViewRepresentable {
)
// Set initial textfield text
- context.coordinator.updateText(value, textField: textField)
+ context.coordinator.updateText(amount, textField: textField)
return textField
}
@@ -144,30 +136,33 @@ struct CurrencyInputField: UIViewRepresentable {
self.input = currencyTextField
}
- func setValue(_ value: UInt64, textField: UITextField) {
+ func setValue(_ amount: Amount, textField: UITextField) {
+ // Update hidden textfield text
+ updateText(amount, textField: textField)
// Update input value
- input.value = value
-
- // Update textfield text
- updateText(value, textField: textField)
+// print(input.amount.description, " := ", amount.description)
+ input.amount = amount
}
- func updateText(_ value: UInt64, textField: UITextField) {
+ func updateText(_ amount: Amount, textField: UITextField) {
// Update field text and last valid input text
- textField.text = String(value)
- lastValidInput = String(value)
+ lastValidInput = amount.plainString(input.currencyInfo)
+// print(lastValidInput)
+ textField.text = lastValidInput
}
func textField(_ textField: UITextField, shouldChangeCharactersIn
range: NSRange, replacementString string: String) -> Bool {
// If replacement string is empty, we can assume the backspace key
was hit
if string.isEmpty {
// Resign first responder when delete is hit when value is 0
- if input.value == 0 {
+ if input.amount.isZero {
textField.resignFirstResponder()
+ } else {
+ // Remove trailing digit: divide value by 10
+ let amount = input.amount.copy()
+ amount.removeDigit(input.currencyInfo)
+ setValue(amount, textField: textField)
}
-
- // Remove trailing digit
- setValue(UInt64(input.value / 10), textField: textField)
}
return true
}
@@ -189,7 +184,7 @@ struct CurrencyInputField: UIViewRepresentable {
}
// Find new character and try to get an Int value from it
- guard let char = char, let digit = Int(String(char)) else {
+ guard let char, let digit = UInt8(String(char)), digit <= 9 else {
// New character could not be converted to Int
// Revert to last valid text
textField.text = lastValidInput
@@ -197,27 +192,18 @@ struct CurrencyInputField: UIViewRepresentable {
}
// Multiply by 10 to shift numbers one position to the left,
revert if an overflow occurs
- let (multValue, multOverflow) =
input.value.multipliedReportingOverflow(by: 10)
- if multOverflow {
- textField.text = lastValidInput
- return
- }
-
// Add the new trailing digit, revert if an overflow occurs
- let (addValue, addOverflow) =
multValue.addingReportingOverflow(UInt64(digit))
- if addOverflow {
- textField.text = lastValidInput
- return
- }
+ let amount = input.amount.copy()
+ amount.addDigit(digit, currencyInfo: input.currencyInfo)
// If new value has more digits than allowed by formatter, revert
- if input.formatter.maximumFractionDigits +
input.formatter.maximumIntegerDigits < String(addValue).count {
- textField.text = lastValidInput
- return
- }
+// if input.formatter.maximumFractionDigits +
input.formatter.maximumIntegerDigits < String(addValue).count {
+// textField.text = lastValidInput
+// return
+// }
// Update new value
- setValue(addValue, textField: textField)
+ setValue(amount, textField: textField)
}
}
}
diff --git a/TalerWallet1/Views/HelperViews/CurrencyInputView.swift
b/TalerWallet1/Views/HelperViews/CurrencyInputView.swift
index 156a609..ef7dcc4 100644
--- a/TalerWallet1/Views/HelperViews/CurrencyInputView.swift
+++ b/TalerWallet1/Views/HelperViews/CurrencyInputView.swift
@@ -3,13 +3,18 @@
* See LICENSE.md
*/
import SwiftUI
+import taler_swift
struct CurrencyInputView: View {
- let currencyField: CurrencyField
+ @Binding var amount: Amount // the `value´
let title: String
+ @EnvironmentObject private var controller: Controller
@State var hasBeenShown = false
+
var body: some View {
+ let currencyInfo = controller.info(for: amount.currencyStr,
controller.currencyTicker)
+ let currencyField = CurrencyField(amount: $amount, currencyInfo:
currencyInfo)
VStack (alignment: .leading) {
Text(title)
// .padding(.top)
@@ -22,9 +27,9 @@ struct CurrencyInputView: View {
.textFieldStyle(.roundedBorder)
}.onAppear { // make CurrencyField show the keyboard after 0.4
seconds
if hasBeenShown {
- print("❗️Yikes: CurrencyInputView hasBeenShown")
+// print("❗️Yikes: CurrencyInputView hasBeenShown")
} else {
- print("❗️Yikes: First CurrencyInputView❗️")
+// print("❗️Yikes: First CurrencyInputView❗️")
DispatchQueue.main.asyncAfter(deadline: .now() + 0.4) {
hasBeenShown = true
currencyField.becomeFirstResponder()
@@ -37,20 +42,19 @@ struct CurrencyInputView: View {
}
// MARK: -
#if DEBUG
-fileprivate struct BindingViewContainer : View {
- @State var centsToTransfer: UInt64 = 0
+struct CurrencyInputView_Previews: PreviewProvider {
+ struct StateContainer : View {
+ @State var amountToTransfer = Amount(currency: LONGCURRENCY, cent: 0)
var body: some View {
- let currencyField = CurrencyField(value: $centsToTransfer, currency:
LONGCURRENCY)
- CurrencyInputView(currencyField: currencyField,
- title: "Amount to withdraw:")
+ CurrencyInputView(amount: $amountToTransfer,
+ title: "Amount to withdraw:")
}
-}
+ }
-struct CurrencyInputView_Previews: PreviewProvider {
static var previews: some View {
List {
- BindingViewContainer()
+ StateContainer()
}
}
}
diff --git a/TalerWallet1/Views/Peer2peer/RequestPayment.swift
b/TalerWallet1/Views/Peer2peer/RequestPayment.swift
index b0c6708..252c97d 100644
--- a/TalerWallet1/Views/Peer2peer/RequestPayment.swift
+++ b/TalerWallet1/Views/Peer2peer/RequestPayment.swift
@@ -26,10 +26,9 @@ struct RequestPayment: View {
#endif
let currency = amountToTransfer.currencyStr
let navTitle = String(localized: "Request Money", comment: "Dialog
Title")
- let currencyField = CurrencyField(amount: $amountToTransfer)
ScrollView { VStack {
- CurrencyInputView(currencyField: currencyField,
+ CurrencyInputView(amount: $amountToTransfer,
title: String(localized: "Amount to request:"))
let someCoins = SomeCoins(details: peerPullCheck)
diff --git a/TalerWallet1/Views/Peer2peer/SendAmount.swift
b/TalerWallet1/Views/Peer2peer/SendAmount.swift
index f03f850..7aa9190 100644
--- a/TalerWallet1/Views/Peer2peer/SendAmount.swift
+++ b/TalerWallet1/Views/Peer2peer/SendAmount.swift
@@ -38,7 +38,6 @@ struct SendAmount: View {
#endif
let currency = amountAvailable.currencyStr
let navTitle = String(localized: "Send \(currency)", comment: "Send
currency, Dialog Title")
- let currencyField = CurrencyField(amount: $amountToTransfer)
let fee = fee(ppCheck: peerPushCheck)
ScrollView {
VStack(alignment: .trailing) {
@@ -46,7 +45,7 @@ struct SendAmount: View {
Text("Available: \(available)")
.accessibilityFont(.title3)
.padding(.bottom, 2)
- CurrencyInputView(currencyField: currencyField,
+ CurrencyInputView(amount: $amountToTransfer,
title: String(localized: "Amount to send:"))
Text("+ \(fee) payment fee")
.accessibilityFont(.body)
diff --git a/taler-swift/Sources/taler-swift/Amount.swift
b/taler-swift/Sources/taler-swift/Amount.swift
index 938b6dc..86814f7 100644
--- a/taler-swift/Sources/taler-swift/Amount.swift
+++ b/taler-swift/Sources/taler-swift/Amount.swift
@@ -247,7 +247,7 @@ public final class Amount: Codable, Hashable, @unchecked
Sendable, CustomStringC
/// Copies an amount.
/// - Returns: A copy of the amount.
- func copy() -> Amount {
+ public func copy() -> Amount {
Amount(currency: currency, integer: integer, fraction: fraction)
}
@@ -283,36 +283,49 @@ public final class Amount: Codable, Hashable, @unchecked
Sendable, CustomStringC
/// Divides by ten
public func shiftRight() {
- var remainder = integer % 10
+ var remainder = UInt32(integer % 10)
self.integer = integer / 10
- let fractionalBase64 = UInt64(fractionalBase())
- remainder = (remainder * fractionalBase64) + UInt64(fraction)
- self.fraction = UInt32(remainder / 10)
+ remainder = remainder * fractionalBase() + fraction
+ self.fraction = remainder / 10
}
/// Multiplies by ten, then adds digit
public func shiftLeft(add digit: UInt8, _ inputDigits: UInt) {
- let mask = fractionalBase(Self.fractionalBaseDigits - inputDigits)
- let shiftedInt = integer * 10
- + UInt64(fraction / (fractionalBase() / 10))
+ // 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
- let remainder = (fraction % mask) * 10 + UInt32(digit)
- self.fraction = remainder * fractionalBase(inputDigits)
+// 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
- let remainder = (fraction % (mask / 10)) * 10 + UInt32(digit)
- self.fraction = remainder * fractionalBase(inputDigits)
+ 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)")
}
/// Sets all fractional digits after inputDigits to 0
public func mask(_ inputDigits: UInt) {
let mask = fractionalBase(Self.fractionalBaseDigits - inputDigits)
let remainder = fraction % mask
- self.fraction = remainder * fractionalBase(inputDigits)
+ self.fraction -= remainder
}
/// Adds two amounts together.
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.
- [taler-taler-ios] 09/36: cleanup, zero, (continued)
- [taler-taler-ios] 09/36: cleanup, zero, gnunet, 2023/11/13
- [taler-taler-ios] 29/36: less logging, gnunet, 2023/11/13
- [taler-taler-ios] 13/36: once at very first startup, gnunet, 2023/11/13
- [taler-taler-ios] 15/36: About with explicit link to taler.net, gnunet, 2023/11/13
- [taler-taler-ios] 28/36: Cleanup property wrappers, gnunet, 2023/11/13
- [taler-taler-ios] 22/36: amountToTransfer ManualWithdraw, gnunet, 2023/11/13
- [taler-taler-ios] 33/36: Announce shouldn't change screen, gnunet, 2023/11/13
- [taler-taler-ios] 34/36: Previews, gnunet, 2023/11/13
- [taler-taler-ios] 32/36: Shortcuts (50,25,10,5), gnunet, 2023/11/13
- [taler-taler-ios] 11/36: Debugging, gnunet, 2023/11/13
- [taler-taler-ios] 25/36: amountToTransfer Currency,
gnunet <=
- [taler-taler-ios] 16/36: TransactionsArraySliceV, gnunet, 2023/11/13
- [taler-taler-ios] 20/36: amountToTransfer Request, gnunet, 2023/11/13
- [taler-taler-ios] 26/36: Minimalistic, gnunet, 2023/11/13
- [taler-taler-ios] 31/36: Use `te´and `ku´ for previews, gnunet, 2023/11/13
- [taler-taler-ios] 10/36: @Published currencyTicker, gnunet, 2023/11/13
- [taler-taler-ios] 35/36: Check Available, accessibility, gnunet, 2023/11/13
- [taler-taler-ios] 36/36: Bump version to 0.9.3 (25), gnunet, 2023/11/13
- [taler-taler-ios] 08/36: Cleanup, gnunet, 2023/11/13