Files
self/app/ios/MRZScannerModule.swift
2025-06-04 11:37:32 +02:00

92 lines
3.2 KiB
Swift

//
// MRZScannerModule.swift
// ProofOfPassport
//
// Created by Rémi Colin on 27/02/2024.
//
import Foundation
import React
import SwiftUI
@objc(MRZScannerModule)
class MRZScannerModule: NSObject, RCTBridgeModule {
static func moduleName() -> String! {
return "MRZScannerModule"
}
static func requiresMainQueueSetup() -> Bool {
return true
}
@objc func startScanning(_ resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
DispatchQueue.main.async {
guard let rootViewController = UIApplication.shared.keyWindow?.rootViewController else {
reject("error", "Unable to find root view controller", nil)
return
}
var hostingController: UIHostingController<ScannerWithInstructions>? = nil
var scannerView = QKMRZScannerViewRepresentable()
let lottieView = LottieView(animationFileName: "passport", loopMode: .loop)
scannerView.onScanResult = { scanResult in
// Format dates to YYMMDD format
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyMMdd"
let birthDate = scanResult.birthdate.map { dateFormatter.string(from: $0) } ?? ""
let expiryDate = scanResult.expiryDate.map { dateFormatter.string(from: $0) } ?? ""
let resultDict: [String: Any] = [
"documentNumber": scanResult.documentNumber,
"expiryDate": expiryDate,
"birthDate": birthDate
]
resolve(resultDict)
// Dismiss the hosting controller after scanning
hostingController?.dismiss(animated: true, completion: nil)
}
// Wrap the scanner view and instruction text in a new SwiftUI view
let scannerWithInstructions = ScannerWithInstructions(scannerView: scannerView, lottieView: lottieView)
hostingController = UIHostingController(rootView: scannerWithInstructions)
rootViewController.present(hostingController!, animated: true, completion: nil)
}
}
@objc func stopScanning(_ resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) {
// Logic to stop scanning
resolve("Scanning stopped")
}
}
// Define a new SwiftUI view that includes the scanner and instruction text
struct ScannerWithInstructions: View {
var scannerView: QKMRZScannerViewRepresentable
var lottieView: LottieView
var body: some View {
ZStack {
Color.white.ignoresSafeArea() // This creates a white background for the entire view
VStack {
ZStack {
scannerView
.mask {
RoundedRectangle(cornerRadius: 15)
.frame(width: 370, height: 270)
}
lottieView.frame(width: 360, height: 230)
}
.frame(height: 320)
Text("Hold your passport on a flat surface while scanning")
.foregroundColor(.black)
.multilineTextAlignment(.center)
.frame(width: 300)
.padding()
}
}
}
}