Skip to content

Commit

Permalink
feat: Support tap to focus without a Preview View
Browse files Browse the repository at this point in the history
  • Loading branch information
mrousavy committed Jul 17, 2024
1 parent 9a06204 commit add4f3e
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 15 deletions.
16 changes: 8 additions & 8 deletions package/example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1391,16 +1391,16 @@ PODS:
- ReactCommon/turbomodule/core
- Yoga
- SocketRocket (0.7.0)
- VisionCamera (4.4.3):
- VisionCamera/Core (= 4.4.3)
- VisionCamera/FrameProcessors (= 4.4.3)
- VisionCamera/React (= 4.4.3)
- VisionCamera/Core (4.4.3)
- VisionCamera/FrameProcessors (4.4.3):
- VisionCamera (4.5.0):
- VisionCamera/Core (= 4.5.0)
- VisionCamera/FrameProcessors (= 4.5.0)
- VisionCamera/React (= 4.5.0)
- VisionCamera/Core (4.5.0)
- VisionCamera/FrameProcessors (4.5.0):
- React
- React-callinvoker
- react-native-worklets-core
- VisionCamera/React (4.4.3):
- VisionCamera/React (4.5.0):
- React-Core
- VisionCamera/FrameProcessors
- Yoga (0.0.0)
Expand Down Expand Up @@ -1688,7 +1688,7 @@ SPEC CHECKSUMS:
RNStaticSafeAreaInsets: 055ddbf5e476321720457cdaeec0ff2ba40ec1b8
RNVectorIcons: 2a2f79274248390b80684ea3c4400bd374a15c90
SocketRocket: abac6f5de4d4d62d24e11868d7a2f427e0ef940d
VisionCamera: 7435f20f7ee7756a1e307e986195a97764da5142
VisionCamera: c75705e486d3ba2e0e850e98aa314010f04e922d
Yoga: 2f71ecf38d934aecb366e686278102a51679c308

PODFILE CHECKSUM: 49584be049764895189f1f88ebc9769116621103
Expand Down
26 changes: 26 additions & 0 deletions package/ios/Core/Types/CoordinateSystem.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//
// CoordinateSystem.swift
// VisionCamera
//
// Created by Marc Rousavy on 17.07.24.
//

import Foundation

@frozen
enum CoordinateSystem: String, JSUnionValue {
case previewView = "preview-view"
case camera = "camera"

init(jsValue: String) throws {
if let parsed = CoordinateSystem(rawValue: jsValue) {
self = parsed
} else {
throw CameraError.parameter(.invalid(unionName: "hardwareLevel", receivedValue: jsValue))
}
}

var jsValue: String {
return rawValue
}
}
9 changes: 8 additions & 1 deletion package/ios/React/CameraView+Focus.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import AVFoundation
import Foundation

extension CameraView {
func focus(point: CGPoint, promise: Promise) {
func focus(pointInPreviewView point: CGPoint, promise: Promise) {
withPromise(promise) {
guard let previewView = self.previewView else {
throw CameraError.capture(.focusRequiresPreview)
Expand All @@ -20,4 +20,11 @@ extension CameraView {
return nil
}
}

Check failure on line 23 in package/ios/React/CameraView+Focus.swift

View workflow job for this annotation

GitHub Actions / SwiftLint

Trailing Whitespace Violation: Lines should not have trailing whitespace (trailing_whitespace)
func focus(pointInCameraCoordinates point: CGPoint, promise: Promise) {
withPromise(promise) {
try cameraSession.focus(point: point)
return nil
}
}
}
25 changes: 21 additions & 4 deletions package/ios/React/CameraViewManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -86,14 +86,31 @@ final class CameraViewManager: RCTViewManager {
}

@objc
final func focus(_ node: NSNumber, point: NSDictionary, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
final func focus(_ node: NSNumber, focusOptions: NSDictionary, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
let promise = Promise(resolver: resolve, rejecter: reject)
guard let x = point["x"] as? NSNumber, let y = point["y"] as? NSNumber else {
promise.reject(error: .parameter(.invalid(unionName: "point", receivedValue: point.description)))

Check failure on line 91 in package/ios/React/CameraViewManager.swift

View workflow job for this annotation

GitHub Actions / SwiftLint

Trailing Whitespace Violation: Lines should not have trailing whitespace (trailing_whitespace)
guard let coordinateSystemString = focusOptions["coordinateSystem"] as? String,
let pointDictionary = focusOptions["point"] as? NSDictionary else {
promise.reject(error: .parameter(.invalid(unionName: "focusOptions", receivedValue: focusOptions.description)))
return
}
guard let x = pointDictionary["x"] as? NSNumber, let y = pointDictionary["y"] as? NSNumber else {
promise.reject(error: .parameter(.invalid(unionName: "focusOptions.point", receivedValue: pointDictionary.description)))
return
}
guard let coordinateSystem = try? CoordinateSystem(jsValue: coordinateSystemString) else {
promise.reject(error: .parameter(.invalid(unionName: "focusOptions.coordinateSystem", receivedValue: coordinateSystemString)))
return
}
let component = getCameraView(withTag: node)
component.focus(point: CGPoint(x: x.doubleValue, y: y.doubleValue), promise: promise)
let point = CGPoint(x: x.doubleValue, y: y.doubleValue)

Check failure on line 107 in package/ios/React/CameraViewManager.swift

View workflow job for this annotation

GitHub Actions / SwiftLint

Trailing Whitespace Violation: Lines should not have trailing whitespace (trailing_whitespace)
switch coordinateSystem {
case .previewView:
component.focus(pointInPreviewView: point, promise: promise)
case .camera:
component.focus(pointInCameraCoordinates: point, promise: promise)
}
}

@objc
Expand Down
29 changes: 27 additions & 2 deletions package/src/Camera.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,11 @@ export class Camera extends React.PureComponent<CameraProps, CameraState> {
return nodeHandle
}

private get enablePreviewView(): boolean {
const isRenderingWithSkia = isSkiaFrameProcessor(this.props.frameProcessor)
return isRenderingWithSkia ? false : this.props.preview ?? true
}

//#region View-specific functions (UIViewManager)
/**
* Take a single photo and write it's content to a temporary file.
Expand Down Expand Up @@ -385,7 +390,27 @@ export class Camera extends React.PureComponent<CameraProps, CameraState> {
*/
public async focus(point: Point): Promise<void> {
try {
return await CameraModule.focus(this.handle, point)
if (this.enablePreviewView) {
// Use Preview coordinate system
return await CameraModule.focus(this.handle, {
coordinateSystem: 'preview-view',
point: point,
})
} else {
// Use Camera-native coordinate system
const format = this.props.format
if (format == null) {
// TODO: Move this to native so it isn't required.
throw new Error('Format is required to focus without a Preview View!')
}
return await CameraModule.focus(this.handle, {
coordinateSystem: 'camera',
point: {
x: point.x / format.videoWidth,
y: point.y / format.videoHeight,
},
})
}
} catch (e) {
throw tryParseNativeCameraError(e)
}
Expand Down Expand Up @@ -669,7 +694,7 @@ export class Camera extends React.PureComponent<CameraProps, CameraState> {
codeScannerOptions={codeScanner}
enableFrameProcessor={frameProcessor != null}
enableBufferCompression={props.enableBufferCompression ?? shouldEnableBufferCompression}
preview={isRenderingWithSkia ? false : props.preview ?? true}>
preview={this.enablePreviewView}>
{isRenderingWithSkia && (
<SkiaCameraCanvas
style={styles.customPreviewView}
Expand Down

0 comments on commit add4f3e

Please sign in to comment.