gnunet-svn
[Top][All Lists]
Advanced

[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.



reply via email to

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