1*5d715522SAlan Hughes import ExpoModulesCore
2*5d715522SAlan Hughes 
3*5d715522SAlan Hughes public final class BarCodeScannerModule: Module {
definitionnull4*5d715522SAlan Hughes   public func definition() -> ModuleDefinition {
5*5d715522SAlan Hughes     Name("ExpoBarCodeScanner")
6*5d715522SAlan Hughes 
7*5d715522SAlan Hughes     Constants([
8*5d715522SAlan Hughes       "Type": [
9*5d715522SAlan Hughes         "front": EXCameraType.front.rawValue,
10*5d715522SAlan Hughes         "back": EXCameraType.back.rawValue
11*5d715522SAlan Hughes       ],
12*5d715522SAlan Hughes       "BarCodeType": EXBarCodeScannerUtils.validBarCodeTypes()
13*5d715522SAlan Hughes     ])
14*5d715522SAlan Hughes 
15*5d715522SAlan Hughes     OnCreate {
16*5d715522SAlan Hughes       let permissionsManager = self.appContext?.permissions
17*5d715522SAlan Hughes 
18*5d715522SAlan Hughes       EXPermissionsMethodsDelegate.register(
19*5d715522SAlan Hughes         [EXBareCodeCameraRequester()],
20*5d715522SAlan Hughes         withPermissionsManager: permissionsManager
21*5d715522SAlan Hughes       )
22*5d715522SAlan Hughes     }
23*5d715522SAlan Hughes 
24*5d715522SAlan Hughes     AsyncFunction("getPermissionsAsync") { (promise: Promise) in
25*5d715522SAlan Hughes       EXPermissionsMethodsDelegate.getPermissionWithPermissionsManager(
26*5d715522SAlan Hughes         self.appContext?.permissions,
27*5d715522SAlan Hughes         withRequester: EXBareCodeCameraRequester.self,
28*5d715522SAlan Hughes         resolve: promise.resolver,
29*5d715522SAlan Hughes         reject: promise.legacyRejecter
30*5d715522SAlan Hughes       )
31*5d715522SAlan Hughes     }
32*5d715522SAlan Hughes 
33*5d715522SAlan Hughes     AsyncFunction("requestPermissionsAsync") { (promise: Promise) in
34*5d715522SAlan Hughes       EXPermissionsMethodsDelegate.askForPermission(
35*5d715522SAlan Hughes         withPermissionsManager: self.appContext?.permissions,
36*5d715522SAlan Hughes         withRequester: EXBareCodeCameraRequester.self,
37*5d715522SAlan Hughes         resolve: promise.resolver,
38*5d715522SAlan Hughes         reject: promise.legacyRejecter
39*5d715522SAlan Hughes       )
40*5d715522SAlan Hughes     }
41*5d715522SAlan Hughes 
42*5d715522SAlan Hughes     AsyncFunction("scanFromURLAsync") { (url: URL, _: [String], promise: Promise) in
43*5d715522SAlan Hughes       guard let imageLoader = appContext?.imageLoader else {
44*5d715522SAlan Hughes         throw ImageLoaderNotFound()
45*5d715522SAlan Hughes       }
46*5d715522SAlan Hughes 
47*5d715522SAlan Hughes       imageLoader.loadImage(for: url) { error, image in
48*5d715522SAlan Hughes         if error != nil {
49*5d715522SAlan Hughes           promise.reject(FailedToLoadImage())
50*5d715522SAlan Hughes           return
51*5d715522SAlan Hughes         }
52*5d715522SAlan Hughes 
53*5d715522SAlan Hughes         guard let cgImage = image?.cgImage else {
54*5d715522SAlan Hughes           promise.reject(FailedToLoadImage())
55*5d715522SAlan Hughes           return
56*5d715522SAlan Hughes         }
57*5d715522SAlan Hughes 
58*5d715522SAlan Hughes         guard let detector = CIDetector(
59*5d715522SAlan Hughes           ofType: CIDetectorTypeQRCode,
60*5d715522SAlan Hughes           context: nil,
61*5d715522SAlan Hughes           options: [CIDetectorAccuracy: CIDetectorAccuracyHigh]
62*5d715522SAlan Hughes         ) else {
63*5d715522SAlan Hughes           promise.reject(InitScannerFailed())
64*5d715522SAlan Hughes           return
65*5d715522SAlan Hughes         }
66*5d715522SAlan Hughes 
67*5d715522SAlan Hughes         let ciImage = CIImage(cgImage: cgImage)
68*5d715522SAlan Hughes         let features = detector.features(in: ciImage)
69*5d715522SAlan Hughes         promise.resolve(self.getResultFrom(features))
70*5d715522SAlan Hughes       }
71*5d715522SAlan Hughes     }
72*5d715522SAlan Hughes 
73*5d715522SAlan Hughes     View(EXBarCodeScannerView.self) {
74*5d715522SAlan Hughes       Events("onBarCodeScanned")
75*5d715522SAlan Hughes 
76*5d715522SAlan Hughes       Prop("type") { (view, type: Int) in
77*5d715522SAlan Hughes         if view.presetCamera != type {
78*5d715522SAlan Hughes           view.presetCamera = type
79*5d715522SAlan Hughes         }
80*5d715522SAlan Hughes       }
81*5d715522SAlan Hughes 
82*5d715522SAlan Hughes       Prop("barCodeTypes") { (view, barcodeTypes: [String]) in
83*5d715522SAlan Hughes         view.barCodeTypes = barcodeTypes
84*5d715522SAlan Hughes       }
85*5d715522SAlan Hughes     }
86*5d715522SAlan Hughes   }
87*5d715522SAlan Hughes 
getResultFromnull88*5d715522SAlan Hughes   private func getResultFrom(_ features: [CIFeature]) -> [[AnyHashable: Any]?] {
89*5d715522SAlan Hughes     var result = [[AnyHashable: Any]?]()
90*5d715522SAlan Hughes 
91*5d715522SAlan Hughes     for feature in features {
92*5d715522SAlan Hughes       if let qrCodeFeature = feature as? CIQRCodeFeature {
93*5d715522SAlan Hughes         let item = EXBarCodeScannerUtils.ciQRCodeFeature(
94*5d715522SAlan Hughes           toDicitionary: qrCodeFeature,
95*5d715522SAlan Hughes           barCodeType: AVMetadataObject.ObjectType.qr.rawValue
96*5d715522SAlan Hughes         )
97*5d715522SAlan Hughes         result.append(item)
98*5d715522SAlan Hughes       }
99*5d715522SAlan Hughes     }
100*5d715522SAlan Hughes 
101*5d715522SAlan Hughes     return result
102*5d715522SAlan Hughes   }
103*5d715522SAlan Hughes }
104