From 66b93181e10804db901f2c1b7527a5b89ce80e85 Mon Sep 17 00:00:00 2001 From: Marc Rousavy Date: Mon, 29 Mar 2021 11:34:35 +0200 Subject: [PATCH] Remove code scanning (#112) * Remove Audio Device if it failed to configure * Add `audio-in-use-by-other-app` error * Try removing on interruption * Format code * Remove code scanning * Fix export --- ios/CameraView+AVCaptureSession.swift | 28 ---- ios/CameraView+CodeScanning.swift | 48 ------ ios/CameraView.swift | 7 +- ...MetadataObject.ObjectType+descriptor.swift | 138 ------------------ ios/VisionCamera.xcodeproj/project.pbxproj | 8 - src/Camera.tsx | 25 +--- src/CameraProps.ts | 12 -- src/Code.ts | 65 --------- src/index.ts | 1 - 9 files changed, 3 insertions(+), 329 deletions(-) delete mode 100644 ios/CameraView+CodeScanning.swift delete mode 100644 ios/Parsers/AVMetadataObject.ObjectType+descriptor.swift delete mode 100644 src/Code.ts diff --git a/ios/CameraView+AVCaptureSession.swift b/ios/CameraView+AVCaptureSession.swift index 415b956..6aaf8cb 100644 --- a/ios/CameraView+AVCaptureSession.swift +++ b/ios/CameraView+AVCaptureSession.swift @@ -107,34 +107,6 @@ extension CameraView { movieOutput!.mirror() } - // Barcode Scanning - if let metadataOutput = self.metadataOutput { - captureSession.removeOutput(metadataOutput) - } - if let scannableCodes = self.scannableCodes { - // scannableCodes prop is not nil, so enable barcode scanning. - guard onCodeScanned != nil else { - return invokeOnError(.parameter(.invalidCombination(provided: "scannableCodes", missing: "onCodeScanned"))) - } - metadataOutput = AVCaptureMetadataOutput() - guard captureSession.canAddOutput(metadataOutput!) else { - return invokeOnError(.parameter(.unsupportedOutput(outputDescriptor: "metadata-output"))) - } - captureSession.addOutput(metadataOutput!) - metadataOutput!.setMetadataObjectsDelegate(self, queue: queue) - var objectTypes: [AVMetadataObject.ObjectType] = [] - scannableCodes.forEach { code in - do { - objectTypes.append(try AVMetadataObject.ObjectType(withString: code)) - } catch let EnumParserError.unsupportedOS(supportedOnOS: os) { - invokeOnError(.parameter(.unsupportedOS(unionName: "CodeType", receivedValue: code, supportedOnOs: os))) - } catch { - invokeOnError(.parameter(.invalid(unionName: "CodeType", receivedValue: code))) - } - } - metadataOutput!.metadataObjectTypes = objectTypes - } - invokeOnInitialized() isReady = true ReactLogger.logJS(level: .info, message: "Session successfully configured!") diff --git a/ios/CameraView+CodeScanning.swift b/ios/CameraView+CodeScanning.swift deleted file mode 100644 index 6fda33c..0000000 --- a/ios/CameraView+CodeScanning.swift +++ /dev/null @@ -1,48 +0,0 @@ -// -// CameraView+CodeScanning.swift -// Cuvent -// -// Created by Marc Rousavy on 16.12.20. -// Copyright © 2020 Facebook. All rights reserved. -// - -import AVFoundation -import Foundation - -extension CameraView: AVCaptureMetadataOutputObjectsDelegate { - func metadataOutput(_: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from _: AVCaptureConnection) { - if metadataObjects.isEmpty { - return - } - - let objects = metadataObjects.map { (object) -> [String: Any]? in - guard let object = object as? AVMetadataMachineReadableCodeObject else { - return nil - } - return [ - "code": object.stringValue as Any, - "type": object.type.descriptor, - "bounds": [ - "minX": object.bounds.minX, - "minY": object.bounds.minY, - "maxX": object.bounds.maxX, - "maxY": object.bounds.maxY, - "width": object.bounds.width, - "height": object.bounds.height, - ], - ] - } - invokeOnCodeScanned(codes: objects) - } - - private func invokeOnCodeScanned(codes: [[String: Any]?]) { - guard let onCodeScanned = self.onCodeScanned else { - ReactLogger.log(level: .warning, - message: "onCodeScanned was invoked with no listeners. " + - "This means that the Camera is unnecessarily scanning codes. This indicates a memory leak.", - alsoLogToJS: true) - return - } - onCodeScanned(["codes": codes]) - } -} diff --git a/ios/CameraView.swift b/ios/CameraView.swift index 7189a27..10c4df8 100644 --- a/ios/CameraView.swift +++ b/ios/CameraView.swift @@ -24,9 +24,7 @@ private let propsThatRequireReconfiguration = ["cameraId", "enableDepthData", "enableHighResolutionCapture", "enablePortraitEffectsMatteDelivery", - "preset", - "onCodeScanned", - "scannableCodes"] + "preset"] private let propsThatRequireDeviceReconfiguration = ["fps", "hdr", "lowLightBoost", @@ -99,7 +97,7 @@ final class CameraView: UIView { // pragma MARK: Private Properties internal var isReady = false - /// The serial execution queue for the camera preview layer (input stream) as well as output processing (take photo, record video, process metadata/barcodes) + /// The serial execution queue for the camera preview layer (input stream) as well as output processing (take photo and record video) internal let queue = DispatchQueue(label: "com.mrousavy.camera-queue", qos: .userInteractive, attributes: [], autoreleaseFrequency: .inherit, target: nil) // Capture Session internal let captureSession = AVCaptureSession() @@ -109,7 +107,6 @@ final class CameraView: UIView { // Outputs internal var photoOutput: AVCapturePhotoOutput? internal var movieOutput: AVCaptureMovieFileOutput? - internal var metadataOutput: AVCaptureMetadataOutput? // CameraView+TakePhoto internal var photoCaptureDelegates: [PhotoCaptureDelegate] = [] // CameraView+RecordVideo diff --git a/ios/Parsers/AVMetadataObject.ObjectType+descriptor.swift b/ios/Parsers/AVMetadataObject.ObjectType+descriptor.swift deleted file mode 100644 index 38fb44c..0000000 --- a/ios/Parsers/AVMetadataObject.ObjectType+descriptor.swift +++ /dev/null @@ -1,138 +0,0 @@ -// -// AVMetadataObject.ObjectType+descriptor.swift -// Cuvent -// -// Created by Marc Rousavy on 16.12.20. -// Copyright © 2020 Facebook. All rights reserved. -// - -import AVFoundation -import Foundation - -extension AVMetadataObject.ObjectType { - init(withString string: String) throws { - switch string { - case "aztec": - self = .aztec - return - case "cat-body": - if #available(iOS 13.0, *) { - self = .catBody - return - } else { - throw EnumParserError.unsupportedOS(supportedOnOS: "13.0") - } - case "code-128": - self = .code128 - return - case "code-39": - self = .code39 - return - case "code-39-mod-43": - self = .code39Mod43 - return - case "code-93": - self = .code93 - return - case "data-matrix": - self = .dataMatrix - return - case "dog-body": - if #available(iOS 13.0, *) { - self = .dogBody - return - } else { - throw EnumParserError.unsupportedOS(supportedOnOS: "13.0") - } - case "ean-13": - self = .ean13 - return - case "ean-8": - self = .ean8 - return - case "face": - self = .face - return - case "human-body": - if #available(iOS 13.0, *) { - self = .humanBody - return - } else { - throw EnumParserError.unsupportedOS(supportedOnOS: "13.0") - } - case "interleaved-2-of-5": - self = .interleaved2of5 - return - case "itf-14": - self = .itf14 - return - case "pdf-417": - self = .pdf417 - return - case "qr": - self = .qr - return - case "salient-object": - if #available(iOS 13.0, *) { - self = .salientObject - return - } else { - throw EnumParserError.unsupportedOS(supportedOnOS: "13.0") - } - case "upce": - self = .upce - return - default: - throw EnumParserError.invalidValue - } - } - - var descriptor: String { - if #available(iOS 13.0, *) { - switch self { - case .catBody: - return "cat-body" - case .dogBody: - return "dog-body" - case .humanBody: - return "human-body" - case .salientObject: - return "salient-object" - default: - break - } - } - switch self { - case .aztec: - return "aztec" - case .code128: - return "code-128" - case .code39: - return "code-39" - case .code39Mod43: - return "code-39-mod-43" - case .code93: - return "code-93" - case .dataMatrix: - return "data-matrix" - case .ean13: - return "ean-13" - case .ean8: - return "ean-8" - case .face: - return "face" - case .interleaved2of5: - return "interleaved-2-of-5" - case .itf14: - return "itf-14" - case .pdf417: - return "pdf-417" - case .qr: - return "qr" - case .upce: - return "upce" - default: - fatalError("AVMetadataObject.ObjectType has unknown state.") - } - } -} diff --git a/ios/VisionCamera.xcodeproj/project.pbxproj b/ios/VisionCamera.xcodeproj/project.pbxproj index aa467f0..82fb23a 100644 --- a/ios/VisionCamera.xcodeproj/project.pbxproj +++ b/ios/VisionCamera.xcodeproj/project.pbxproj @@ -24,7 +24,6 @@ B887519025E0102000DB86D6 /* AVCaptureDevice.Format+matchesFilter.swift in Sources */ = {isa = PBXBuildFile; fileRef = B887516925E0102000DB86D6 /* AVCaptureDevice.Format+matchesFilter.swift */; }; B887519125E0102000DB86D6 /* AVCaptureDevice.Format+toDictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = B887516A25E0102000DB86D6 /* AVCaptureDevice.Format+toDictionary.swift */; }; B887519225E0102000DB86D6 /* AVCaptureMovieFileOutput+mirror.swift in Sources */ = {isa = PBXBuildFile; fileRef = B887516B25E0102000DB86D6 /* AVCaptureMovieFileOutput+mirror.swift */; }; - B887519325E0102000DB86D6 /* CameraView+CodeScanning.swift in Sources */ = {isa = PBXBuildFile; fileRef = B887516C25E0102000DB86D6 /* CameraView+CodeScanning.swift */; }; B887519425E0102000DB86D6 /* MakeReactError.swift in Sources */ = {isa = PBXBuildFile; fileRef = B887516E25E0102000DB86D6 /* MakeReactError.swift */; }; B887519525E0102000DB86D6 /* ReactLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = B887516F25E0102000DB86D6 /* ReactLogger.swift */; }; B887519625E0102000DB86D6 /* Promise.swift in Sources */ = {isa = PBXBuildFile; fileRef = B887517025E0102000DB86D6 /* Promise.swift */; }; @@ -34,7 +33,6 @@ B887519A25E0102000DB86D6 /* AVVideoCodecType+descriptor.swift in Sources */ = {isa = PBXBuildFile; fileRef = B887517525E0102000DB86D6 /* AVVideoCodecType+descriptor.swift */; }; B887519B25E0102000DB86D6 /* AVCaptureSession.Preset+descriptor.swift in Sources */ = {isa = PBXBuildFile; fileRef = B887517625E0102000DB86D6 /* AVCaptureSession.Preset+descriptor.swift */; }; B887519C25E0102000DB86D6 /* AVCaptureDevice.TorchMode+descriptor.swift in Sources */ = {isa = PBXBuildFile; fileRef = B887517725E0102000DB86D6 /* AVCaptureDevice.TorchMode+descriptor.swift */; }; - B887519D25E0102000DB86D6 /* AVMetadataObject.ObjectType+descriptor.swift in Sources */ = {isa = PBXBuildFile; fileRef = B887517825E0102000DB86D6 /* AVMetadataObject.ObjectType+descriptor.swift */; }; B887519E25E0102000DB86D6 /* AVCapturePhotoOutput.QualityPrioritization+descriptor.swift in Sources */ = {isa = PBXBuildFile; fileRef = B887517925E0102000DB86D6 /* AVCapturePhotoOutput.QualityPrioritization+descriptor.swift */; }; B887519F25E0102000DB86D6 /* AVCaptureDevice.DeviceType+descriptor.swift in Sources */ = {isa = PBXBuildFile; fileRef = B887517A25E0102000DB86D6 /* AVCaptureDevice.DeviceType+descriptor.swift */; }; B88751A025E0102000DB86D6 /* AVAuthorizationStatus+descriptor.swift in Sources */ = {isa = PBXBuildFile; fileRef = B887517B25E0102000DB86D6 /* AVAuthorizationStatus+descriptor.swift */; }; @@ -81,7 +79,6 @@ B887516925E0102000DB86D6 /* AVCaptureDevice.Format+matchesFilter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "AVCaptureDevice.Format+matchesFilter.swift"; sourceTree = ""; }; B887516A25E0102000DB86D6 /* AVCaptureDevice.Format+toDictionary.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "AVCaptureDevice.Format+toDictionary.swift"; sourceTree = ""; }; B887516B25E0102000DB86D6 /* AVCaptureMovieFileOutput+mirror.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "AVCaptureMovieFileOutput+mirror.swift"; sourceTree = ""; }; - B887516C25E0102000DB86D6 /* CameraView+CodeScanning.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CameraView+CodeScanning.swift"; sourceTree = ""; }; B887516E25E0102000DB86D6 /* MakeReactError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MakeReactError.swift; sourceTree = ""; }; B887516F25E0102000DB86D6 /* ReactLogger.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReactLogger.swift; sourceTree = ""; }; B887517025E0102000DB86D6 /* Promise.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Promise.swift; sourceTree = ""; }; @@ -91,7 +88,6 @@ B887517525E0102000DB86D6 /* AVVideoCodecType+descriptor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "AVVideoCodecType+descriptor.swift"; sourceTree = ""; }; B887517625E0102000DB86D6 /* AVCaptureSession.Preset+descriptor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "AVCaptureSession.Preset+descriptor.swift"; sourceTree = ""; }; B887517725E0102000DB86D6 /* AVCaptureDevice.TorchMode+descriptor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "AVCaptureDevice.TorchMode+descriptor.swift"; sourceTree = ""; }; - B887517825E0102000DB86D6 /* AVMetadataObject.ObjectType+descriptor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "AVMetadataObject.ObjectType+descriptor.swift"; sourceTree = ""; }; B887517925E0102000DB86D6 /* AVCapturePhotoOutput.QualityPrioritization+descriptor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "AVCapturePhotoOutput.QualityPrioritization+descriptor.swift"; sourceTree = ""; }; B887517A25E0102000DB86D6 /* AVCaptureDevice.DeviceType+descriptor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "AVCaptureDevice.DeviceType+descriptor.swift"; sourceTree = ""; }; B887517B25E0102000DB86D6 /* AVAuthorizationStatus+descriptor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "AVAuthorizationStatus+descriptor.swift"; sourceTree = ""; }; @@ -133,7 +129,6 @@ B887518425E0102000DB86D6 /* CameraView.swift */, B86DC976260E315100FB17B2 /* CameraView+AVCaptureSession.swift */, B86DC973260E310600FB17B2 /* CameraView+AVAudioSession.swift */, - B887516C25E0102000DB86D6 /* CameraView+CodeScanning.swift */, B887518025E0102000DB86D6 /* CameraView+Focus.swift */, B887515D25E0102000DB86D6 /* CameraView+RecordVideo.swift */, B887517125E0102000DB86D6 /* CameraView+TakePhoto.swift */, @@ -185,7 +180,6 @@ B887517525E0102000DB86D6 /* AVVideoCodecType+descriptor.swift */, B887517625E0102000DB86D6 /* AVCaptureSession.Preset+descriptor.swift */, B887517725E0102000DB86D6 /* AVCaptureDevice.TorchMode+descriptor.swift */, - B887517825E0102000DB86D6 /* AVMetadataObject.ObjectType+descriptor.swift */, B887517925E0102000DB86D6 /* AVCapturePhotoOutput.QualityPrioritization+descriptor.swift */, B887517A25E0102000DB86D6 /* AVCaptureDevice.DeviceType+descriptor.swift */, B887517B25E0102000DB86D6 /* AVAuthorizationStatus+descriptor.swift */, @@ -313,7 +307,6 @@ B887519B25E0102000DB86D6 /* AVCaptureSession.Preset+descriptor.swift in Sources */, B88751A725E0102000DB86D6 /* CameraView+Zoom.swift in Sources */, B887518525E0102000DB86D6 /* PhotoCaptureDelegate.swift in Sources */, - B887519D25E0102000DB86D6 /* AVMetadataObject.ObjectType+descriptor.swift in Sources */, B887518B25E0102000DB86D6 /* AVCaptureDevice.Format+isBetterThan.swift in Sources */, B887518E25E0102000DB86D6 /* AVFrameRateRange+includes.swift in Sources */, B88751A125E0102000DB86D6 /* AVCaptureDevice.Position+descriptor.swift in Sources */, @@ -332,7 +325,6 @@ B887519C25E0102000DB86D6 /* AVCaptureDevice.TorchMode+descriptor.swift in Sources */, B88751A525E0102000DB86D6 /* CameraView+Focus.swift in Sources */, B86DC971260E2D5200FB17B2 /* AVAudioSession+trySetAllowHaptics.swift in Sources */, - B887519325E0102000DB86D6 /* CameraView+CodeScanning.swift in Sources */, B887519E25E0102000DB86D6 /* AVCapturePhotoOutput.QualityPrioritization+descriptor.swift in Sources */, B887518825E0102000DB86D6 /* VideoCaptureDelegate.swift in Sources */, ); diff --git a/src/Camera.tsx b/src/Camera.tsx index 70fbaae..2fcc810 100644 --- a/src/Camera.tsx +++ b/src/Camera.tsx @@ -5,7 +5,6 @@ import type { CameraDevice } from './CameraDevice'; import type { ErrorWithCause } from './CameraError'; import { CameraCaptureError, CameraRuntimeError, tryParseNativeCameraError, isErrorWithCause } from './CameraError'; import type { CameraProps } from './CameraProps'; -import type { Code } from './Code'; import type { PhotoFile, TakePhotoOptions } from './PhotoFile'; import type { Point } from './Point'; import type { TakeSnapshotOptions } from './Snapshot'; @@ -20,14 +19,10 @@ interface OnErrorEvent { message: string; cause?: ErrorWithCause; } -interface OnCodeScannedEvent { - codes: Code[]; -} type NativeCameraViewProps = Omit & { cameraId: string; onInitialized?: (event: NativeSyntheticEvent) => void; onError?: (event: NativeSyntheticEvent) => void; - onCodeScanned?: (event: NativeSyntheticEvent) => void; }; type RefType = React.Component & Readonly; //#endregion @@ -94,7 +89,6 @@ export class Camera extends React.PureComponent { this.state = { cameraId: undefined }; this.onInitialized = this.onInitialized.bind(this); this.onError = this.onError.bind(this); - this.onCodeScanned = this.onCodeScanned.bind(this); this.ref = React.createRef(); } @@ -375,14 +369,6 @@ export class Camera extends React.PureComponent { private onInitialized(): void { this.props.onInitialized?.(); } - - private onCodeScanned(event: NativeSyntheticEvent): void { - if (event == null) throw new Error('onCodeScanned() was invoked but event was null!'); - - if (this.props.onCodeScanned == null) - console.warn('Camera: onCodeScanned event was invoked but no listeners attached! Did you forget to remove the `scannableCodes` property?'); - else this.props.onCodeScanned(event.nativeEvent.codes); - } //#endregion /** @@ -403,16 +389,7 @@ export class Camera extends React.PureComponent { // We remove the big `device` object from the props because we only need to pass `cameraId` to native. const { device: _, ...props } = this.props; - return ( - - ); + return ; } } //#endregion diff --git a/src/CameraProps.ts b/src/CameraProps.ts index 57e4325..d714848 100644 --- a/src/CameraProps.ts +++ b/src/CameraProps.ts @@ -2,7 +2,6 @@ import type { ViewProps } from 'react-native'; import type { CameraDevice, CameraDeviceFormat, ColorSpace } from './CameraDevice'; import type { CameraRuntimeError } from './CameraError'; import type { CameraPreset } from './CameraPreset'; -import type { Code, CodeType } from './Code'; export interface CameraProps extends ViewProps { /** @@ -127,16 +126,5 @@ export interface CameraProps extends ViewProps { * Called when the camera was successfully initialized. */ onInitialized?: () => void; - - // TODO: Remove once frameProcessors land - /** - * Specify the code types this camera can scan. Will be removed with the addition of Frame Processors. - */ - scannableCodes?: CodeType[]; - // TODO: Remove once frameProcessors land - /** - * Called when one or multiple codes have been scanned. Will be removed with the addition of Frame Processors. - */ - onCodeScanned?: (codes: Code[]) => void; //#endregion } diff --git a/src/Code.ts b/src/Code.ts deleted file mode 100644 index 1044c15..0000000 --- a/src/Code.ts +++ /dev/null @@ -1,65 +0,0 @@ -/** - * Available code types - */ -export type CodeType = - | 'cat-body' - | 'dog-body' - | 'human-body' - | 'salient-object' - | 'aztec' - | 'code-128' - | 'code-39' - | 'code-39-mod-43' - | 'code-93' - | 'data-matrix' - | 'ean-13' - | 'ean-8' - | 'face' - | 'interleaved-2-of-5' - | 'itf-14' - | 'pdf-417' - | 'qr' - | 'upce'; - -/** - * Represents a Metadata Code read by the Camera. Example: QR Code - */ -export interface Code { - /** - * The decoded string representation of the code. - */ - code?: string; - /** - * The type of the code. - */ - type: CodeType; - /** - * The position of the code relative to the camera's bounds - */ - bounds: { - /** - * Returns the smallest value for the x-coordinate of the rectangle. - */ - minX: number; - /** - * Returns the smallest value for the y-coordinate of the rectangle. - */ - minY: number; - /** - * Returns the largest value of the x-coordinate for the rectangle. - */ - maxX: number; - /** - * Returns the largest value of the y-coordinate for the rectangle. - */ - maxY: number; - /** - * Returns the width of a rectangle. - */ - width: number; - /** - * Returns the height of a rectangle. - */ - height: number; - }; -} diff --git a/src/index.ts b/src/index.ts index 378174f..730480c 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5,7 +5,6 @@ export * from './CameraError'; export * from './CameraPosition'; export * from './CameraPreset'; export * from './CameraProps'; -export * from './Code'; export * from './PhotoFile'; export * from './Point'; export * from './Snapshot';