mirror of
https://github.com/bitwarden/ios.git
synced 2025-12-13 19:47:02 -06:00
91 lines
3.0 KiB
Swift
91 lines
3.0 KiB
Swift
import BitwardenKit
|
|
import Combine
|
|
import SwiftUI
|
|
|
|
// MARK: - ScanCodeProcessor
|
|
|
|
/// A processor that can process `ScanCodeAction`s.
|
|
///
|
|
/// This class is responsible for handling actions and effects related to scanning QR codes.
|
|
///
|
|
final class ScanCodeProcessor: StateProcessor<ScanCodeState, ScanCodeAction, ScanCodeEffect> {
|
|
// MARK: Types
|
|
|
|
/// A typealias for the services required by this processor.
|
|
typealias Services = HasCameraService
|
|
& HasErrorReporter
|
|
|
|
// MARK: Properties
|
|
|
|
/// A publisher that publishes the processor's scan result when it changes.
|
|
var qrScanPublisher: AnyPublisher<[ScanResult], Never> {
|
|
qrScanResultSubject.eraseToAnyPublisher()
|
|
}
|
|
|
|
// MARK: Private Properties
|
|
|
|
/// The `Coordinator` responsible for navigation-related actions.
|
|
private let coordinator: any Coordinator<AuthenticatorKeyCaptureRoute, AuthenticatorKeyCaptureEvent>
|
|
|
|
/// The services used by this processor, including camera authorization and error reporting.
|
|
private let services: Services
|
|
|
|
/// A subject cointaining the scan code results.
|
|
private var qrScanResultSubject = CurrentValueSubject<[ScanResult], Never>([])
|
|
|
|
// MARK: Intialization
|
|
|
|
/// Creates a new `ScanCodeProcessor`.
|
|
///
|
|
/// - Parameters:
|
|
/// - coordinator: The `Coordinator` responsible for managing navigation based on actions received.
|
|
/// - services: The services used by this processor, including access to the camera and error reporting.
|
|
/// - state: The initial state of this processor, representing the UI's state.
|
|
///
|
|
init(
|
|
coordinator: any Coordinator<AuthenticatorKeyCaptureRoute, AuthenticatorKeyCaptureEvent>,
|
|
services: Services,
|
|
state: ScanCodeState,
|
|
) {
|
|
self.coordinator = coordinator
|
|
self.services = services
|
|
super.init(state: state)
|
|
}
|
|
|
|
override func perform(_ effect: ScanCodeEffect) async {
|
|
switch effect {
|
|
case .appeared:
|
|
await setupCameraResultsObservation()
|
|
case .disappeared:
|
|
services.cameraService.stopCameraSession()
|
|
}
|
|
}
|
|
|
|
override func receive(_ action: ScanCodeAction) {
|
|
switch action {
|
|
case .dismissPressed:
|
|
coordinator.navigate(to: .dismiss())
|
|
case .manualEntryPressed:
|
|
coordinator.navigate(to: .manualKeyEntry)
|
|
}
|
|
}
|
|
|
|
/// Sets up the camera for scanning QR codes.
|
|
///
|
|
/// This method checks for camera support and initiates the camera session. If an error occurs,
|
|
/// it logs the error through the provided error reporting service.
|
|
///
|
|
private func setupCameraResultsObservation() async {
|
|
guard services.cameraService.deviceSupportsCamera() else {
|
|
coordinator.navigate(to: .manualKeyEntry)
|
|
return
|
|
}
|
|
|
|
for await value in services.cameraService.getScanResultPublisher() {
|
|
guard let value else { continue }
|
|
coordinator.navigate(to: .complete(value: value))
|
|
return
|
|
}
|
|
}
|
|
}
|