summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc Stibane <marc@taler.net>2023-10-15 23:28:12 +0200
committerMarc Stibane <marc@taler.net>2023-10-15 23:28:12 +0200
commitd45d020554bf1681c91b573767e170e0b5ea9ecb (patch)
tree3f47a9b5380d5f95b37d61a14db5362a433b77d4
parentf46596353ba8c26a1112030499943c2b13398af5 (diff)
downloadtaler-ios-d45d020554bf1681c91b573767e170e0b5ea9ecb.tar.gz
taler-ios-d45d020554bf1681c91b573767e170e0b5ea9ecb.tar.bz2
taler-ios-d45d020554bf1681c91b573767e170e0b5ea9ecb.zip
Button Layout
-rw-r--r--TalerWallet.xcodeproj/project.pbxproj6
-rw-r--r--TalerWallet1/Views/Balances/BalanceRowView.swift147
-rw-r--r--TalerWallet1/Views/Balances/TwoRowButtons.swift14
-rw-r--r--TalerWallet1/Views/Exchange/ExchangeSectionView.swift33
-rw-r--r--TalerWallet1/Views/HelperViews/View+needVStack.swift32
5 files changed, 153 insertions, 79 deletions
diff --git a/TalerWallet.xcodeproj/project.pbxproj b/TalerWallet.xcodeproj/project.pbxproj
index a30ede5..91e0346 100644
--- a/TalerWallet.xcodeproj/project.pbxproj
+++ b/TalerWallet.xcodeproj/project.pbxproj
@@ -169,6 +169,8 @@
4E9796902A3765ED006F73BC /* AgePicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E97968F2A3765ED006F73BC /* AgePicker.swift */; };
4E983C292ADBDD3500FA9CC5 /* SingleAxisGeometryReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E983C282ADBDD3500FA9CC5 /* SingleAxisGeometryReader.swift */; };
4E983C2A2ADBDD3500FA9CC5 /* SingleAxisGeometryReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E983C282ADBDD3500FA9CC5 /* SingleAxisGeometryReader.swift */; };
+ 4E983C2C2ADC416800FA9CC5 /* View+needVStack.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E983C2B2ADC416800FA9CC5 /* View+needVStack.swift */; };
+ 4E983C2D2ADC416800FA9CC5 /* View+needVStack.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E983C2B2ADC416800FA9CC5 /* View+needVStack.swift */; };
4EA1ABBE29A3833A008821EA /* PublicConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EA1ABBD29A3833A008821EA /* PublicConstants.swift */; };
4EA551252A2C923600FEC9A8 /* CurrencyInputView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EA551242A2C923600FEC9A8 /* CurrencyInputView.swift */; };
4EAD117629F672FA008EDD0B /* KeyboardResponder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EAD117529F672FA008EDD0B /* KeyboardResponder.swift */; };
@@ -336,6 +338,7 @@
4E9320462A164BC700A87B0E /* PaymentPurpose.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PaymentPurpose.swift; sourceTree = "<group>"; };
4E97968F2A3765ED006F73BC /* AgePicker.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AgePicker.swift; sourceTree = "<group>"; };
4E983C282ADBDD3500FA9CC5 /* SingleAxisGeometryReader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SingleAxisGeometryReader.swift; sourceTree = "<group>"; };
+ 4E983C2B2ADC416800FA9CC5 /* View+needVStack.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "View+needVStack.swift"; sourceTree = "<group>"; };
4EA1ABBD29A3833A008821EA /* PublicConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PublicConstants.swift; sourceTree = "<group>"; };
4EA551242A2C923600FEC9A8 /* CurrencyInputView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CurrencyInputView.swift; sourceTree = "<group>"; };
4EAD117529F672FA008EDD0B /* KeyboardResponder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeyboardResponder.swift; sourceTree = "<group>"; };
@@ -729,6 +732,7 @@
4E5A88F42A38A4FD00072618 /* QRCodeDetailView.swift */,
4E6EDD862A363D8D0031D520 /* ListStyle.swift */,
4E983C282ADBDD3500FA9CC5 /* SingleAxisGeometryReader.swift */,
+ 4E983C2B2ADC416800FA9CC5 /* View+needVStack.swift */,
4EB095482989CBFE0043A8A1 /* TextFieldAlert.swift */,
4EBA82AA2A3EB2CA00E5F39A /* TransactionButton.swift */,
4EB095492989CBFE0043A8A1 /* AmountView.swift */,
@@ -1031,6 +1035,7 @@
4E3EAE252A990778009F1BE8 /* WithdrawAcceptDone.swift in Sources */,
4E3EAE262A990778009F1BE8 /* Transaction.swift in Sources */,
4E605DB72AB05E48002FB9A7 /* View+flippedDirection.swift in Sources */,
+ 4E983C2C2ADC416800FA9CC5 /* View+needVStack.swift in Sources */,
4E3EAE272A990778009F1BE8 /* WalletColors.swift in Sources */,
4E3EAE282A990778009F1BE8 /* BalancesListView.swift in Sources */,
4E3EAE292A990778009F1BE8 /* WalletBackendError.swift in Sources */,
@@ -1135,6 +1140,7 @@
4E5A88F72A3B9E5B00072618 /* WithdrawAcceptDone.swift in Sources */,
4EB095222989CBCB0043A8A1 /* Transaction.swift in Sources */,
4E605DB82AB05E48002FB9A7 /* View+flippedDirection.swift in Sources */,
+ 4E983C2D2ADC416800FA9CC5 /* View+needVStack.swift in Sources */,
4E9320432A14F6EA00A87B0E /* WalletColors.swift in Sources */,
4EB0955D2989CBFE0043A8A1 /* BalancesListView.swift in Sources */,
4EB095212989CBCB0043A8A1 /* WalletBackendError.swift in Sources */,
diff --git a/TalerWallet1/Views/Balances/BalanceRowView.swift b/TalerWallet1/Views/Balances/BalanceRowView.swift
index be6de61..129ea3d 100644
--- a/TalerWallet1/Views/Balances/BalanceRowView.swift
+++ b/TalerWallet1/Views/Balances/BalanceRowView.swift
@@ -5,93 +5,134 @@
import SwiftUI
import taler_swift
-/// This view shows the currency row in a currency section
-/// [Send Coins] [Receive Coins] Balance
+let SPACING = CGFloat(10) // space between the two buttons
+
+struct BalanceLabel: View {
+ let balanceTitle: String
+ let horizontal: Bool
+ let amountStr: String
+ let iconOnly: Bool
+
+ var body: some View {
+ Group { // can either be horizontal (preferred) or vertical (if doesn't fit horizontally)
+ if !iconOnly {
+ Text(balanceTitle)
+ .accessibilityFont(.title2)
+ .foregroundColor(.secondary)
+ }
+ if horizontal {
+ Spacer(minLength: 0)
+ Text(amountStr)
+ .accessibilityFont(.title)
+ .monospacedDigit()
+ } else { HStack {
+ Spacer(minLength: 0)
+ Text(amountStr)
+ .accessibilityFont(.title)
+ .monospacedDigit()
+ } }
+ }
+ }
+}
struct BalanceButton: View {
- let amount: Amount
+ let amountStr: String
let rowAction: () -> Void
+
@AppStorage("iconOnly") var iconOnly: Bool = false
var body: some View {
+ let balanceTitle = String(localized: "Balance:", comment: "Main view")
Button(action: rowAction) {
- HStack(alignment: .lastTextBaseline) {
- Text("Balance:", comment: "Balance in main view")
- .accessibilityFont(.title2)
- .foregroundColor(iconOnly ? .clear : .secondary) // hide if iconOnly
- Spacer()
- Text(verbatim: "\(amount.valueStr)") // TODO: CurrencyFormatter?
- .accessibilityFont(.title)
- .monospacedDigit()
+ SingleAxisGeometryReader { width in
+ Group {
+ let balancesFont = TalerFont.uiFont(.title2)
+ let amountFont = TalerFont.uiFont(.title)
+ let titles = [(balanceTitle, balancesFont),
+ (amountStr, amountFont)]
+ let needVStack = !iconOnly && Self.needVStack(titles, width: width, spacing: SPACING, sameSize: false)
+ if needVStack {
+ VStack(alignment: .leading, spacing: 0) {
+ BalanceLabel(balanceTitle: balanceTitle, horizontal: false, amountStr: amountStr, iconOnly: iconOnly)
+ }
+ } else {
+ HStack(alignment: .lastTextBaseline, spacing: 0) {
+ BalanceLabel(balanceTitle: balanceTitle, horizontal: true, amountStr: amountStr, iconOnly: iconOnly)
+ }
+ }
+ }
}
- .accessibilityFont(.subheadline)
} .disabled(false)
- .accessibilityElement(children: /*@START_MENU_TOKEN@*/.ignore/*@END_MENU_TOKEN@*/)
- .accessibilityLabel("Balance \(amount.readableDescription)") // TODO: CurrencyFormatter!
.buttonStyle(TalerButtonStyle(type: iconOnly ? .plain : .balance, aligned: .trailing))
-// .background(Color.yellow)
+ .accessibilityElement(children: /*@START_MENU_TOKEN@*/.ignore/*@END_MENU_TOKEN@*/)
+ .accessibilityLabel("\(balanceTitle) \(amountStr)") // TODO: CurrencyFormatter!
}
}
+
+/// This view shows the currency row in a currency section
+/// [Send Coins] [Receive Coins] Balance
struct BalanceRowView: View {
let amount: Amount
let sendAction: () -> Void
let recvAction: () -> Void
let rowAction: () -> Void
@Environment(\.sizeCategory) var sizeCategory
+ @AppStorage("myListStyle") var myListStyle: MyListStyle = .automatic
+
let sendTitle1 = String(localized: "Send", comment: "Top of button <Send Money>")
let sendTitle2 = String(localized: "Money", comment: "Bottom of button <Send Money>")
let requestTitle1 = String(localized: "Request", comment: "Top of button <Request Payment>")
let requestTitle2 = String(localized: "Payment", comment: "Bottom of button <Request Payment>")
- func needVStack(_ amount: Amount) -> Bool {
- // Sizes: 320 (SE), 375 (X, Xs, 12, 13 mini), 390 (12,13,14), 414 (Plus, Max), 428 (Pro Max)
- guard 350 < UIScreen.screenWidth else {return true} // always for iPhone SE 1st Gen
- var count = amount.currencyStr.count
-// print(sizeCategory)
- switch sizeCategory {
- case ContentSizeCategory.extraSmall:
- count += 0
- case ContentSizeCategory.small:
- count += 1
- case ContentSizeCategory.medium:
- count += 2
- case ContentSizeCategory.large:
- count += 3
- case ContentSizeCategory.extraLarge:
- count += 4
- default:
- count += 5
- }
- return count > 9
- }
-
var body: some View {
- VStack (alignment: .trailing) {
- BalanceButton(amount: amount, rowAction: rowAction)
- let sendTitle = sendTitle1 + "\n" + sendTitle2
- let requestTitle = requestTitle1 + "\n" + requestTitle2
- let twoRowButtons = TwoRowButtons(sendTitle: sendTitle, recvTitle: requestTitle,
- lineLimit: 5, sendDisabled: amount.isZero,
- sendAction: sendAction, recvAction: recvAction)
- if needVStack(amount) {
- VStack { twoRowButtons }
- } else {
- HStack { twoRowButtons }
+ SingleAxisGeometryReader { width in
+ VStack (alignment: .trailing) {
+ BalanceButton(amountStr: amount.valueStr, // TODO: CurrencyFormatter?
+ rowAction: rowAction)
+ let uiFont = TalerFont.uiFont(.title3)
+ let titles = [(requestTitle1, uiFont), (requestTitle2, uiFont), (sendTitle1, uiFont), (sendTitle2, uiFont)]
+ let sendTitle = sendTitle1 + "\n" + sendTitle2
+ let requestTitle = requestTitle1 + "\n" + requestTitle2
+ let twoRowButtons = TwoRowButtons(sendTitle: sendTitle, recvTitle: requestTitle,
+ 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) {
+ VStack { twoRowButtons }
+ } else {
+ HStack(spacing: SPACING) { twoRowButtons }
+ }
}
+ .accessibilityElement(children: .combine)
}
- .accessibilityElement(children: .combine)
}
}
// MARK: -
#if DEBUG
struct BalanceRowView_Previews: PreviewProvider {
static var previews: some View {
+ let test = try! Amount(fromString: TESTCURRENCY + ":1.23")
+ let demo = try! Amount(fromString: DEMOCURRENCY + ":1234.56")
List {
- BalanceRowView(amount: try! Amount(fromString: TESTCURRENCY + ":1234.56"),
- sendAction: {}, recvAction: {}, rowAction: {})
- BalanceRowView(amount: try! Amount(fromString: DEMOCURRENCY + ":1234.56"),
- sendAction: {}, recvAction: {}, rowAction: {})
+ Section {
+ HStack(alignment: .lastTextBaseline) {
+ BalanceLabel(balanceTitle: "BalanceA:", horizontal: true, amountStr: test.valueStr, iconOnly: false)
+ .listRowSeparator(.hidden)
+ }
+ }
+ Section {
+ BalanceLabel(balanceTitle: "Balance:", horizontal: false, amountStr: demo.valueStr, iconOnly: false)
+ .listRowSeparator(.hidden)
+ }
+ Section {
+ BalanceButton(amountStr: demo.valueStr, rowAction: {})
+ .listRowSeparator(.hidden)
+ }
+ Section {
+ BalanceRowView(amount: demo, sendAction: {}, recvAction: {}, rowAction: {})
+ }
+ BalanceRowView(amount: test, sendAction: {}, recvAction: {}, rowAction: {})
}
}
}
diff --git a/TalerWallet1/Views/Balances/TwoRowButtons.swift b/TalerWallet1/Views/Balances/TwoRowButtons.swift
index 3d5014e..163b703 100644
--- a/TalerWallet1/Views/Balances/TwoRowButtons.swift
+++ b/TalerWallet1/Views/Balances/TwoRowButtons.swift
@@ -35,22 +35,16 @@ struct TwoRowButtons: View {
struct TwoRowButtons_Previews: PreviewProvider {
static var previews: some View {
List {
- VStack {
- let amount = try! Amount(fromString: LONGCURRENCY + ":1234.56")
- TwoRowButtons(sendTitle: "Send\n" + LONGCURRENCY,
+ TwoRowButtons(sendTitle: "Send\n" + TESTCURRENCY,
recvTitle: "Receive\n" + LONGCURRENCY,
- lineLimit: 0, sendDisabled: true,
+ lineLimit: 2, sendDisabled: true,
sendAction: {}, recvAction: {})
- BalanceButton(amount: amount, rowAction: {})
- }
- HStack {
- let amount = try! Amount(fromString: DEMOCURRENCY + ":1234.56")
+ .listRowSeparator(.hidden)
TwoRowButtons(sendTitle: "Send\n" + DEMOCURRENCY,
recvTitle: "Receive\n" + DEMOCURRENCY,
lineLimit: 2, sendDisabled: true,
sendAction: {}, recvAction: {})
- BalanceButton(amount: amount, rowAction: {})
- }
+ .listRowSeparator(.hidden)
}
}
}
diff --git a/TalerWallet1/Views/Exchange/ExchangeSectionView.swift b/TalerWallet1/Views/Exchange/ExchangeSectionView.swift
index 692e750..1a6c622 100644
--- a/TalerWallet1/Views/Exchange/ExchangeSectionView.swift
+++ b/TalerWallet1/Views/Exchange/ExchangeSectionView.swift
@@ -29,11 +29,6 @@ struct ExchangeRowView: View {
let depositTitle = String(localized: "Deposit", comment: "Top of button <Deposit (currency)>")
let withdrawTitle = String(localized: "Withdraw", comment: "Top of button <Withdraw (currency)>")
- func needVStack(_ currency: String) -> Bool {
- // Sizes: 320 (SE), 375 (X, Xs, 12, 13 mini), 390 (12,13,14), 414 (Plus, Max), 428 (Pro Max)
-
- return false
- }
var body: some View {
let baseURL = exchange.exchangeBaseUrl
@@ -54,16 +49,23 @@ struct ExchangeRowView: View {
) { EmptyView() }.frame(width: 0).opacity(0)
}.listRowSeparator(.hidden)
- let sendTitle = depositTitle + "\n" + currency // TODO: amount.currencyStr
- let recvTitle = withdrawTitle + "\n" + currency // TODO: amount.currencyStr
- let twoRowButtons = TwoRowButtons(sendTitle: sendTitle, recvTitle: recvTitle,
- lineLimit: 5, sendDisabled: true, // TODO: amount.isZero
- sendAction: { selectAndUpdate(1) },
- recvAction: { selectAndUpdate(2) })
- if needVStack(currency) {
- VStack { twoRowButtons }
- } else {
- HStack { twoRowButtons }
+ SingleAxisGeometryReader { width in
+ Group {
+ let uiFont = TalerFont.uiFont(.title3)
+ let titles = [(depositTitle, uiFont), (withdrawTitle, uiFont), (currency, uiFont)]
+ let sendTitle = depositTitle + "\n" + currency // TODO: amount.currencyStr
+ let recvTitle = withdrawTitle + "\n" + currency // TODO: amount.currencyStr
+ let twoRowButtons = TwoRowButtons(sendTitle: sendTitle, recvTitle: recvTitle,
+ lineLimit: 5, sendDisabled: true, // TODO: amount.isZero
+ sendAction: { selectAndUpdate(1) },
+ recvAction: { selectAndUpdate(2) })
+ let spacing = CGFloat(10) // space between the two buttons
+ if Self.needVStack(titles, width: width, spacing: spacing) {
+ VStack { twoRowButtons }
+ } else {
+ HStack(spacing: spacing) { twoRowButtons }
+ }
+ }
}
}
}
@@ -76,7 +78,6 @@ struct ExchangeSectionView: View {
// let amount: Amount
let currency: String // TODO: amount.currencyStr
let exchanges: [Exchange]
-
@Binding var centsToTransfer: UInt64
var body: some View {
diff --git a/TalerWallet1/Views/HelperViews/View+needVStack.swift b/TalerWallet1/Views/HelperViews/View+needVStack.swift
new file mode 100644
index 0000000..e71cf72
--- /dev/null
+++ b/TalerWallet1/Views/HelperViews/View+needVStack.swift
@@ -0,0 +1,32 @@
+/*
+ * This file is part of GNU Taler, ©2022-23 Taler Systems S.A.
+ * See LICENSE.md
+ */
+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 {
+ let padding: CGFloat = 20 // TODO: depend on myListStyle
+ var maxTitleWidth: CGFloat = 0
+ var totalWidth = padding
+
+ for (title, uiFont) in titles {
+ let titleWidth = title.widthOfString(usingUIFont: uiFont)
+ if titleWidth > maxTitleWidth {
+ maxTitleWidth = titleWidth
+ }
+ totalWidth += titleWidth
+ }
+
+ let neededWidth = padding + maxTitleWidth
+ let totalSpacing = spacing * CGFloat(numViews - 1)
+ let availableWidth = (width / CGFloat(numViews)) - totalSpacing
+ totalWidth += totalSpacing
+
+ return sameSize ? neededWidth > availableWidth
+ : totalWidth > width
+ }
+}