TransactionsEmptyView.swift (6795B)
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 SymLog 10 11 /// This view shows hints if a wallet is empty 12 /// It is the very first thing the user sees after installing the app 13 14 struct TransactionsEmptyView: View { 15 let stack: CallStack 16 let currency: String 17 18 @AppStorage("myListStyle") var myListStyle: MyListStyle = .automatic 19 20 var body: some View { 21 List { 22 Section { 23 Text("There are no transactions for \(currency).") 24 } 25 .talerFont(.title2) 26 } 27 .listStyle(myListStyle.style).anyView 28 .background(FullBackground()) 29 .onAppear() { 30 DebugViewC.shared.setViewID(VIEW_EMPTY_HISTORY, stack: stack.push()) // 20 31 } 32 } 33 } 34 35 // MARK: - 36 struct UnconfirmedKeyChangeView: View { 37 var baseURL: String 38 var balance: Balance 39 var isLegacy: Bool 40 41 @Environment(\.dismiss) var dismiss // pop back once 42 @EnvironmentObject private var model: WalletModel 43 @EnvironmentObject private var controller: Controller 44 @AppStorage("myListStyle") var myListStyle: MyListStyle = .automatic 45 46 @State private var exchange: Exchange? = nil 47 @State private var alertAccept: Bool = false 48 @State private var alertDelete: Bool = false 49 50 func notValid(_ amountString: String) -> String { 51 String(localized: "Unfortunately this means, that your \(amountString) are not valid anymore, because they were obtained with the old security identity.") 52 } 53 54 func keep(_ amountString: String) -> String { 55 String(localized: "Keep the \(amountString)") 56 } 57 58 func delete(_ amountString: String) -> String { 59 String(localized: "Delete the \(amountString)") 60 } 61 62 func acceptAction() { 63 if let exchange, let masterPub = exchange.masterPub { 64 Task { 65 try? await model.confirmExchangeKeyChange(exchangeBaseUrl: baseURL, 66 currentMasterPub: masterPub) 67 dismiss() 68 } 69 } else { 70 // TODO: Yikes! 71 } 72 } 73 74 func deleteAction() { 75 if let exchange, let masterPub = exchange.masterPub { 76 Task { 77 try? await model.purgeExchangeLegacyKeys(exchangeBaseUrl: baseURL, 78 currentMasterPub: masterPub) 79 dismiss() 80 } 81 } else { 82 // TODO: Yikes! 83 } 84 } 85 86 func keepAction() { 87 withAnimation { 88 dismiss() 89 } 90 } 91 92 private var acceptButton: some View { 93 Button("Accept") { 94 alertAccept = false 95 acceptAction() 96 } 97 } 98 private var deleteButton: some View { 99 Button("Delete") { 100 alertDelete = false 101 deleteAction() 102 } 103 } 104 private var dismissAlertButton: some View { 105 Button("Cancel", role: .cancel) { 106 alertAccept = false 107 alertDelete = false 108 } 109 } 110 111 @MainActor 112 private func viewDidLoad() async { 113 exchange = await controller.exchange(for: baseURL) 114 } 115 116 var body: some View { 117 let scope = balance.scopeInfo 118 let available = balance.available 119 let formatted = available.formatted(scope, isNegative: false) 120 let navTitle = String(localized: "Security Alert!", comment: "ViewTitle of UnconfirmedKeyChangeView") 121 let warning1 = Text("Only trust the new identity if the payment service has confirmed this change.") 122 let warning2 = Text("Otherwise, wait and try again later...") 123 List { 124 Section { 125 Text("The security identity of \(baseURL.trimURL) has changed unexpectedly.") 126 127 if isLegacy { 128 if !available.isZero { 129 let sorry = notValid(formatted.0) 130 let a11y = notValid(formatted.1) 131 Text(sorry) 132 .accessibilityLabel(a11y) 133 134 warning1 135 .talerFont(.body) 136 warning2 137 .bold() 138 .talerFont(.body) 139 140 Button(keep(formatted.0), action: keepAction) 141 .buttonStyle(TalerButtonStyle(type: .bordered)) 142 .padding(.horizontal) 143 .accessibilityLabel(keep(formatted.1)) 144 145 Text("If you are sure that the old security identity will not be used anymore, you can delete the invalid money.") 146 .talerFont(.body) 147 Button(delete(formatted.0), action: { alertDelete = true }) 148 .buttonStyle(TalerButtonStyle(type: .bordered)) 149 .padding(.horizontal) 150 .accessibilityLabel(delete(formatted.1)) 151 } 152 } else { 153 warning1 154 warning2 155 .bold() 156 Text("If you are sure that the old security identity will not be used anymore, you can withdraw new money with the new security identity.") 157 Button("Accept new security identity", action: { alertAccept = true }) 158 .buttonStyle(TalerButtonStyle(type: .bordered)) 159 .padding(.horizontal) 160 Text("Money you obtained with the old security identity will be invalid.") 161 } 162 } 163 .talerFont(.title2) 164 .listRowSeparator(.hidden) 165 } 166 .listStyle(myListStyle.style).anyView 167 .background(FullBackground()) 168 .navigationTitle(navTitle) 169 .task { 170 await viewDidLoad() 171 } 172 .alert("Accept the new payment service security identity.", 173 isPresented: $alertAccept, 174 actions: { acceptButton 175 dismissAlertButton }, 176 message: { Text("Are you sure? Your money obtained with the old security identity will be invalid.") }) 177 .alert("Delete money obtained with the old security identity.", 178 isPresented: $alertDelete, 179 actions: { deleteButton 180 dismissAlertButton }, 181 message: { Text("Are you sure? That money will be lost.") }) 182 } 183 } 184 // MARK: - 185 struct TransactionsEmptyView_Previews: PreviewProvider { 186 static var previews: some View { 187 TransactionsEmptyView(stack: CallStack("Preview"), currency: LONGCURRENCY) 188 } 189 }