Implement bank transfer app flows
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
import SwiftUI
|
||||
import AVFoundation
|
||||
|
||||
struct QRScannerSheet: View {
|
||||
var onResult: (String) -> Void
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
|
||||
var body: some View {
|
||||
NavigationStack {
|
||||
QRCameraView(onResult: { result in
|
||||
dismiss()
|
||||
onResult(result)
|
||||
})
|
||||
.ignoresSafeArea()
|
||||
.navigationTitle("Scan QR Code")
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .navigationBarLeading) {
|
||||
Button("Cancel") { dismiss() }
|
||||
.foregroundStyle(.white)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private struct QRCameraView: UIViewRepresentable {
|
||||
var onResult: (String) -> Void
|
||||
|
||||
func makeUIView(context: Context) -> UIView {
|
||||
let view = UIView()
|
||||
view.backgroundColor = .black
|
||||
|
||||
let session = AVCaptureSession()
|
||||
guard let device = AVCaptureDevice.default(for: .video),
|
||||
let input = try? AVCaptureDeviceInput(device: device) else {
|
||||
return view
|
||||
}
|
||||
if session.canAddInput(input) { session.addInput(input) }
|
||||
|
||||
let output = AVCaptureMetadataOutput()
|
||||
if session.canAddOutput(output) {
|
||||
session.addOutput(output)
|
||||
output.setMetadataObjectsDelegate(context.coordinator, queue: .main)
|
||||
output.metadataObjectTypes = [.qr]
|
||||
}
|
||||
|
||||
let preview = AVCaptureVideoPreviewLayer(session: session)
|
||||
preview.videoGravity = .resizeAspectFill
|
||||
preview.frame = view.bounds
|
||||
view.layer.addSublayer(preview)
|
||||
context.coordinator.previewLayer = preview
|
||||
|
||||
DispatchQueue.global(qos: .userInitiated).async { session.startRunning() }
|
||||
context.coordinator.session = session
|
||||
return view
|
||||
}
|
||||
|
||||
func updateUIView(_ uiView: UIView, context: Context) {
|
||||
context.coordinator.previewLayer?.frame = uiView.bounds
|
||||
}
|
||||
|
||||
func makeCoordinator() -> Coordinator { Coordinator(onResult: onResult) }
|
||||
|
||||
final class Coordinator: NSObject, AVCaptureMetadataOutputObjectsDelegate {
|
||||
var onResult: (String) -> Void
|
||||
var session: AVCaptureSession?
|
||||
var previewLayer: AVCaptureVideoPreviewLayer?
|
||||
private var didCapture = false
|
||||
|
||||
init(onResult: @escaping (String) -> Void) {
|
||||
self.onResult = onResult
|
||||
}
|
||||
|
||||
func metadataOutput(_ output: AVCaptureMetadataOutput,
|
||||
didOutput objects: [AVMetadataObject],
|
||||
from connection: AVCaptureConnection) {
|
||||
guard !didCapture,
|
||||
let obj = objects.first as? AVMetadataMachineReadableCodeObject,
|
||||
let str = obj.stringValue else { return }
|
||||
didCapture = true
|
||||
session?.stopRunning()
|
||||
DispatchQueue.main.async { self.onResult(str) }
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user