taler-ios

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

commit 131b14e6a66deb66662e5b8583a176b9d0475112
parent 3384b0f0db6e5b69f9ba4cfe8762d8daa1430e64
Author: Marc Stibane <marc@taler.net>
Date:   Mon, 28 Apr 2025 06:54:19 +0200

selectedIndex (savings box selection)

Diffstat:
MTalerWallet1/Views/Actions/Peer2peer/RequestPayment.swift | 21++++++++++++++++++++-
MTalerWallet1/Views/Actions/Peer2peer/SendAmountV.swift | 22+++++++++++++++++++++-
MTalerWallet1/Views/Balances/BalancesListView.swift | 2++
MTalerWallet1/Views/Main/MainView.swift | 6++++++
MTalerWallet1/Views/OIM/OIMView.swift | 65+++++++++++++++++++++++++++++++++++++++++++++++++++++++----------
5 files changed, 104 insertions(+), 12 deletions(-)

diff --git a/TalerWallet1/Views/Actions/Peer2peer/RequestPayment.swift b/TalerWallet1/Views/Actions/Peer2peer/RequestPayment.swift @@ -20,13 +20,32 @@ struct RequestPayment: View { @EnvironmentObject private var controller: Controller #if OIM - @StateObject private var cash = OIMcash() + @StateObject private var cash: OIMcash #endif @State private var balanceIndex = 0 @State private var balance: Balance? = nil // nil only when balances == [] @State private var currencyInfo: CurrencyInfo = CurrencyInfo.zero(UNKNOWN) @State private var amountToTransfer = Amount.zero(currency: EMPTYSTRING) // Update currency when used + init(stack: CallStack, + selectedBalance: Balance?, + selectedIndex: Int?, + amountLastUsed: Binding<Amount>, + summary: Binding<String> + ) { + // SwiftUI ensures that the initialization uses the + // closure only once during the lifetime of the view, so + // later changes to the currency have no effect. + self.stack = stack + self.selectedBalance = selectedBalance + self._amountLastUsed = amountLastUsed + self._summary = summary +#if OIM + let currency = selectedIndex == 1 ? OIMleones : OIMeuros + self._cash = StateObject(wrappedValue: { OIMcash(currency) }()) +#endif + } + @MainActor private func viewDidLoad() async { if let selectedBalance { diff --git a/TalerWallet1/Views/Actions/Peer2peer/SendAmountV.swift b/TalerWallet1/Views/Actions/Peer2peer/SendAmountV.swift @@ -21,7 +21,7 @@ struct SendAmountV: View { @EnvironmentObject private var model: WalletModel #if OIM - @StateObject private var cash = OIMcash() + @StateObject private var cash: OIMcash #endif @State private var balanceIndex = 0 @State private var balance: Balance? = nil // nil only when balances == [] @@ -31,6 +31,25 @@ struct SendAmountV: View { @State private var buttonSelected = false @Namespace var namespace + init(stack: CallStack, + selectedBalance: Balance?, + selectedIndex: Int?, + amountLastUsed: Binding<Amount>, + summary: Binding<String> + ) { + // SwiftUI ensures that the initialization uses the + // closure only once during the lifetime of the view, so + // later changes to the currency have no effect. + self.stack = stack + self.selectedBalance = selectedBalance + self._amountLastUsed = amountLastUsed + self._summary = summary +#if OIM + let currency = selectedIndex == 1 ? OIMleones : OIMeuros + self._cash = StateObject(wrappedValue: { OIMcash(currency) }()) +#endif + } + @MainActor private func viewDidLoad() async { let balances = controller.balances @@ -159,6 +178,7 @@ fileprivate struct Preview_Content: View { flags: []) SendAmountV(stack: CallStack("Preview"), selectedBalance: noBalance, + selectedIndex: nil, amountLastUsed: $amountToPreview, summary: $summary) } diff --git a/TalerWallet1/Views/Balances/BalancesListView.swift b/TalerWallet1/Views/Balances/BalancesListView.swift @@ -15,6 +15,7 @@ struct BalancesListView: View { private let symLog = SymLogV(0) let stack: CallStack @Binding var selectedBalance: Balance? // pass down to TransactionsListView + @Binding var selectedIndex: Int? @Binding var reloadTransactions: Int @Binding var qrButtonTapped: Bool @@ -75,6 +76,7 @@ struct BalancesListView: View { if controller.oimModeActive { OIMView(stack: stack.push(), selectedBalance: $selectedBalance, // set to user choice + selectedIndex: $selectedIndex, qrButtonTapped: $qrButtonTapped) .environmentObject(NamespaceWrapper(namespace)) // keep OIMviews apart } diff --git a/TalerWallet1/Views/Main/MainView.swift b/TalerWallet1/Views/Main/MainView.swift @@ -32,6 +32,7 @@ struct MainView: View { @StateObject var tabBarModel = TabBarModel() @State private var selectedBalance: Balance? = nil // gets set in TransactionsListView + @State private var selectedIndex: Int? = nil // user selects savings box in OIMview @State private var urlToOpen: URL? = nil @State private var showUrlSheet = false @State private var showActionSheet = false @@ -62,6 +63,7 @@ struct MainView: View { let mainContent = ZStack { MainContent(logger: logger, stack: stack.push("Content"), selectedBalance: $selectedBalance, + selectedIndex: $selectedIndex, // user selects savings box in OIMview talerFontIndex: $talerFontIndex, showActionSheet: $showActionSheet, showScanner: $showScanner, @@ -244,6 +246,7 @@ extension MainView { let logger: Logger let stack: CallStack @Binding var selectedBalance: Balance? + @Binding var selectedIndex: Int? // user selects savings box in OIMview @Binding var talerFontIndex: Int @Binding var showActionSheet: Bool @Binding var showScanner: Bool @@ -327,10 +330,12 @@ extension MainView { /// Destinations for the 4 actions let sendDest = SendAmountV(stack: stack.push(Self.name), selectedBalance: selectedBalance, // if nil shows currency picker + selectedIndex: selectedIndex, // selected savings box from OIMview amountLastUsed: $amountLastUsed, // currency needs to be updated! summary: $summary) let requestDest = RequestPayment(stack: stack.push(Self.name), selectedBalance: selectedBalance, + selectedIndex: selectedIndex, // selected savings box from OIMview amountLastUsed: $amountLastUsed, // currency needs to be updated! summary: $summary) let depositDest = DepositSelectV(stack: stack.push(Self.name), @@ -369,6 +374,7 @@ extension MainView { let balancesStack = NavigationView { BalancesListView(stack: stack.push(balancesTitle), selectedBalance: $selectedBalance, // <= gets set in TransactionsListView + selectedIndex: $selectedIndex, // user selects savings box in OIMview // shouldReloadPending: $shouldReloadPending, reloadTransactions: $shouldReloadTransactions, qrButtonTapped: $qrButtonTapped) diff --git a/TalerWallet1/Views/OIM/OIMView.swift b/TalerWallet1/Views/OIM/OIMView.swift @@ -66,8 +66,10 @@ struct OIMView: View { let stack: CallStack // let decimal: Int // 0 for ¥,HUF; 2 for $,€,£; 3 for ﷼,₯ (arabic) @Binding var selectedBalance: Balance? // return user's choice + @Binding var selectedIndex: Int? @Binding var qrButtonTapped: Bool + @EnvironmentObject private var controller: Controller @EnvironmentObject private var wrapper: NamespaceWrapper @StateObject private var cash = OIMcash() @@ -75,6 +77,7 @@ struct OIMView: View { @State private var tappedVal: UInt64 = 0 @State private var sending = false @State private var available: Amount? = nil + @State private var isOpen: Int? = nil func sendAction() { let delay = cash.moveDown() @@ -127,16 +130,41 @@ struct OIMView: View { actions VStack { Spacer() - OIMcurrencyScroller(stack: stack.push(), - cash: cash, - availableVal: $availableVal, - tappedVal: $tappedVal, - canEdit: false) - .zIndex(1) // make notes fly from topZ - .clipped(antialiased: true) - .padding(.horizontal, 5) - .ignoresSafeArea(edges: .horizontal) - .opacity(sending ? 1.0 : 0.01) + HStack(spacing: 30) { +// ForEach(controller.balances, id: \.self) { balance in +// OIMbalanceButton(isOpen: selectedBalance == balance) { + + let balance = controller.balances[0] + ForEach(0...1, id: \.self) { index in + let itsMe = isOpen == index + let isClosed = isOpen == nil + let size = isClosed ? 120.0 : 66.0 + OIMbalanceButton(isOpen: itsMe, tint: index > 0) { + withAnimation(.basic1) { + if itsMe { + isOpen = nil + selectedBalance = nil + selectedIndex = nil + available = nil + } else { + isOpen = index + selectedIndex = index + cash.currency = index == 0 ? OIMeuros : OIMleones + selectedBalance = balance + available = balance.available + } + } + } + .frame(width: size, height: size) + .zIndex(itsMe ? 3 : 0) + .opacity((isClosed || itsMe) ? 1.0 : 0.01) + .matchedGeometryEffect(id: itsMe ? (sending ? "OIMback" : "OIMnumber") + : String(index), + in: wrapper.namespace,isSource: false) + .frame(width: size, height: size) + } + } + Spacer() } VStack { Spacer() @@ -152,6 +180,23 @@ struct OIMView: View { #if DEBUG // .border(.red) #endif + VStack { + Spacer() + OIMcurrencyScroller(stack: stack.push(), + cash: cash, + availableVal: $availableVal, + tappedVal: $tappedVal, + canEdit: false) + .clipped(antialiased: true) + .padding(.horizontal, 5) + .ignoresSafeArea(edges: .horizontal) + .scrollDisabled(true) +#if DEBUG + .opacity(sending ? 1.0 : 0.3) +#else + .opacity(sending ? 1.0 : 0.01) +#endif + } } } .task {