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
This commit is contained in:
Marc Rousavy 2021-03-29 11:34:35 +02:00 committed by GitHub
parent 1558dd2f15
commit 66b93181e1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 3 additions and 329 deletions

View File

@ -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!")

View File

@ -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])
}
}

View File

@ -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

View File

@ -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.")
}
}
}

View File

@ -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 = "<group>"; };
B887516A25E0102000DB86D6 /* AVCaptureDevice.Format+toDictionary.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "AVCaptureDevice.Format+toDictionary.swift"; sourceTree = "<group>"; };
B887516B25E0102000DB86D6 /* AVCaptureMovieFileOutput+mirror.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "AVCaptureMovieFileOutput+mirror.swift"; sourceTree = "<group>"; };
B887516C25E0102000DB86D6 /* CameraView+CodeScanning.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CameraView+CodeScanning.swift"; sourceTree = "<group>"; };
B887516E25E0102000DB86D6 /* MakeReactError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MakeReactError.swift; sourceTree = "<group>"; };
B887516F25E0102000DB86D6 /* ReactLogger.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReactLogger.swift; sourceTree = "<group>"; };
B887517025E0102000DB86D6 /* Promise.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Promise.swift; sourceTree = "<group>"; };
@ -91,7 +88,6 @@
B887517525E0102000DB86D6 /* AVVideoCodecType+descriptor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "AVVideoCodecType+descriptor.swift"; sourceTree = "<group>"; };
B887517625E0102000DB86D6 /* AVCaptureSession.Preset+descriptor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "AVCaptureSession.Preset+descriptor.swift"; sourceTree = "<group>"; };
B887517725E0102000DB86D6 /* AVCaptureDevice.TorchMode+descriptor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "AVCaptureDevice.TorchMode+descriptor.swift"; sourceTree = "<group>"; };
B887517825E0102000DB86D6 /* AVMetadataObject.ObjectType+descriptor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "AVMetadataObject.ObjectType+descriptor.swift"; sourceTree = "<group>"; };
B887517925E0102000DB86D6 /* AVCapturePhotoOutput.QualityPrioritization+descriptor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "AVCapturePhotoOutput.QualityPrioritization+descriptor.swift"; sourceTree = "<group>"; };
B887517A25E0102000DB86D6 /* AVCaptureDevice.DeviceType+descriptor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "AVCaptureDevice.DeviceType+descriptor.swift"; sourceTree = "<group>"; };
B887517B25E0102000DB86D6 /* AVAuthorizationStatus+descriptor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "AVAuthorizationStatus+descriptor.swift"; sourceTree = "<group>"; };
@ -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 */,
);

View File

@ -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<CameraProps, 'device' | 'onInitialized' | 'onError' | 'onCodeScanned'> & {
cameraId: string;
onInitialized?: (event: NativeSyntheticEvent<void>) => void;
onError?: (event: NativeSyntheticEvent<OnErrorEvent>) => void;
onCodeScanned?: (event: NativeSyntheticEvent<OnCodeScannedEvent>) => void;
};
type RefType = React.Component<NativeCameraViewProps> & Readonly<NativeMethods>;
//#endregion
@ -94,7 +89,6 @@ export class Camera extends React.PureComponent<CameraProps, CameraState> {
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<RefType>();
}
@ -375,14 +369,6 @@ export class Camera extends React.PureComponent<CameraProps, CameraState> {
private onInitialized(): void {
this.props.onInitialized?.();
}
private onCodeScanned(event: NativeSyntheticEvent<OnCodeScannedEvent>): 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<CameraProps, CameraState> {
// We remove the big `device` object from the props because we only need to pass `cameraId` to native.
const { device: _, ...props } = this.props;
return (
<NativeCameraView
{...props}
cameraId={this.state.cameraId}
ref={this.ref}
onInitialized={this.onInitialized}
onError={this.onError}
onCodeScanned={this.onCodeScanned}
/>
);
return <NativeCameraView {...props} cameraId={this.state.cameraId} ref={this.ref} onInitialized={this.onInitialized} onError={this.onError} />;
}
}
//#endregion

View File

@ -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
}

View File

@ -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;
};
}

View File

@ -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';