taler-ios

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

TwoRowButtons.swift (6777B)


      1 /*
      2  * This file is part of GNU Taler, ©2022-25 Taler Systems S.A.
      3  * See LICENSE.md
      4  */
      5 /**
      6  * @author Marc Stibane
      7  */
      8 import SwiftUI
      9 import taler_swift
     10 
     11 let LINELIMIT = 5
     12 
     13 struct TypeButton: View {
     14     let stack: CallStack
     15     let phase: Int
     16     let title: String
     17     let a11y: String
     18     var type: TransactionType
     19     let disabled: Bool
     20     let action: NSNotification.Name
     21 
     22     @AppStorage("minimalistic") var minimalistic: Bool = false
     23 
     24     @MainActor
     25     func dismissAndPost() {
     26         dismissTop(stack.push())
     27         NotificationCenter.default.post(name: action, object: nil)                // will trigger NavigationLink
     28     }
     29 
     30     var body: some View {
     31 #if DEBUG
     32         let debug = 1==0
     33         let red = debug ? Color.red : Color.clear
     34         let green = debug ? Color.green : Color.clear
     35         let blue = debug ? Color.blue : Color.clear
     36         let orange = debug ? Color.orange : Color.clear
     37 #endif
     38         let disabledColor = WalletColors().gray2
     39         let primaryAccent = WalletColors().primaryAccent
     40         let icon = ButtonIconBadge(type: type,
     41                                   phase: phase,
     42                               foreColor: disabled ? disabledColor : primaryAccent,
     43                                    done: false)
     44                         .talerFont(.title2)
     45         let hLayout = HStack {
     46             icon
     47             Spacer()
     48             Text(title)
     49                 .fixedSize(horizontal: true, vertical: false)
     50             Spacer()
     51         }
     52 #if DEBUG
     53             .border(red)
     54 #endif
     55 
     56         let vLayout = VStack {
     57             let fragments = title.components(separatedBy: "\n")
     58             let fragCount = fragments.count
     59             if fragCount > 1 {
     60                 Text(fragments[0])
     61                 HStack {
     62                     icon
     63                     Spacer()
     64                     Text(fragments[1])
     65                         .fixedSize(horizontal: true, vertical: false)
     66                     Spacer()
     67                 }
     68 #if DEBUG
     69                 .border(orange)
     70 #endif
     71                 if fragCount > 2 {
     72                     Text(fragments[2])
     73 //                        .fixedSize(horizontal: true, vertical: false)
     74 #if DEBUG
     75                         .border(green)
     76 #endif
     77                 }
     78             } else {
     79                 hLayout
     80             }
     81         }
     82 #if DEBUG
     83             .border(red)
     84 #endif
     85 
     86         Button(action: dismissAndPost) {
     87             if minimalistic {
     88                 icon
     89             } else {
     90                 if #available(iOS 16.4, *) {
     91                     ViewThatFits(in: .horizontal) {
     92                         hLayout
     93                         vLayout
     94                     }
     95                 } else { vLayout } // view for iOS 15
     96             }
     97         }
     98         .accessibilityLabel(Text(a11y))
     99         .lineLimit(LINELIMIT)
    100         .disabled(disabled)
    101         .buttonStyle(TalerButtonStyle(type: .bordered,
    102                                     dimmed: false,
    103                                   disabled: disabled,
    104                                    aligned: .center))
    105     }
    106 }
    107 // MARK: -
    108 struct TwoRowButtons: View {
    109     let stack: CallStack
    110     let phase: Int?
    111     let sendTitle: String
    112     var sendType: TransactionType
    113     let sendA11y: String
    114     let recvTitle: String
    115     var recvType: TransactionType
    116     let recvA11y: String
    117     let sendDisabled: Bool   // can't send/deposit if wallet has no coins at all
    118     let sendAction: NSNotification.Name
    119     let recvDisabled: Bool   // can't receive/withdraw if wallet has no payments services
    120     let recvAction: NSNotification.Name
    121 
    122     func sendButton(_ title: String, _ phase: Int) -> TypeButton {
    123         TypeButton(stack: stack.push(),
    124                    phase: phase,
    125                    title: title,
    126                     a11y: sendA11y,
    127                     type: sendType,
    128                 disabled: sendDisabled,
    129                   action: sendAction)
    130     }
    131 
    132     func recvButton(_ title: String, _ phase: Int) -> TypeButton {
    133         TypeButton(stack: stack.push(),
    134                    phase: phase,
    135                    title: title,
    136                     a11y: recvA11y,
    137                     type: recvType,
    138                 disabled: recvDisabled,
    139                   action: recvAction)
    140     }
    141 
    142     func phase(_ first: Bool) -> Int {
    143         if let phase {
    144             let myPhase = phase % 16
    145             if first {
    146                 return myPhase > 7 ? 0 : myPhase
    147             }
    148             return myPhase < 9 ? 0 : myPhase - 8
    149         }
    150         return 0
    151     }
    152 
    153     var body: some View {
    154 //        let _ = Self._printChanges()
    155         let hLayout = HStack(spacing: HSPACING) {
    156             // side by side, text in 1+ lines (\t -> \n)
    157             sendButton(sendTitle.tabbed(oneLine: false), phase(true))
    158             recvButton(recvTitle.tabbed(oneLine: false), phase(false))
    159         }
    160         let vLayout = VStack(alignment: .leading) {
    161             // one below the other, text in one line (\t -> " ")
    162             sendButton(sendTitle.tabbed(oneLine: true), phase(true))
    163             recvButton(recvTitle.tabbed(oneLine: true), phase(false))
    164         }
    165 
    166         if #available(iOS 16.4, *) {
    167             ViewThatFits(in: .horizontal) {
    168                 hLayout
    169 //                    .border(.green)
    170                 vLayout
    171 //                    .border(.red)
    172             }
    173         } else { vLayout } // iOS 15 has no ViewThatFits
    174     }
    175 }
    176 // MARK: -
    177 #if  DEBUG
    178 struct TwoRowButtons_Previews: PreviewProvider {
    179     static var previews: some View {
    180         List {
    181             TwoRowButtons(stack: CallStack("Preview"),
    182                          phase: nil,
    183                       sendTitle: "Send " + TESTCURRENCY,
    184                        sendType: .peerPushDebit,
    185                        sendA11y: "Send " + TESTCURRENCY,
    186                       recvTitle: "Request " + LONGCURRENCY,
    187                        recvType: .peerPullCredit,
    188                        recvA11y: "Request " + LONGCURRENCY,
    189                    sendDisabled: true,
    190                      sendAction: .SendAction,
    191                    recvDisabled: false,
    192                      recvAction: .RequestAction)
    193                 .listRowSeparator(.hidden)
    194             TwoRowButtons(stack: CallStack("Preview"),
    195                          phase: nil,
    196                       sendTitle: "Send " + DEMOCURRENCY,
    197                        sendType: .peerPushDebit,
    198                        sendA11y: "Send " + DEMOCURRENCY,
    199                       recvTitle: "Request " + DEMOCURRENCY,
    200                        recvType: .peerPullCredit,
    201                        recvA11y: "Request " + DEMOCURRENCY,
    202                    sendDisabled: true,
    203                      sendAction: .SendAction,
    204                    recvDisabled: false,
    205                      recvAction: .RequestAction)
    206                 .listRowSeparator(.hidden)
    207         }
    208     }
    209 }
    210 #endif