taler-ios

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

BalancesListView.swift (5202B)


      1 /*
      2  * This file is part of GNU Taler, ©2022-26 Taler Systems S.A.
      3  * See LICENSE.md
      4  */
      5 /**
      6  * @author Marc Stibane
      7  */
      8 import SwiftUI
      9 import taler_swift
     10 import SymLog
     11 import AVFoundation
     12 
     13 /// This view shows the list of balances / currencies, each in its own section
     14 struct BalancesListView: View {
     15     private let symLog = SymLogV(0)
     16     let stack: CallStack
     17     let title: String
     18     @Binding var selectedBalance: Balance?                      // set in TransactionsListView
     19     @Binding var reloadTransactions: Int
     20 
     21     @EnvironmentObject private var model: WalletModel
     22     @EnvironmentObject private var controller: Controller
     23     @AppStorage("myListStyle") var myListStyle: MyListStyle = .automatic
     24     @AppStorage("oimEuro") var oimEuro: Bool = false
     25 
     26     @State private var amountToTransfer = Amount.zero(currency: EMPTYSTRING)    // Update currency when used
     27     @State private var summary = EMPTYSTRING
     28 
     29     @State private var historyTapped: Int? = nil
     30     @Namespace var namespace
     31 
     32     private static func className() -> String {"\(self)"}
     33 
     34     func refresh() async {
     35         controller.hapticNotification(.success)
     36         symLog.log("refreshing balances")
     37         await controller.loadBalances(stack.push("refreshing balances"), model)
     38     }
     39 
     40     @ViewBuilder
     41     func balancesList() -> some View {
     42         let count = controller.balances.count
     43         let list = List {
     44             if !controller.haveProdBalance && !controller.defaultExchanges.isEmpty {
     45                 ProdSectionView(stack: stack.push(), isEmpty: false, disabled: false)
     46             }
     47             ForEachWithIndex(data: controller.balances) { index, balance in
     48                 BalancesSectionView(stack: stack.push("\(balance.scopeInfo.currency)"),
     49                                   balance: balance,                     // this is the currency to be used
     50                           selectedBalance: $selectedBalance,            // set in TransactionsListView
     51                              balanceIndex: index,
     52                              sectionCount: count,
     53                          amountToTransfer: $amountToTransfer,           // does still have the wrong currency
     54                                   summary: $summary,
     55                             historyTapped: $historyTapped,
     56                        reloadTransactions: $reloadTransactions)
     57             }
     58         }
     59             .listStyle(myListStyle.style).anyView
     60             .background(FullBackground())
     61             .onAppear() {
     62                 DebugViewC.shared.setViewID(VIEW_BALANCES, stack: stack.push("onAppear"))
     63                 if !controller.oimModeActive {
     64                     print("🚩BalancesListView.onAppear() reset selectedBalance")
     65 //                  if count > 1 {
     66                         selectedBalance = nil                           // reset
     67 //                  }
     68                 }
     69             }
     70             .refreshable {
     71                 await refresh()
     72             }
     73             .navigationTitle(title)
     74         if #available(iOS 26.0, *) {
     75             list
     76                 .toolbar {
     77                     ToolbarItem(placement: .primaryAction) {
     78                         Button {
     79                             NotificationCenter.default.post(name: .SettingsAction, object: nil)   // will trigger NavigationLink
     80                         } label: {
     81                             Label(TalerTab.settings.title, systemImage: TalerTab.settings.sysImg)
     82                                 .labelStyle(.iconOnly)
     83                         }
     84                         //                                  .padding()
     85                         .buttonStyle(.glass)
     86 //                        .accessibilitySortPriority(0)
     87                     }
     88                 }
     89         } else {
     90             list
     91         }
     92     }
     93 
     94     var body: some View {
     95 #if PRINT_CHANGES
     96         let _ = Self._printChanges()
     97         let _ = symLog.vlog()       // just to get the # to compare it with .onAppear & onDisappear
     98 #endif
     99         /// In standard mode, selectedBalance just sets a "preference" which balance to pre-select for Actions.
    100         ///   However, the user can select another balance (with the picker) in each action
    101         /// In OIM mode, the user selects a balance 'here' (in OIMView) when tapping on a savings box (representing the balance)
    102 
    103         balancesList()
    104             .onChange(of: controller.oimModeActive) { oimModeActive in
    105                 if !oimModeActive {
    106                     print("🚩BalancesListView.onChange(of: oimModeActive) reset selectedBalance")
    107 //                    if count > 1 {
    108                         selectedBalance = nil                               // reset
    109 //                    }
    110                  }
    111             }
    112             .overlay { if #available(iOS 16.4, *) {
    113                 if controller.oimModeActive {
    114 #if OIM
    115                     OIMbalances(stack: stack.push(),
    116                       selectedBalance: $selectedBalance,                    // set to user choice
    117                         historyTapped: $historyTapped,
    118                               oimEuro: oimEuro)
    119                         .environmentObject(NamespaceWrapper(namespace))         // keep OIMviews apart
    120 #endif // OIM
    121                 }
    122             } }
    123     }
    124 }