damus

nostr ios client
git clone git://jb55.com/damus
Log | Files | Refs | README | LICENSE

CodeScanner.swift (4022B)


      1 //
      2 //  CodeScanner.swift
      3 //  https://github.com/twostraws/CodeScanner
      4 //
      5 //  Created by Paul Hudson on 14/12/2021.
      6 //  Copyright © 2021 Paul Hudson. All rights reserved.
      7 //
      8 
      9 import AVFoundation
     10 import SwiftUI
     11 
     12 /// An enum describing the ways CodeScannerView can hit scanning problems.
     13 public enum ScanError: Error {
     14     /// The camera could not be accessed.
     15     case badInput
     16 
     17     /// The camera was not capable of scanning the requested codes.
     18     case badOutput
     19 
     20     /// Initialization failed.
     21     case initError(_ error: Error)
     22 }
     23 
     24 /// The result from a successful scan: the string that was scanned, and also the type of data that was found.
     25 /// The type is useful for times when you've asked to scan several different code types at the same time, because
     26 /// it will report the exact code type that was found.
     27 public struct ScanResult {
     28     /// The contents of the code.
     29     public let string: String
     30 
     31     /// The type of code that was matched.
     32     public let type: AVMetadataObject.ObjectType
     33 }
     34 
     35 /// The operating mode for CodeScannerView.
     36 public enum ScanMode {
     37     /// Scan exactly one code, then stop.
     38     case once
     39 
     40     /// Scan each code no more than once.
     41     case oncePerCode
     42 
     43     /// Keep scanning all codes until dismissed.
     44     case continuous
     45 }
     46 
     47 /// A SwiftUI view that is able to scan barcodes, QR codes, and more, and send back what was found.
     48 /// To use, set `codeTypes` to be an array of things to scan for, e.g. `[.qr]`, and set `completion` to
     49 /// a closure that will be called when scanning has finished. This will be sent the string that was detected or a `ScanError`.
     50 /// For testing inside the simulator, set the `simulatedData` property to some test data you want to send back.
     51 public struct CodeScannerView: UIViewControllerRepresentable {
     52     
     53     public let codeTypes: [AVMetadataObject.ObjectType]
     54     public let scanMode: ScanMode
     55     public let scanInterval: Double
     56     public let showViewfinder: Bool
     57     public var simulatedData = ""
     58     public var shouldVibrateOnSuccess: Bool
     59     public var isTorchOn: Bool
     60     public var isGalleryPresented: Binding<Bool>
     61     public var videoCaptureDevice: AVCaptureDevice?
     62     public var completion: (Result<ScanResult, ScanError>) -> Void
     63 
     64     public init(
     65         codeTypes: [AVMetadataObject.ObjectType],
     66         scanMode: ScanMode = .once,
     67         scanInterval: Double = 2.0,
     68         showViewfinder: Bool = false,
     69         simulatedData: String = "",
     70         shouldVibrateOnSuccess: Bool = true,
     71         isTorchOn: Bool = false,
     72         isGalleryPresented: Binding<Bool> = .constant(false),
     73         videoCaptureDevice: AVCaptureDevice? = AVCaptureDevice.default(for: .video),
     74         completion: @escaping (Result<ScanResult, ScanError>) -> Void
     75     ) {
     76         self.codeTypes = codeTypes
     77         self.scanMode = scanMode
     78         self.showViewfinder = showViewfinder
     79         self.scanInterval = scanInterval
     80         self.simulatedData = simulatedData
     81         self.shouldVibrateOnSuccess = shouldVibrateOnSuccess
     82         self.isTorchOn = isTorchOn
     83         self.isGalleryPresented = isGalleryPresented
     84         self.videoCaptureDevice = videoCaptureDevice
     85         self.completion = completion
     86     }
     87 
     88     public func makeCoordinator() -> ScannerCoordinator {
     89         ScannerCoordinator(parent: self)
     90     }
     91 
     92     public func makeUIViewController(context: Context) -> ScannerViewController {
     93         let viewController = ScannerViewController(showViewfinder: showViewfinder)
     94         viewController.delegate = context.coordinator
     95         return viewController
     96     }
     97 
     98     public func updateUIViewController(_ uiViewController: ScannerViewController, context: Context) {
     99         uiViewController.updateViewController(
    100             isTorchOn: isTorchOn,
    101             isGalleryPresented: isGalleryPresented.wrappedValue
    102         )
    103     }
    104     
    105 }
    106 
    107 @available(macCatalyst 14.0, *)
    108 struct CodeScannerView_Previews: PreviewProvider {
    109     static var previews: some View {
    110         CodeScannerView(codeTypes: [.qr]) { result in
    111             // do nothing
    112         }
    113     }
    114 }