taler-ios

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

commit 9ec3d69b203c31c48d49e9d9df7786a8b5f4046c
parent f6393725982d29898a539b8c12a6cab95a1957b5
Author: Marc Stibane <marc@taler.net>
Date:   Sat, 20 Jul 2024 19:11:23 +0200

BalanceRowView -> SendRequestV

Diffstat:
MTalerWallet.xcodeproj/project.pbxproj | 12++++++------
DTalerWallet1/Views/Balances/BalanceRowView.swift | 151------------------------------------------------------------------------------
ATalerWallet1/Views/Balances/SendRequestV.swift | 136+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 142 insertions(+), 157 deletions(-)

diff --git a/TalerWallet.xcodeproj/project.pbxproj b/TalerWallet.xcodeproj/project.pbxproj @@ -111,7 +111,7 @@ 4E3EAE712A990778009F1BE8 /* URL+id+iban.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E363CBB2A237E0900D7E98C /* URL+id+iban.swift */; }; 4E3EAE722A990778009F1BE8 /* RequestPayment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E9320442A1645B600A87B0E /* RequestPayment.swift */; }; 4E3EAE732A990778009F1BE8 /* SettingsItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EB095262989CBFE0043A8A1 /* SettingsItem.swift */; }; - 4E3EAE742A990778009F1BE8 /* BalanceRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EB095362989CBFE0043A8A1 /* BalanceRowView.swift */; }; + 4E3EAE742A990778009F1BE8 /* SendRequestV.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EB095362989CBFE0043A8A1 /* SendRequestV.swift */; }; 4E3EAE752A990778009F1BE8 /* DebugViewC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E753A052A0952F7002D9328 /* DebugViewC.swift */; }; 4E3EAE772A990778009F1BE8 /* AnyCodable in Frameworks */ = {isa = PBXBuildFile; productRef = 4E3EAE162A990778009F1BE8 /* AnyCodable */; }; 4E3EAE782A990778009F1BE8 /* SymLog in Frameworks */ = {isa = PBXBuildFile; productRef = 4E3EAE182A990778009F1BE8 /* SymLog */; }; @@ -223,7 +223,7 @@ 4EB095582989CBFE0043A8A1 /* TransactionSummaryV.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EB095312989CBFE0043A8A1 /* TransactionSummaryV.swift */; }; 4EB095592989CBFE0043A8A1 /* Model+Transactions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EB095322989CBFE0043A8A1 /* Model+Transactions.swift */; }; 4EB0955A2989CBFE0043A8A1 /* URLSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EB095332989CBFE0043A8A1 /* URLSheet.swift */; }; - 4EB0955C2989CBFE0043A8A1 /* BalanceRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EB095362989CBFE0043A8A1 /* BalanceRowView.swift */; }; + 4EB0955C2989CBFE0043A8A1 /* SendRequestV.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EB095362989CBFE0043A8A1 /* SendRequestV.swift */; }; 4EB0955D2989CBFE0043A8A1 /* BalancesListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EB095372989CBFE0043A8A1 /* BalancesListView.swift */; }; 4EB0955E2989CBFE0043A8A1 /* PendingRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EB095382989CBFE0043A8A1 /* PendingRowView.swift */; }; 4EB0955F2989CBFE0043A8A1 /* WalletEmptyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EB095392989CBFE0043A8A1 /* WalletEmptyView.swift */; }; @@ -440,7 +440,7 @@ 4EB095312989CBFE0043A8A1 /* TransactionSummaryV.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransactionSummaryV.swift; sourceTree = "<group>"; }; 4EB095322989CBFE0043A8A1 /* Model+Transactions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Model+Transactions.swift"; sourceTree = "<group>"; }; 4EB095332989CBFE0043A8A1 /* URLSheet.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = URLSheet.swift; sourceTree = "<group>"; }; - 4EB095362989CBFE0043A8A1 /* BalanceRowView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BalanceRowView.swift; sourceTree = "<group>"; }; + 4EB095362989CBFE0043A8A1 /* SendRequestV.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SendRequestV.swift; sourceTree = "<group>"; }; 4EB095372989CBFE0043A8A1 /* BalancesListView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BalancesListView.swift; sourceTree = "<group>"; }; 4EB095382989CBFE0043A8A1 /* PendingRowView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PendingRowView.swift; sourceTree = "<group>"; }; 4EB095392989CBFE0043A8A1 /* WalletEmptyView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WalletEmptyView.swift; sourceTree = "<group>"; }; @@ -800,7 +800,7 @@ 4EB0953A2989CBFE0043A8A1 /* BalancesSectionView.swift */, 4E77976E2C4BEA4E005D6ECB /* BalanceCellV.swift */, 4E448AB62C4A4109007D5C92 /* BalancesPendingRowV.swift */, - 4EB095362989CBFE0043A8A1 /* BalanceRowView.swift */, + 4EB095362989CBFE0043A8A1 /* SendRequestV.swift */, 4EB065432A4CD1A80039B91D /* TwoRowButtons.swift */, 4EB095382989CBFE0043A8A1 /* PendingRowView.swift */, ); @@ -1284,7 +1284,7 @@ 4EDBDCD92AB787CB00925C02 /* CallStack.swift in Sources */, 4E3EAE722A990778009F1BE8 /* RequestPayment.swift in Sources */, 4E3EAE732A990778009F1BE8 /* SettingsItem.swift in Sources */, - 4E3EAE742A990778009F1BE8 /* BalanceRowView.swift in Sources */, + 4E3EAE742A990778009F1BE8 /* SendRequestV.swift in Sources */, 4E3EAEA82AA70157009F1BE8 /* Binding+onChange.swift in Sources */, 4E3EAE752A990778009F1BE8 /* DebugViewC.swift in Sources */, ); @@ -1412,7 +1412,7 @@ 4EDBDCDA2AB787CB00925C02 /* CallStack.swift in Sources */, 4E9320452A1645B600A87B0E /* RequestPayment.swift in Sources */, 4EB095502989CBFE0043A8A1 /* SettingsItem.swift in Sources */, - 4EB0955C2989CBFE0043A8A1 /* BalanceRowView.swift in Sources */, + 4EB0955C2989CBFE0043A8A1 /* SendRequestV.swift in Sources */, 4E3EAEA92AA70157009F1BE8 /* Binding+onChange.swift in Sources */, 4E753A062A0952F8002D9328 /* DebugViewC.swift in Sources */, ); diff --git a/TalerWallet1/Views/Balances/BalanceRowView.swift b/TalerWallet1/Views/Balances/BalanceRowView.swift @@ -1,151 +0,0 @@ -/* - * This file is part of GNU Taler, ©2022-24 Taler Systems S.A. - * See LICENSE.md - */ -/** - * @author Marc Stibane - */ -import SwiftUI -import taler_swift - -struct BalanceCell: View { - let stack: CallStack? - let amount: Amount - let sizeCategory: ContentSizeCategory - let rowAction: () -> Void - let balanceDest: LazyView<TransactionsListView>? - - @Environment(\.colorScheme) private var colorScheme - @Environment(\.colorSchemeContrast) private var colorSchemeContrast - @AppStorage("minimalistic") var minimalistic: Bool = false - - /// Renders the Balance button. "Balance" leading, amountStr trailing. If it doesn't fit in one row then - /// amount (trailing) goes underneath "Balance" (leading). - var body: some View { - let amountV = AmountV(stack: stack?.push("AmountV"), amount: amount, isNegative: false, large: true) - .foregroundColor(.primary) - let hLayout = amountV - .frame(maxWidth: .infinity, alignment: .trailing) - let balanceCell = Group { - if minimalistic { - hLayout - } else { - let balanceText = Text("Balance:", comment: "Main view") - .talerFont(.title2) - .foregroundColor(WalletColors().secondary(colorScheme, colorSchemeContrast)) - let vLayout = VStack(alignment: .leading, spacing: 0) { - balanceText - hLayout - } - - if #available(iOS 16.0, *) { - ViewThatFits(in: .horizontal) { - HStack(spacing: HSPACING) { - balanceText - hLayout - } - vLayout - } - } else { vLayout } // view for iOS 15 - } - } - NavigationLink { balanceDest } label: { - balanceCell - .accessibilityElement(children: .combine) - .accessibilityHint(String(localized: "Will go to main transactions list.")) -// .accessibilityLabel(balanceTitleStr + " " + amountStr) // TODO: CurrencyFormatter! - } - } -} - - -/// This view shows the currency row in a currency section, and two action buttons below -/// Balance: amount -/// [Send Money] [Request Payment] -struct BalanceRowView: View { - let stack: CallStack - let currencyName: String - let amount: Amount - let sendAction: () -> Void - let recvAction: () -> Void - let rowAction: () -> Void - let balanceDest: LazyView<TransactionsListView>? - - @Environment(\.sizeCategory) var sizeCategory - @EnvironmentObject private var controller: Controller - @AppStorage("minimalistic") var minimalistic: Bool = false - @AppStorage("myListStyle") var myListStyle: MyListStyle = .automatic - - var body: some View { - let sendTitle0 = String(localized: "SendButton_Short", defaultValue: "Send", - comment: "Abbreviation of button `Send (currency)´") - let sendTitle1 = String(localized: "SendButton_Full", defaultValue: "Send\t\(currencyName)", - comment: "`Send (currency)´ in Balances - must have ONE \\t and ONE %@") - - let requestTitle0 = String(localized: "RequestButton_Short", defaultValue: "Request", - comment: "Abbreviation of button `Request (currency)´") - let requestTitle1 = String(localized: "RequestButton_Full", defaultValue: "Request\t\(currencyName)", - comment: "`Request (currency)´ in Balances - must have ONE \\t and ONE %@") - VStack (alignment: .trailing, spacing: 6) { - BalanceCell(stack: stack.push("BalanceCell"), - amount: amount, - sizeCategory: sizeCategory, - rowAction: rowAction, - balanceDest: balanceDest) -// .border(.red) - - let sendTitle = minimalistic ? sendTitle0 : sendTitle1 - let requTitle = minimalistic ? requestTitle0 : requestTitle1 - let twoRowButtons = TwoRowButtons(stack: stack.push(), - sendTitle: sendTitle, - sendType: .peerPushDebit, - sendA11y: sendTitle.tabbed(oneLine: true), - recvTitle: requTitle, - recvType: .peerPullCredit, - recvA11y: requTitle.tabbed(oneLine: true), - fitsSideBySide: false, - lineLimit: 5, - sendDisabled: amount.isZero, - sendAction: sendAction, - recvAction: recvAction) - if #available(iOS 16.0, *) { - ViewThatFits(in: .horizontal) { - HStack(spacing: HSPACING) { - twoRowButtons.makeCopy(fitsSideBySide: true) - } -// .border(.red) - VStack { twoRowButtons } -// .border(.red) - } - } else { // view for iOS 15 - VStack { twoRowButtons } - } - } - } -} -// MARK: - -#if DEBUG -struct BalanceRowView_Previews: PreviewProvider { - @MainActor - struct StateContainer: View { - var body: some View { - let test = Amount(currency: TESTCURRENCY, cent: 123) - let demo = Amount(currency: DEMOCURRENCY, cent: 123456) - - List { - Section { - BalanceRowView(stack: CallStack("Preview"), currencyName: DEMOCURRENCY, amount: demo, - sendAction: {}, recvAction: {}, rowAction: {}, balanceDest: nil) - } - BalanceRowView(stack: CallStack("Preview"), currencyName: TESTCURRENCY, amount: test, - sendAction: {}, recvAction: {}, rowAction: {}, balanceDest: nil) - } - } - } - - static var previews: some View { - StateContainer() -// .environment(\.sizeCategory, .extraExtraLarge) Canvas Device Settings - } -} -#endif diff --git a/TalerWallet1/Views/Balances/SendRequestV.swift b/TalerWallet1/Views/Balances/SendRequestV.swift @@ -0,0 +1,136 @@ +/* + * This file is part of GNU Taler, ©2022-24 Taler Systems S.A. + * See LICENSE.md + */ +/** + * @author Marc Stibane + */ +import SwiftUI +import taler_swift +import SymLog + +struct SendRequestV: View { + private let symLog = SymLogV(0) + let stack: CallStack + let currencyInfo: CurrencyInfo + let amountAvailable: Amount + // let currency: String // this is the currency to be used + @Binding var amountToTransfer: Amount // does still have the wrong currency + @Binding var summary: String + let cameraAction: () -> Void + + @EnvironmentObject private var model: WalletModel + @AppStorage("minimalistic") var minimalistic: Bool = false + @State private var buttonSelected: Int? = nil + + func selectAndUpdate(_ button: Int) { + let scope = currencyInfo.scope + let currency = scope.currency + amountToTransfer.setCurrency(currency) + buttonSelected = button // will trigger NavigationLink + // after user tapped a button, while navigation animation runs, contact Exchange to update Fees + if let url = scope.url { + Task { // runs on MainActor + do { + // TODO: try await model.updateExchange(scopeInfo: scope) + try await model.updateExchange(exchangeBaseUrl: url) + } catch { // TODO: error handling - couldn't updateExchange + symLog.log("error: \(error)") + } + } + } + } + + private static func className() -> String {"\(self)"} + + var body: some View { + let scope = currencyInfo.scope + let currencyName = currencyInfo.specs.name + let sendTitle0 = String(localized: "SendButton_Short", defaultValue: "Send", + comment: "Abbreviation of button `Send (currency)´") + let sendTitle1 = String(localized: "SendButton_Full", defaultValue: "Send\t\(currencyName)", + comment: "`Send (currency)´ in Balances - must have ONE \\t and ONE %@") + let sendTitle = minimalistic ? sendTitle0 : sendTitle1 + + let requTitle0 = String(localized: "RequestButton_Short", defaultValue: "Request", + comment: "Abbreviation of button `Request (currency)´") + let requTitle1 = String(localized: "RequestButton_Full", defaultValue: "Request\t\(currencyName)", + comment: "`Request (currency)´ in Balances - must have ONE \\t and ONE %@") + let requTitle = minimalistic ? requTitle0 : requTitle1 + let sendDest = LazyView { + SendAmount(stack: stack.push("\(Self.className())()"), + currencyInfo: currencyInfo, + amountAvailable: amountAvailable, + amountToTransfer: $amountToTransfer, // with correct currency + summary: $summary, + scopeInfo: scope, + cameraAction: cameraAction) + } + let requestDest = LazyView { + RequestPayment(stack: stack.push("\(Self.className())()"), + amountToTransfer: $amountToTransfer, // with correct currency + summary: $summary, + scopeInfo: scope, + cameraAction: cameraAction) + } + let disableSend = amountAvailable.isZero //?? false + let twoRowButtons = TwoRowButtons(stack: stack.push(), + sendTitle: sendTitle, + sendType: .peerPushDebit, + sendA11y: sendTitle1.tabbed(oneLine: true), + recvTitle: requTitle, + recvType: .peerPullCredit, + recvA11y: requTitle1.tabbed(oneLine: true), + fitsSideBySide: false, + lineLimit: 5, + sendDisabled: disableSend, + sendAction: { selectAndUpdate(1) }, + recvAction: { selectAndUpdate(2) }) + Group { + if #available(iOS 16.0, *) { + ViewThatFits(in: .horizontal) { + HStack(spacing: HSPACING) { + twoRowButtons.makeCopy(fitsSideBySide: true) + } +// .border(.red) + VStack { twoRowButtons } +// .border(.red) + } + } else { // view for iOS 15 + VStack { twoRowButtons } + } + } + .background( Group { + NavigationLink(destination: sendDest, tag: 1, selection: $buttonSelected) + { EmptyView() }.frame(width: 0).opacity(0).hidden() + NavigationLink(destination: requestDest, tag: 2, selection: $buttonSelected) + { EmptyView() }.frame(width: 0).opacity(0).hidden() + }) + } +} +// MARK: - +#if false +struct SendRequestV_Previews: PreviewProvider { + @MainActor + struct StateContainer: View { + var body: some View { + let test = Amount(currency: TESTCURRENCY, cent: 123) + let demo = Amount(currency: DEMOCURRENCY, cent: 123456) + + List { + Section { + SendRequestV(stack: CallStack("Preview"), currencyName: DEMOCURRENCY, amount: demo, + sendAction: {}, recvAction: {}, rowAction: {}, balanceDest: nil) + } + SendRequestV(stack: CallStack("Preview"), currencyName: TESTCURRENCY, amount: test, + sendAction: {}, recvAction: {}, rowAction: {}, balanceDest: nil) + } + } + } + + static var previews: some View { + StateContainer() +// .environment(\.sizeCategory, .extraExtraLarge) Canvas Device Settings + } +} +#endif