taler-ios

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

SettingsItem.swift (7334B)


      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 
     10 struct SettingsItem<Content: View>: View {
     11     var name: String
     12     var id1: String?
     13     var imageName: String?
     14     var description: String?
     15     var content: () -> Content
     16     
     17     init(name: String, id1: String, imageName: String, description: String? = nil, @ViewBuilder content: @escaping () -> Content) {
     18         self.name = name
     19         self.id1 = id1
     20         self.imageName = imageName
     21         self.description = description
     22         self.content = content
     23     }
     24     
     25     init(name: String, id1: String, description: String? = nil, @ViewBuilder content: @escaping () -> Content) {
     26         self.name = name
     27         self.id1 = id1
     28         self.imageName = nil
     29         self.description = description
     30         self.content = content
     31     }
     32 
     33     var body: some View {
     34         HStack {
     35             VStack {
     36                 let isWeb = id1?.hasPrefix("web") ?? false
     37                 let foreColor = isWeb ? Color.accentColor
     38                                       : .primary
     39                 HStack(spacing: 8.0) {
     40                     if let imageName {
     41                         Image(systemName: imageName)
     42                     }
     43                     Text(name)
     44                         .id(id1)
     45                 }
     46                     .frame(maxWidth: .infinity, alignment: .leading)
     47                     .foregroundColor(foreColor)
     48                     .talerFont(.title2)
     49                     .padding([.bottom], 0.01)
     50                 if let desc = description {
     51                     Text(desc)
     52                         .id(id1 == nil ? nil : id1! + "_T")
     53                         .frame(maxWidth: .infinity, alignment: .leading)
     54                         .talerFont(.caption)
     55                 }
     56             }.id(id1 == nil ? nil : id1! + "_V")
     57             content()
     58                 .talerFont(.body)
     59         }.id(id1 == nil ? nil : id1! + "_H")
     60             .accessibilityElement(children: .combine)
     61             .padding([.bottom], 4)
     62     }
     63 }
     64 // MARK: -
     65 struct SettingsToggle: View {
     66     var name: String
     67     @Binding var value: Bool
     68     var id1: String? = nil
     69     var description: String?
     70     var action: () -> Void = {}
     71 
     72     var body: some View {
     73         let accLabel: String = if let description {
     74             name + ", " + description
     75         } else {
     76             name
     77         }
     78         VStack {
     79             Toggle(name, isOn: $value.animation())
     80                 .id(id1)
     81 //                .accessibilityLabel(name)
     82                 .accessibility(sortPriority: 1)
     83                 .talerFont(.title2)
     84                 .onChange(of: value) { value in
     85                     action()
     86                 }
     87 
     88             if let desc = description {
     89                 Text(desc)
     90                     .id(id1 == nil ? nil : id1! + "_T")
     91                     .frame(maxWidth: .infinity, alignment: .leading)
     92                     .accessibility(sortPriority: 0)
     93                     .talerFont(.caption)
     94             }
     95         }
     96         .accessibilityElement(children: .combine)
     97         .accessibilityLabel(accLabel)
     98         .padding([.bottom], 4)
     99         .id(id1 == nil ? nil : id1! + "_V")
    100     }
    101 }
    102 // MARK: -
    103 struct SettingsFont: View {
    104     let title: String
    105     let value: Int
    106     let action: (Int) -> Void
    107 
    108     @State private var selectedFont = 0
    109     let fonts = [String(localized: "Standard iOS Font"), "Atkinson-Hyperlegible", "Nunito"]
    110 
    111     var body: some View {
    112         Picker(title, selection: $selectedFont, content: {
    113             ForEach(0..<fonts.count, id: \.self, content: { index in
    114                 Text(fonts[index]).tag(index)
    115             })
    116         })
    117             .talerFont(.title2)
    118             .pickerStyle(.menu)
    119             .onAppear() {
    120                 withAnimation { selectedFont = value }
    121             }
    122             .onChange(of: selectedFont) { selectedF in
    123                 action(selectedF)
    124             }
    125     }
    126 }
    127 // MARK: -
    128 struct SettingsStyle: View {
    129     let title: String
    130     @Binding var myListStyle: MyListStyle
    131 
    132     var body: some View {
    133         HStack {
    134             Text(title)
    135                 .talerFont(.title2)
    136             Spacer()
    137             Picker(selection: $myListStyle) {
    138                 ForEach(MyListStyle.allCases, id: \.self) {
    139                     Text($0.displayName.capitalized).tag($0)
    140                         .talerFont(.title2)
    141                 }
    142             } label: {}
    143                 .pickerStyle(.menu)
    144 //                .frame(alignment: .trailing)
    145 //                .background(WalletColors().buttonBackColor(pressed: false, disabled: false))  TODO: RoundRect
    146         }
    147         .accessibilityElement(children: .combine)
    148     }
    149 }
    150 // MARK: -
    151 struct SettingsTriState: View {
    152     var name: String
    153     @Binding var value: Int
    154     var description: String?
    155     var action: (_ value: Int) -> Void = {value in }
    156 
    157     func imageName(_ value: Int) -> (String, String) {
    158         return (value == 0) ? ("eye.slash", "Off")
    159              : (value == 1) ? ("eye",       "Type only")
    160                             : ("eye.fill",  "Type and JSON")
    161     }
    162     var body: some View {
    163         let image = imageName(value)
    164 
    165         VStack {
    166             HStack {
    167                 Text(name)
    168                     .talerFont(.title2)
    169                 Spacer()
    170                 Text(verbatim: " ")
    171                     .talerFont(.largeTitle)
    172                 Button {
    173                     if value > 0 {
    174                         value = -1
    175                         action(value)
    176                         Controller.shared.playSound(1)
    177                     } else {
    178                         value = value + 1
    179                         action(value)
    180                         Controller.shared.playSound(value)
    181                     }
    182                 } label: {
    183                     Image(systemName: image.0)
    184                         .talerFont(.largeTitle)
    185                 }
    186             }
    187 
    188             if let desc = description {
    189                 Text(desc)
    190                     .frame(maxWidth: .infinity, alignment: .leading)
    191                     .talerFont(.caption)
    192             }
    193         }
    194         .accessibilityElement(children: .combine)
    195         .accessibilityLabel(name)
    196         .accessibility(value: Text(image.1))
    197         .accessibilityHint(description ?? EMPTYSTRING)
    198         .padding([.bottom], 4)
    199     }
    200 }
    201 // MARK: -
    202 #if DEBUG
    203 struct SettingsItemPreview : View {
    204     @State var developerMode: Bool = false
    205     @State var observe: Int = 0
    206 
    207     var body: some View {
    208         VStack {
    209             SettingsToggle(name: "Developer Preview", value: $developerMode, id1: "dev1",
    210                     description: "More information intended for debugging")
    211             SettingsTriState(name: "Observe walletCore", value: $observe,
    212                      description: "on LocalConsole")
    213 
    214         }
    215     }
    216 }
    217 
    218 struct SettingsItem_Previews: PreviewProvider {
    219     static var previews: some View {
    220         List {
    221             SettingsItem (name: "Exchanges", id1: "list", description: "Manage list of exchanges known to this wallet") {}
    222             SettingsItemPreview()
    223             SettingsItem(name: "Save Logfile", id1: "save", description: "Help debugging wallet-core") {
    224                 Button("Save") {
    225                 }
    226                 .buttonStyle(.bordered)
    227                 .disabled(true)
    228             }
    229         }
    230     }
    231 }
    232 #endif