QRCodeDetailView.swift (4761B)
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 AVFoundation 11 12 struct QRCodeDetailView: View { 13 let talerURI: String 14 let talerCopyShare: String 15 let incoming: Bool 16 let amount: Amount 17 let scope: ScopeInfo? 18 19 @EnvironmentObject private var controller: Controller 20 @AppStorage("minimalistic") var minimalistic: Bool = false 21 @AppStorage("showQRauto16") var showQRauto16: Bool = true 22 @AppStorage("showQRauto17") var showQRauto17: Bool = false 23 24 @State private var showQRcode = false 25 @State private var currencyInfo: CurrencyInfo? 26 @State private var qrImage: UIImage? = nil 27 28 private func currencyTickerChanged() async { 29 if let scope { 30 currencyInfo = controller.info(for: scope) 31 } 32 } 33 34 private func amountStr(_ currencyInfo : CurrencyInfo?) -> (String, String) { 35 let amountFormatted: (String, String) 36 let readable = amount.readableDescription 37 let myCurrencyInfo = currencyInfo ?? (scope != nil ? controller.info(for: scope!) : nil) 38 if let myCurrencyInfo { 39 amountFormatted = amount.formatted(myCurrencyInfo, isNegative: false, 40 useISO: false, a11yDecSep: nil) 41 } else { 42 amountFormatted = (readable, readable) 43 } 44 return amountFormatted 45 } 46 47 private func requesting(_ amountS: String) -> String { 48 minimalistic ? String(localized: "(payer) 1 mini", 49 defaultValue: "Requesting \(amountS)", 50 comment: "e.g. '5,3 €'") 51 : String(localized: "(payer) 1", 52 defaultValue: "Scan this to pay \(amountS)", 53 comment: "e.g. '5,3 €'") 54 } 55 private func sending(_ amountS: String) -> String { 56 minimalistic ? String(localized: "(payee) 1 mini", 57 defaultValue: "Sending \(amountS)", 58 comment: "e.g. '$ 7.41'") 59 : String(localized: "(payee) 1", 60 defaultValue: "Scan this to receive \(amountS)", 61 comment: "e.g. '$ 7.41'") 62 } 63 64 var body: some View { 65 if talerURI.count > 10 { 66 Section { 67 let amountStr = amountStr(currencyInfo) 68 let scanLong = incoming ? (requesting(amountStr.0), requesting(amountStr.1)) 69 : (sending(amountStr.0), sending(amountStr.1)) 70 let logo = Image(TALER_LOGO_QR) 71 let size = 240.0 72 let logoSize = 88.0 73 let qrView = QRGeneratorView(text: talerURI, size: size, logo: logo, logoSize: logoSize, image: $qrImage) 74 .frame(maxWidth: .infinity, alignment: .center) 75 if #available(iOS 17.7, *) { 76 BorderWithHCE(talerURI: talerURI, nfcHint: true, size: size, scanHints: scanLong) { 77 qrView 78 } 79 } else if showQRcode { 80 qrView 81 } else { 82 let qrCode = Image(systemName: QRCODE) // "qrcode" 83 Button(minimalistic ? "\(qrCode)" : "\(qrCode) Show QR code") { 84 withAnimation { showQRcode = true } 85 }.buttonStyle(TalerButtonStyle(type: .prominent)) 86 } 87 CopyShare(textToCopy: talerCopyShare, image: qrImage) 88 .disabled(false) 89 // .padding(.bottom) 90 .listRowSeparator(.hidden) 91 92 } 93 .task(id: controller.currencyTicker) { await currencyTickerChanged() } 94 .task { 95 withAnimation { 96 if #available(iOS 17.7, *) { 97 showQRcode = showQRauto17 98 } else { 99 showQRcode = showQRauto16 100 } 101 } 102 } 103 } 104 } 105 } 106 // MARK: - 107 #if DEBUG 108 //fileprivate struct ContentView: View { 109 // @State var previewURI: String = "taler://pay-push/exchange.demo.taler.net/95ZG4D1AGFGZQ7CNQ1V49D3FT18HXKA6HQT4X3XME9YSJQVFQ520" 110 // 111 // var body: some View { 112 // let amount = Amount(currency: LONGCURRENCY, cent: 123) 113 // List { 114 // QRCodeDetailView(talerURI: previewURI, talerCopyShare: previewURI, incoming: false, amount: amount) 115 // } 116 // } 117 //} 118 //struct QRCodeDetailView_Previews: PreviewProvider { 119 // 120 // static var previews: some View { 121 // ContentView() 122 // } 123 //} 124 #endif