taler-ios

iOS apps for GNU Taler (wallet)
Log | Files | Refs | README | LICENSE

commit aec0b491e69749cbaab8e409c79eed854d981924
parent 07624076e60d1accca424a03663c8c0490d1a870
Author: Marc Stibane <marc@taler.net>
Date:   Sat, 21 Oct 2023 21:05:28 +0200

Use CurrencyFormatter for Balance

Diffstat:
MTalerWallet1/Helper/CurrencySpecification.swift | 49+++++++++++++++++++++++++++++++++++++++++++++++++
MTalerWallet1/Helper/TalerStrings.swift | 22++++++++++++++++++++++
MTalerWallet1/Views/Balances/BalanceRowView.swift | 7+++++--
MTalerWallet1/Views/Balances/BalancesSectionView.swift | 19++++++++++++-------
4 files changed, 88 insertions(+), 9 deletions(-)

diff --git a/TalerWallet1/Helper/CurrencySpecification.swift b/TalerWallet1/Helper/CurrencySpecification.swift @@ -9,6 +9,55 @@ public struct CurrencyInfo { let scope: ScopeInfo let specs: CurrencySpecification let formatter: CurrencyFormatter + + func string(for value: Double, useSymbol: Bool = true) -> String { + formatter.setUseSymbol(useSymbol) + if let valueStr = formatter.string(for: value) { + let decimalSeparator = formatter.decimalSeparator ?? specs.decimalSeparator + if let decimalIndex = valueStr.endIndex(of: decimalSeparator) { + var fraction = 1 + var integerStr = String(valueStr[..<decimalIndex]) + let fractionStr = valueStr[decimalIndex...] + for character in fractionStr { + let charStr = String(character) + if let digit = Int(charStr) { + let digitStr = fraction > specs.fractionalNormalDigits ? + SuperScriptDigits(charStr) : charStr + integerStr += digitStr + } else { integerStr += charStr } + fraction += 1 + } + return integerStr + } + return valueStr + } else { // formatter doesn't work - we need to format ourselves + var madeUpStr = "" + var currencyName = scope.currency + var hasSymbol = false + if useSymbol && formatter.hasAltUnitName0 { + if let symbol = specs.altUnitNames?[0] { + currencyName = symbol + hasSymbol = true + } + } + if specs.isCurrencyNameLeading { + madeUpStr = currencyName + if !hasSymbol { + madeUpStr += " " + } + } + let integerPart = Int(value) + madeUpStr += String(integerPart) + madeUpStr += specs.decimalSeparator + if !specs.isCurrencyNameLeading { + if !hasSymbol { + madeUpStr += " " + } + madeUpStr += currencyName + } + return madeUpStr + } // DIY + } } public struct CurrencySpecification2: Codable, Sendable { diff --git a/TalerWallet1/Helper/TalerStrings.swift b/TalerWallet1/Helper/TalerStrings.swift @@ -14,6 +14,28 @@ extension StringProtocol { } return String(self) } + + func index<S: StringProtocol>(of string: S, options: String.CompareOptions = []) -> Index? { + range(of: string, options: options)?.lowerBound + } + func endIndex<S: StringProtocol>(of string: S, options: String.CompareOptions = []) -> Index? { + range(of: string, options: options)?.upperBound + } + func indices<S: StringProtocol>(of string: S, options: String.CompareOptions = []) -> [Index] { + ranges(of: string, options: options).map(\.lowerBound) + } + func ranges<S: StringProtocol>(of string: S, options: String.CompareOptions = []) -> [Range<Index>] { + var result: [Range<Index>] = [] + var startIndex = self.startIndex + while startIndex < endIndex, + let range = self[startIndex...] + .range(of: string, options: options) { + result.append(range) + startIndex = range.lowerBound < range.upperBound ? range.upperBound : + index(range.lowerBound, offsetBy: 1, limitedBy: endIndex) ?? endIndex + } + return result + } } extension String { diff --git a/TalerWallet1/Views/Balances/BalanceRowView.swift b/TalerWallet1/Views/Balances/BalanceRowView.swift @@ -74,6 +74,7 @@ struct BalanceButton: View { /// [Send Coins] [Receive Coins] Balance struct BalanceRowView: View { let amount: Amount + let currencyInfo: CurrencyInfo? let sendAction: () -> Void let recvAction: () -> Void let rowAction: () -> Void @@ -86,9 +87,11 @@ struct BalanceRowView: View { let requestTitle2 = String(localized: "Payment", comment: "Bottom of button <Request Payment>") var body: some View { + SingleAxisGeometryReader { width in VStack (alignment: .trailing) { - BalanceButton(amountStr: amount.valueStr, // TODO: CurrencyFormatter? + let amountStr = currencyInfo?.string(for: amount.value) + BalanceButton(amountStr: amountStr ?? amount.valueStr, rowAction: rowAction) let uiFont = TalerFont.uiFont(.title3) let titles = [(requestTitle1, uiFont), (requestTitle2, uiFont), (sendTitle1, uiFont), (sendTitle2, uiFont)] @@ -109,7 +112,7 @@ struct BalanceRowView: View { } } // MARK: - -#if DEBUG +#if false // DEBUG struct BalanceRowView_Previews: PreviewProvider { static var previews: some View { let test = try! Amount(fromString: TESTCURRENCY + ":1.23") diff --git a/TalerWallet1/Views/Balances/BalancesSectionView.swift b/TalerWallet1/Views/Balances/BalancesSectionView.swift @@ -23,6 +23,7 @@ struct BalancesSectionView { @Binding var summary: String @EnvironmentObject private var model: WalletModel + @EnvironmentObject private var controller: Controller @State private var isShowingDetailView = false @@ -67,6 +68,7 @@ extension BalancesSectionView: View { let _ = symLog.vlog() // just to get the # to compare it with .onAppear & onDisappear #endif let currency = balance.scopeInfo.currency + let currencyInfo = controller.info(for: currency) Section { if "KUDOS" == currency && !balance.available.isZero { @@ -76,6 +78,7 @@ extension BalancesSectionView: View { } BalancesNavigationLinksView(stack: stack.push(), balance: balance, + currencyInfo: currencyInfo, centsToTransfer: $centsToTransfer, summary: $summary, // buttonSelected: $buttonSelected, @@ -221,6 +224,7 @@ fileprivate struct BalancesPendingRowView: View { fileprivate struct BalancesNavigationLinksView: View { let stack: CallStack let balance: Balance + let currencyInfo: CurrencyInfo? // let sectionCount: Int @Binding var centsToTransfer: UInt64 @Binding var summary: String @@ -273,13 +277,14 @@ fileprivate struct BalancesNavigationLinksView: View { }, tag: 3, selection: $buttonSelected ) { EmptyView() }.frame(width: 0).opacity(0).hidden() // TransactionsListView - BalanceRowView(amount: balance.available, sendAction: { - selectAndUpdate(1) // will trigger SendAmount NavigationLink - }, recvAction: { - selectAndUpdate(2) // will trigger RequestPayment NavigationLink - }, rowAction: { - buttonSelected = 3 // will trigger TransactionList NavigationLink - }) + BalanceRowView(amount: balance.available, currencyInfo: currencyInfo, + sendAction: { + selectAndUpdate(1) // will trigger SendAmount NavigationLink + }, recvAction: { + selectAndUpdate(2) // will trigger RequestPayment NavigationLink + }, rowAction: { + buttonSelected = 3 // will trigger TransactionList NavigationLink + }) } } }