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