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 //}