taler-ios

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

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