damus

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

ScannerCoordinator.swift (2472B)


      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 extension CodeScannerView {
     13     @available(macCatalyst 14.0, *)
     14     public class ScannerCoordinator: NSObject, AVCaptureMetadataOutputObjectsDelegate {
     15         var parent: CodeScannerView
     16         var codesFound = Set<String>()
     17         var didFinishScanning = false
     18         var lastTime = Date(timeIntervalSince1970: 0)
     19 
     20         init(parent: CodeScannerView) {
     21             self.parent = parent
     22         }
     23 
     24         public func reset() {
     25             codesFound.removeAll()
     26             didFinishScanning = false
     27             lastTime = Date(timeIntervalSince1970: 0)
     28         }
     29 
     30         public func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
     31             if let metadataObject = metadataObjects.first {
     32                 guard let readableObject = metadataObject as? AVMetadataMachineReadableCodeObject else { return }
     33                 guard let stringValue = readableObject.stringValue else { return }
     34                 guard didFinishScanning == false else { return }
     35                 let result = ScanResult(string: stringValue, type: readableObject.type)
     36 
     37                 switch parent.scanMode {
     38                 case .once:
     39                     found(result)
     40                     // make sure we only trigger scan once per use
     41                     didFinishScanning = true
     42 
     43                 case .oncePerCode:
     44                     if !codesFound.contains(stringValue) {
     45                         codesFound.insert(stringValue)
     46                         found(result)
     47                     }
     48 
     49                 case .continuous:
     50                     if isPastScanInterval() {
     51                         found(result)
     52                     }
     53                 }
     54             }
     55         }
     56 
     57         func isPastScanInterval() -> Bool {
     58             Date().timeIntervalSince(lastTime) >= parent.scanInterval
     59         }
     60 
     61         func found(_ result: ScanResult) {
     62             lastTime = Date()
     63 
     64             if parent.shouldVibrateOnSuccess {
     65                 AudioServicesPlaySystemSound(SystemSoundID(kSystemSoundID_Vibrate))
     66             }
     67 
     68             parent.completion(.success(result))
     69         }
     70 
     71         func didFail(reason: ScanError) {
     72             parent.completion(.failure(reason))
     73         }
     74     }
     75 }