taler-ios

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

QRSheet.swift (3350B)


      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 CodeScanner
     10 import SymLog
     11 import AVFoundation
     12 
     13 struct QRSheet: View {
     14     private let symLog = SymLogV(0)
     15     let stack: CallStack
     16     let selectedBalance: Balance?
     17 
     18     @EnvironmentObject private var model: WalletModel
     19     @State private var scannedCode: String?
     20     @State private var urlToOpen: URL?
     21 
     22     func codeToURL(_ code: String) -> URL? {
     23         if let scannedURL = URL(string: code) {
     24             return scannedURL
     25         }
     26         if let encodedScan = code.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) {
     27             if let encodedURL = URL(string: encodedScan) {
     28                 return encodedURL
     29             }
     30         }
     31         return nil
     32     }
     33 
     34     var body: some View {
     35 #if PRINT_CHANGES
     36         let _ = Self._printChanges()
     37         let _ = symLog.vlog(scannedCode)       // just to get the # to compare it with .onAppear & onDisappear
     38 #endif
     39         Group {
     40             let errorAnnouncement = String(localized: "Error while scanning QR code", comment: "a11y")
     41             if scannedCode != nil {
     42                 if let scannedURL = codeToURL(scannedCode!) {
     43                     let scheme = scannedURL.scheme
     44                     if scheme?.lowercased() == "taler" {
     45                         URLSheet(stack: stack.push(),
     46                        selectedBalance: selectedBalance,
     47                              urlToOpen: $urlToOpen)
     48                     } else {
     49 //                        let _ = print(scannedURL)       // TODO: error logging
     50                         ErrorView(title: String(localized: "Scanned QR is no talerURI"),
     51                                 message: scannedURL.absoluteString,
     52                                copyable: true) {
     53                             dismissTop(stack.push())
     54                         }
     55                     }
     56                 } else {
     57                     ErrorView(title: String(localized: "Scanned QR is no URL"),
     58                             message: scannedCode,
     59                            copyable: true) {
     60                         dismissTop(stack.push())
     61                     }
     62                 }
     63             } else {
     64                 CodeScannerView(codeTypes: [AVMetadataObject.ObjectType.qr], showViewfinder: true) { response in
     65                     let closingAnnouncement: String
     66                     switch response {
     67                         case .success(let result):
     68                             symLog.log("Found code: \(result.string)")
     69                             scannedCode = result.string
     70                             urlToOpen = codeToURL(result.string)
     71                             closingAnnouncement = String(localized: "QR code recognized", comment: "a11y")
     72                         case .failure(let error):
     73                             // TODO: errorAlert
     74                             model.setError(error)
     75                             closingAnnouncement = errorAnnouncement
     76                     }
     77                         announce(closingAnnouncement)
     78                 }
     79             }
     80         }
     81     }
     82 }
     83 // MARK: -
     84 //struct PaySheet_Previews: PreviewProvider {
     85 //    static var previews: some View {
     86 //            // needs BackendManager
     87 //        URLSheet(urlToOpen: URL(string: "ftp://this.URL.is.invalid")!)
     88 //    }
     89 //}