diff options
author | Marc Stibane <marc@taler.net> | 2023-10-24 22:44:55 +0200 |
---|---|---|
committer | Marc Stibane <marc@taler.net> | 2023-10-24 22:44:55 +0200 |
commit | bf7f8e33021e2e950b5b00ef5ffe44b7acfdabea (patch) | |
tree | ee7e1d2be88727a239521452b84e9f993e3c46d6 | |
parent | 812977bb22d06ee01d8a66259430769dc15f078a (diff) | |
download | taler-ios-bf7f8e33021e2e950b5b00ef5ffe44b7acfdabea.tar.gz taler-ios-bf7f8e33021e2e950b5b00ef5ffe44b7acfdabea.tar.bz2 taler-ios-bf7f8e33021e2e950b5b00ef5ffe44b7acfdabea.zip |
Layout for Pending - wip
-rw-r--r-- | TalerWallet1/Controllers/PublicConstants.swift | 2 | ||||
-rw-r--r-- | TalerWallet1/Views/Balances/BalanceRowView.swift | 11 | ||||
-rw-r--r-- | TalerWallet1/Views/Balances/BalancesSectionView.swift | 10 | ||||
-rw-r--r-- | TalerWallet1/Views/Balances/PendingRowView.swift | 155 | ||||
-rw-r--r-- | TalerWallet1/Views/HelperViews/View+needVStack.swift | 19 |
5 files changed, 162 insertions, 35 deletions
diff --git a/TalerWallet1/Controllers/PublicConstants.swift b/TalerWallet1/Controllers/PublicConstants.swift index 0271bdc..3b778bd 100644 --- a/TalerWallet1/Controllers/PublicConstants.swift +++ b/TalerWallet1/Controllers/PublicConstants.swift @@ -4,6 +4,8 @@ */ import Foundation +public let HSPACING = CGFloat(10) // space between items in HStack + public let LAUNCHDURATION: Double = 1.60 public let SLIDEDURATION: Double = 0.45 diff --git a/TalerWallet1/Views/Balances/BalanceRowView.swift b/TalerWallet1/Views/Balances/BalanceRowView.swift index fcff95e..27ded57 100644 --- a/TalerWallet1/Views/Balances/BalanceRowView.swift +++ b/TalerWallet1/Views/Balances/BalanceRowView.swift @@ -5,8 +5,6 @@ import SwiftUI import taler_swift -let SPACING = CGFloat(10) // space between the two buttons - struct BalanceLabel: View { let balanceTitle: String let horizontal: Bool @@ -50,7 +48,7 @@ struct BalanceButton: View { let amountFont = TalerFont.uiFont(.title) let titles = [(balanceTitle, balancesFont), (amountStr, amountFont)] - let needVStack = !iconOnly && Self.needVStack(titles, width: width, spacing: SPACING, sameSize: false) + let needVStack = !iconOnly && Self.needVStack(titles, width: width, spacing: HSPACING, sameSize: false) if needVStack { VStack(alignment: .leading, spacing: 0) { BalanceLabel(balanceTitle: balanceTitle, horizontal: false, amountStr: amountStr, iconOnly: iconOnly) @@ -87,10 +85,9 @@ struct BalanceRowView: View { let requestTitle2 = String(localized: "Payment", comment: "Bottom of button <Request Payment>") var body: some View { - SingleAxisGeometryReader { width in VStack (alignment: .trailing) { - let amountStr = currencyInfo?.string(for: amount.value) + let amountStr = currencyInfo?.string(for: amount.valueAsTuple) BalanceButton(amountStr: amountStr ?? amount.valueStr, rowAction: rowAction) let uiFont = TalerFont.uiFont(.title3) @@ -101,10 +98,10 @@ struct BalanceRowView: View { lineLimit: 5, sendDisabled: amount.isZero, sendAction: sendAction, recvAction: recvAction) // let _ = print("Screenwidth: \(UIScreen.screenWidth) Geometry: \(width) \(sizeCategory): \(sizeCategory)") - if Self.needVStack(titles, width: width, spacing: SPACING) { + if Self.needVStack(titles, width: width, spacing: HSPACING) { VStack { twoRowButtons } } else { - HStack(spacing: SPACING) { twoRowButtons } + HStack(spacing: HSPACING) { twoRowButtons } } } .accessibilityElement(children: .combine) diff --git a/TalerWallet1/Views/Balances/BalancesSectionView.swift b/TalerWallet1/Views/Balances/BalancesSectionView.swift index 80e446d..91872a8 100644 --- a/TalerWallet1/Views/Balances/BalancesSectionView.swift +++ b/TalerWallet1/Views/Balances/BalancesSectionView.swift @@ -89,7 +89,7 @@ extension BalancesSectionView: View { if hasPending { BalancesPendingRowView(symLog: symLog, stack: stack.push(), - currency: currency, + currencyInfo: currencyInfo, pendingTransactions: $pendingTransactions, reloadPending: reloadPending, reloadOneAction: reloadOneAction) @@ -160,7 +160,8 @@ extension BalancesSectionView: View { fileprivate struct BalancesPendingRowView: View { let symLog: SymLogV? let stack: CallStack - let currency: String + let currencyInfo: CurrencyInfo? +// @Binding var pendingTransactions: [Transaction] let reloadPending: (_ stack: CallStack) async -> () let reloadOneAction: ((_ transactionId: String) async throws -> Transaction) @@ -187,6 +188,7 @@ fileprivate struct BalancesPendingRowView: View { } var body: some View { + let currency: String = currencyInfo?.scope.currency ?? "" let (pendingIncoming, pendingOutgoing) = computePending(currency: currency) NavigationLink { @@ -204,11 +206,11 @@ fileprivate struct BalancesPendingRowView: View { VStack(spacing: 6) { var rows = 0 if !pendingIncoming.isZero { - PendingRowView(amount: pendingIncoming, incoming: true) + PendingRowView(amount: pendingIncoming, currencyInfo: currencyInfo, incoming: true) let _ = (rows+=1) } if !pendingOutgoing.isZero { - PendingRowView(amount: pendingOutgoing, incoming: false) + PendingRowView(amount: pendingOutgoing, currencyInfo: currencyInfo, incoming: false) let _ = (rows+=1) } if rows == 0 { diff --git a/TalerWallet1/Views/Balances/PendingRowView.swift b/TalerWallet1/Views/Balances/PendingRowView.swift index c883f57..6604bc1 100644 --- a/TalerWallet1/Views/Balances/PendingRowView.swift +++ b/TalerWallet1/Views/Balances/PendingRowView.swift @@ -5,43 +5,158 @@ import SwiftUI import taler_swift -/// This view shows a pending transaction row in a currency section -struct PendingRowView: View { - let amount: Amount +struct InOrOutView: View { + let title: (String, String) + let horizontal: Bool let incoming: Bool + let imageName: String + + public static func width(image1: String, title1: String, title2: String) -> CGFloat { + let imageFont = TalerFont.uiFont(.largeTitle) + let uiFont = TalerFont.uiFont(.body) + + let image2 = "++" + let imageWidth = image2.widthOfString(usingUIFont: imageFont) + 8.0 //.padding(.trailing) + let title1Width = title1.widthOfString(usingUIFont: uiFont) + let title2Width = title2.widthOfString(usingUIFont: uiFont) +// print("image: ", imageWidth, " title: ", max(title1Width, title2Width)) + return imageWidth + max(title1Width, title2Width) + } var body: some View { - HStack { + let (title1, title2) = title + HStack(spacing: 0) { let pendingColor = WalletColors().pendingColor(incoming) - Image(systemName: incoming ? "text.badge.plus" - : "text.badge.minus") + Image(systemName: imageName) .foregroundColor(pendingColor) .accessibilityFont(.largeTitle) .accessibility(hidden: true) - - Spacer() - Text("pending\n" + (incoming ? "incoming" : "outgoing")) +// .padding(.trailing) + Text(horizontal ? (title1 + "\n" + title2) + : (title1 + " " + title2)) + .lineLimit(2) .accessibilityFont(.body) - Spacer() - VStack(alignment: .trailing) { - let sign = incoming ? "+" : "-" - let valueStr = sign + amount.valueStr - Text(valueStr) - .foregroundColor(pendingColor) - .accessibilityFont(.title) - .monospacedDigit() + } + } +} + +struct PendingAmountView: View { + let amount: Amount + let currencyInfo: CurrencyInfo? + let incoming: Bool + + public static func amountStr(amount: Amount, currencyInfo: CurrencyInfo?, incoming: Bool) -> String { + let sign = incoming ? "+ " : "- " + let amountStr = currencyInfo?.string(for: amount.valueAsTuple) + return sign + (amountStr ?? amount.valueStr) + } + + public static func width(amount: Amount, currencyInfo: CurrencyInfo?, incoming: Bool) -> CGFloat { + let valueStr = Self.amountStr(amount: amount, currencyInfo: currencyInfo, incoming: incoming) + let uiFont = TalerFont.uiFont(.title) + let width = valueStr.widthOfString(usingUIFont: uiFont) +// print("Amount width: ", width) + return width + } + + var body: some View { + let pendingColor = WalletColors().pendingColor(incoming) + let valueStr = Self.amountStr(amount: amount, currencyInfo: currencyInfo, incoming: incoming) + Text(valueStr) + .foregroundColor(pendingColor) + .accessibilityFont(.title) + .monospacedDigit() + } +} + +struct PendingLabel: View { + let amount: Amount + let currencyInfo: CurrencyInfo? + let incoming: Bool + let horizontal: Bool // true: HStack{ image + pending Xcoming + amount } + let title: (String, String) + let imageName: String + + var body: some View { + Group { // can either be horizontal (preferred) or vertical (if doesn't fit horizontally) + InOrOutView(title: title, horizontal: horizontal, incoming: incoming, imageName: imageName) + if horizontal { // Group is an HStack already => just add Spacer + Amount + Spacer(minLength: 0) + PendingAmountView(amount: amount, currencyInfo: currencyInfo, incoming: incoming) + } else { // Group is a VStack => need HStack + Spacer to shift Amount to the trailing edge + HStack(spacing: 0) { + Spacer(minLength: 0) + PendingAmountView(amount: amount, currencyInfo: currencyInfo, incoming: incoming) +} } } } } + +/// This view shows a pending transaction row in a currency section +struct PendingRowView: View { + let amount: Amount + let currencyInfo: CurrencyInfo? + let incoming: Bool + + let inTitle1 = String(localized: "pending", comment: "Top of line <pending incoming>") + let inTitle2 = String(localized: "incoming", comment: "Bottom of line <pending incoming>") + let outTitle1 = String(localized: "pending", comment: "Top of line <pending outgoing>") + let outTitle2 = String(localized: "outgoing", comment: "Bottom of line <pending outgoing>") + + func needVStack(available: CGFloat, inOrOutWidth: CGFloat, valueWidth: CGFloat) -> Bool { + available < (inOrOutWidth + valueWidth + 40) + } + + var body: some View { + let imageName = incoming ? "text.badge.plus" + : "text.badge.minus" + let imageStr = String("\(Image(systemName: imageName))") + SingleAxisGeometryReader { width in + Group { + let title = incoming ? (inTitle1, inTitle2) + : (outTitle1, outTitle2) + let inOrOutWidth = InOrOutView.width(image1: imageStr, + title1: incoming ? inTitle1 : outTitle1, + title2: incoming ? inTitle2 : outTitle2) + let valueWidth = PendingAmountView.width(amount: amount, + currencyInfo: currencyInfo, + incoming: incoming) +// let _ = print(width, " - ", inOrOutWidth + valueWidth, " = ", width - (inOrOutWidth + valueWidth)) + if needVStack(available: width, inOrOutWidth: inOrOutWidth, valueWidth: valueWidth) { + VStack(alignment: .leading, spacing: 0) { + PendingLabel(amount: amount, currencyInfo: currencyInfo, + incoming: incoming, horizontal: false, + title: title, imageName: imageName) + } + } else { + HStack(spacing: 0) { + PendingLabel(amount: amount, currencyInfo: currencyInfo, + incoming: incoming, horizontal: true, + title: title, imageName: imageName) + } + } } + .accessibilityElement(children: .combine) } - .accessibilityElement(children: .combine) } } // MARK: - #if DEBUG struct PendingRowView_Previews: PreviewProvider { static var previews: some View { + let scope = ScopeInfo(type: .global, currency: TESTCURRENCY) + let specs = CurrencySpecification(name: TESTCURRENCY, +// decimalSeparator: ".", groupSeparator: "'", + fractionalInputDigits: 0, + fractionalNormalDigits: 0, + fractionalTrailingZeroDigits: 0, +// isCurrencyNameLeading: true, + altUnitNames: [0 : "¥"]) + let formatter = CurrencyFormatter.formatter(scope: scope, + specs: specs) + let currencyInfo = CurrencyInfo(scope: scope, specs: specs, formatter: formatter) + let test = try! Amount(fromString: TESTCURRENCY + ":1.23") + let demo = try! Amount(fromString: DEMOCURRENCY + ":1234.56") List { - PendingRowView(amount: try! Amount(fromString: LONGCURRENCY + ":4.8"), incoming: true) - PendingRowView(amount: try! Amount(fromString: LONGCURRENCY + ":3.25"), incoming: false) + PendingRowView(amount: test, currencyInfo: currencyInfo, incoming: true) + PendingRowView(amount: demo, currencyInfo: currencyInfo, incoming: false) } } } diff --git a/TalerWallet1/Views/HelperViews/View+needVStack.swift b/TalerWallet1/Views/HelperViews/View+needVStack.swift index e71cf72..fc6f18b 100644 --- a/TalerWallet1/Views/HelperViews/View+needVStack.swift +++ b/TalerWallet1/Views/HelperViews/View+needVStack.swift @@ -6,9 +6,16 @@ import SwiftUI import UIKit extension View { - /// returns true if any of the strings in 'titles' wouldn't fit in a view 1/'numViews' the size of 'width', with 'spacing' - static func needVStack(_ titles: [(String, UIFont)], width: CGFloat, spacing: CGFloat, - sameSize: Bool = true, numViews: Int = 2) -> Bool { + /// if sameSize then this searches for the longest title + /// returns true if any of the strings in 'titles' wouldn't fit in a view 1/'numViews' of the size of 'width', with 'spacing' + /// if !sameSize then all titles are added with spacing + static func needVStack(_ titles: [(String, UIFont)], + width: CGFloat, // total width available + spacing: CGFloat, // between titles + sameSize: Bool = true, + numViews: Int = 2, + currency: String = "") + -> Bool { let padding: CGFloat = 20 // TODO: depend on myListStyle var maxTitleWidth: CGFloat = 0 var totalWidth = padding @@ -25,7 +32,11 @@ extension View { let totalSpacing = spacing * CGFloat(numViews - 1) let availableWidth = (width / CGFloat(numViews)) - totalSpacing totalWidth += totalSpacing - + if sameSize { + print("❗️\(currency) available: \(availableWidth) needed: \(neededWidth)") + } else { + print("❗️\(currency) width: \(width) total: \(totalWidth)") + } return sameSize ? neededWidth > availableWidth : totalWidth > width } |