Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions ios/ReactNativeCameraKit/CKCameraViewComponentView.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
//
// CKCameraViewComponentView.h
// ReactNativeCameraKit
//

#ifdef RCT_NEW_ARCH_ENABLED

#import <UIKit/UIKit.h>
Expand All @@ -8,6 +13,7 @@
NS_ASSUME_NONNULL_BEGIN

@interface CKCameraViewComponentView : RCTViewComponentView
- (facebook::react::SharedViewEventEmitter)eventEmitter;
@end

NS_ASSUME_NONNULL_END
Expand Down
68 changes: 18 additions & 50 deletions ios/ReactNativeCameraKit/CKCameraViewComponentView.mm
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
//
// CKCameraViewComponentView.h
// ReactNativeCameraKit
//

#ifdef RCT_NEW_ARCH_ENABLED

#import "CKCameraViewComponentView.h"

#import "NewArchCameraEventEmitter.h"

#import <React/RCTBridge+Private.h>
#import <React/RCTConversions.h>
#import <React/RCTFabricComponentsPlugins.h>
#import <folly/dynamic.h>

#import <react/renderer/components/rncamerakit_specs/ComponentDescriptors.h>
#import <react/renderer/components/rncamerakit_specs/EventEmitters.h>
#import <react/renderer/components/rncamerakit_specs/Props.h>
#import <react/renderer/components/rncamerakit_specs/RCTComponentViewHelpers.h>

Expand Down Expand Up @@ -64,6 +70,10 @@ @implementation CKCameraViewComponentView {
CKCameraView *_view;
}

- (facebook::react::SharedViewEventEmitter)eventEmitter {
return _eventEmitter;
}

// Needed because of this: https://github.com/facebook/react-native/pull/37274
+ (void)load
{
Expand All @@ -83,61 +93,19 @@ - (instancetype)initWithFrame:(CGRect)frame

- (void)prepareView
{
_view = [[CKCameraView alloc] init];

// just need to pass something, it won't really be used on fabric, but it's used to create events (it won't impact sending them)
_view = [[CKCameraView alloc] init];
_view.reactTag = @-1;

__weak __typeof__(self) weakSelf = self;

[_view setOnReadCode:^(NSDictionary* event) {
__typeof__(self) strongSelf = weakSelf;
_view.eventEmitter = [[NewArchCameraEventEmitter alloc] initWithCameraViewComponentView:self];

if (strongSelf != nullptr && strongSelf->_eventEmitter != nullptr) {
std::string codeStringValue = [event valueForKey:@"codeStringValue"] == nil ? "" : std::string([[event valueForKey:@"codeStringValue"] UTF8String]);
std::string codeFormat = [event valueForKey:@"codeFormat"] == nil ? "" : std::string([[event valueForKey:@"codeFormat"] UTF8String]);
std::dynamic_pointer_cast<const facebook::react::CKCameraEventEmitter>(strongSelf->_eventEmitter)->onReadCode({.codeStringValue = codeStringValue, .codeFormat = codeFormat});
}
}];
[_view setOnOrientationChange:^(NSDictionary* event) {
__typeof__(self) strongSelf = weakSelf;

if (strongSelf != nullptr && strongSelf->_eventEmitter != nullptr) {
id orientation = [event valueForKey:@"orientation"] == nil ? 0 : [event valueForKey:@"orientation"];
std::dynamic_pointer_cast<const facebook::react::CKCameraEventEmitter>(strongSelf->_eventEmitter)->onOrientationChange({.orientation = [orientation intValue]});
}
}];
[_view setOnZoom:^(NSDictionary* event) {
__typeof__(self) strongSelf = weakSelf;

if (strongSelf != nullptr && strongSelf->_eventEmitter != nullptr) {
id zoom = [event valueForKey:@"zoom"] == nil ? 0 : [event valueForKey:@"zoom"];
std::dynamic_pointer_cast<const facebook::react::CKCameraEventEmitter>(strongSelf->_eventEmitter)->onZoom({.zoom = [zoom doubleValue]});
}
}];
[_view setOnCaptureButtonPressIn:^(NSDictionary* event) {
__typeof__(self) strongSelf = weakSelf;

if (strongSelf != nullptr && strongSelf->_eventEmitter != nullptr) {
std::dynamic_pointer_cast<const facebook::react::CKCameraEventEmitter>(strongSelf->_eventEmitter)->onCaptureButtonPressIn({});
}
}];
[_view setOnCaptureButtonPressOut:^(NSDictionary* event) {
__typeof__(self) strongSelf = weakSelf;

if (strongSelf != nullptr && strongSelf->_eventEmitter != nullptr) {
std::dynamic_pointer_cast<const facebook::react::CKCameraEventEmitter>(strongSelf->_eventEmitter)->onCaptureButtonPressOut({});
}
}];

self.contentView = _view;
}

#pragma mark - RCTComponentViewProtocol

+ (ComponentDescriptorProvider)componentDescriptorProvider
{
return concreteComponentDescriptorProvider<CKCameraComponentDescriptor>();
return concreteComponentDescriptorProvider<CKCameraComponentDescriptor>();
}

- (void)updateLayoutMetrics:(const facebook::react::LayoutMetrics &)layoutMetrics oldLayoutMetrics:(const facebook::react::LayoutMetrics &)oldLayoutMetrics
Expand Down Expand Up @@ -218,17 +186,18 @@ - (void)updateProps:(const Props::Shared &)props oldProps:(const Props::Shared &
[changedProps addObject:@"resetFocusWhenMotionDetected"];
}
id focusMode = CKConvertFollyDynamicToId(newProps.focusMode);
if (focusMode != nil) {
if (focusMode != nil && ![focusMode isEqual: @""]) {
_view.focusMode = [focusMode isEqualToString:@"on"] ? CKFocusModeOn : CKFocusModeOff;
[changedProps addObject:@"focusMode"];
}
id zoomMode = CKConvertFollyDynamicToId(newProps.zoomMode);
if (zoomMode != nil) {
if (zoomMode != nil && ![zoomMode isEqual: @""]) {
_view.zoomMode = [zoomMode isEqualToString:@"on"] ? CKZoomModeOn : CKZoomModeOff;
[changedProps addObject:@"zoomMode"];
}
id zoom = CKConvertFollyDynamicToId(newProps.zoom);
if (zoom != nil) {
NSLog(@"Zoom received: %@", zoom);
_view.zoom = zoom;
[changedProps addObject:@"zoom"];
}
Expand All @@ -244,7 +213,6 @@ - (void)updateProps:(const Props::Shared &)props oldProps:(const Props::Shared &
[changedProps addObject:@"barcodeFrameSize"];
}


[super updateProps:props oldProps:oldProps];
[_view didSetProps:changedProps];
}
Expand All @@ -259,7 +227,7 @@ - (void)prepareForRecycle

Class<RCTComponentViewProtocol> CKCameraCls(void)
{
return CKCameraViewComponentView.class;
return CKCameraViewComponentView.class;
}

#endif // RCT_NEW_ARCH_ENABLED
55 changes: 55 additions & 0 deletions ios/ReactNativeCameraKit/CameraEventEmitter.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
//
// CameraEventEmitter.swift
// ReactNativeCameraKit
//

@objc public protocol CameraEventEmitter {
@objc func onReadCode(codeStringValue: String, codeFormat: String)
@objc func onOrientationChange(orientation: Int)
@objc func onZoom(zoom: Double)

@objc func onCaptureButtonPressIn()
@objc func onCaptureButtonPressOut()
}

class OldArchCameraEventEmitter: CameraEventEmitter {
var onReadCodeProp: RCTDirectEventBlock?
var onOrientationChangeProp: RCTDirectEventBlock?
var onZoomProp: RCTDirectEventBlock?
var onCaptureButtonPressInProp: RCTDirectEventBlock?
var onCaptureButtonPressOutProp: RCTDirectEventBlock?

Check warning on line 21 in ios/ReactNativeCameraKit/CameraEventEmitter.swift

View workflow job for this annotation

GitHub Actions / Lint iOS

Lines should not have trailing whitespace (trailing_whitespace)
init(onReadCodeProp: RCTDirectEventBlock?,
onOrientationChangeProp: RCTDirectEventBlock?,
onZoomProp: RCTDirectEventBlock?,
onCaptureButtonPressInProp: RCTDirectEventBlock?,
onCaptureButtonPressOutProp: RCTDirectEventBlock?) {
self.onReadCodeProp = onReadCodeProp
self.onOrientationChangeProp = onOrientationChangeProp
self.onZoomProp = onZoomProp
self.onCaptureButtonPressInProp = onCaptureButtonPressInProp
self.onCaptureButtonPressOutProp = onCaptureButtonPressOutProp
}

Check warning on line 33 in ios/ReactNativeCameraKit/CameraEventEmitter.swift

View workflow job for this annotation

GitHub Actions / Lint iOS

Lines should not have trailing whitespace (trailing_whitespace)
func onReadCode(codeStringValue: String, codeFormat: String) {
onReadCodeProp?(["codeStringValue": codeStringValue, "codeFormat": codeFormat])
}

Check warning on line 37 in ios/ReactNativeCameraKit/CameraEventEmitter.swift

View workflow job for this annotation

GitHub Actions / Lint iOS

Lines should not have trailing whitespace (trailing_whitespace)
func onOrientationChange(orientation: Int) {
onOrientationChangeProp?(["orientation": orientation])
}

Check warning on line 41 in ios/ReactNativeCameraKit/CameraEventEmitter.swift

View workflow job for this annotation

GitHub Actions / Lint iOS

Lines should not have trailing whitespace (trailing_whitespace)
func onZoom(zoom: Double) {
print("onZoom")
print(onZoomProp.debugDescription)
onZoomProp?(["zoom": zoom])
}

Check warning on line 47 in ios/ReactNativeCameraKit/CameraEventEmitter.swift

View workflow job for this annotation

GitHub Actions / Lint iOS

Lines should not have trailing whitespace (trailing_whitespace)
func onCaptureButtonPressIn() {
onCaptureButtonPressInProp?(nil)
}

Check warning on line 51 in ios/ReactNativeCameraKit/CameraEventEmitter.swift

View workflow job for this annotation

GitHub Actions / Lint iOS

Lines should not have trailing whitespace (trailing_whitespace)
func onCaptureButtonPressOut() {
onCaptureButtonPressOutProp?(nil)
}
}
4 changes: 2 additions & 2 deletions ios/ReactNativeCameraKit/CameraProtocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ protocol CameraProtocol: AnyObject, FocusInterfaceViewDelegate {
func setup(cameraType: CameraType, supportedBarcodeType: [CodeFormat])
func cameraRemovedFromSuperview()

func update(eventEmitter: CameraEventEmitter?)

func update(torchMode: TorchMode)
func update(flashMode: FlashMode)
func update(cameraType: CameraType)
func update(onOrientationChange: RCTDirectEventBlock?)
func update(onZoom: RCTDirectEventBlock?)
func update(zoom: Double?)
func update(maxZoom: Double?)
func update(resizeMode: ResizeMode)
Expand Down
51 changes: 31 additions & 20 deletions ios/ReactNativeCameraKit/CameraView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@
public class CameraView: UIView {
private let camera: CameraProtocol

// expose event native -> react
@objc public var eventEmitter: CameraEventEmitter? {
didSet {
camera.update(eventEmitter: eventEmitter)
}
}

// Focus
private let focusInterfaceView: FocusInterfaceView

Expand Down Expand Up @@ -44,26 +51,26 @@
// scanner
@objc public var scanBarcode = false
@objc public var showFrame = false
@objc public var onReadCode: RCTDirectEventBlock?
@objc public var scanThrottleDelay = 2000
@objc public var frameColor: UIColor?
@objc public var laserColor: UIColor?
@objc public var barcodeFrameSize: NSDictionary?

// other
@objc public var onOrientationChange: RCTDirectEventBlock?
@objc public var onZoom: RCTDirectEventBlock?
@objc public var resetFocusTimeout = 0
@objc public var resetFocusWhenMotionDetected = false
@objc public var focusMode: FocusMode = .on
@objc public var zoomMode: ZoomMode = .on
@objc public var zoom: NSNumber?
@objc public var maxZoom: NSNumber?

// callbacks (only defined for old architecture)
@objc public var onReadCode: RCTDirectEventBlock?
@objc public var onOrientationChange: RCTDirectEventBlock?
@objc public var onZoom: RCTDirectEventBlock?
@objc public var onCaptureButtonPressIn: RCTDirectEventBlock?
@objc public var onCaptureButtonPressOut: RCTDirectEventBlock?

// interaction on physical volume button
var eventInteraction: Any? = nil

Check warning on line 73 in ios/ReactNativeCameraKit/CameraView.swift

View workflow job for this annotation

GitHub Actions / Lint iOS

Initializing an optional variable with nil is redundant (redundant_optional_initialization)

// MARK: - Setup

Expand All @@ -84,9 +91,9 @@
hasCameraBeenSetup = true
#if targetEnvironment(macCatalyst)
// Force front camera on Mac Catalyst during initial setup
camera.setup(cameraType: .front, supportedBarcodeType: scanBarcode && onReadCode != nil ? supportedBarcodeType : [])
camera.setup(cameraType: .front, supportedBarcodeType: scanBarcode ? supportedBarcodeType : [])
#else
camera.setup(cameraType: cameraType, supportedBarcodeType: scanBarcode && onReadCode != nil ? supportedBarcodeType : [])
camera.setup(cameraType: cameraType, supportedBarcodeType: scanBarcode ? supportedBarcodeType : [])
#endif
}
}
Expand Down Expand Up @@ -153,13 +160,13 @@
let interaction = AVCaptureEventInteraction { [weak self] event in
// Capture a photo on "press up" of a hardware button.
if event.phase == .began {
self?.onCaptureButtonPressIn?(nil)
self?.eventEmitter?.onCaptureButtonPressIn()
} else if event.phase == .ended {
self?.onCaptureButtonPressOut?(nil)
self?.eventEmitter?.onCaptureButtonPressOut()
}
}
// Add the interaction to the view controller's view.
self.addInteraction(interaction)
addInteraction(interaction)
eventInteraction = interaction
}
#endif
Expand Down Expand Up @@ -200,6 +207,18 @@
override public func didSetProps(_ changedProps: [String]) {
hasPropBeenSetup = true

// Initialized here for old architecture, initialized in CKCameraViewComponentView for new architecture
if (eventEmitter == nil) {

Check warning on line 211 in ios/ReactNativeCameraKit/CameraView.swift

View workflow job for this annotation

GitHub Actions / Lint iOS

`if`, `for`, `guard`, `switch`, `while`, and `catch` statements shouldn't unnecessarily wrap their conditionals or arguments in parentheses (control_statement)
eventEmitter = OldArchCameraEventEmitter(
onReadCodeProp: onReadCode,
onOrientationChangeProp: onOrientationChange,
onZoomProp: onZoom,
onCaptureButtonPressInProp: onCaptureButtonPressIn,
onCaptureButtonPressOutProp: onCaptureButtonPressOut
)
camera.update(eventEmitter: eventEmitter)
}

// Camera settings
if changedProps.contains("cameraType") {
#if targetEnvironment(macCatalyst)
Expand All @@ -218,14 +237,6 @@
if changedProps.contains("maxPhotoQualityPrioritization") {
camera.update(maxPhotoQualityPrioritization: maxPhotoQualityPrioritization)
}

if changedProps.contains("onOrientationChange") {
camera.update(onOrientationChange: onOrientationChange)
}

if changedProps.contains("onZoom") {
camera.update(onZoom: onZoom)
}

if changedProps.contains("resizeMode") {
camera.update(resizeMode: resizeMode)
Expand All @@ -251,7 +262,7 @@
}

// Scanner
if changedProps.contains("scanBarcode") || changedProps.contains("onReadCode") {
if changedProps.contains("scanBarcode") || changedProps.contains("onReadCode") /* only old arch. */ {
camera.isBarcodeScannerEnabled(scanBarcode,
supportedBarcodeTypes: supportedBarcodeType,
onBarcodeRead: { [weak self] (barcode, codeFormat) in
Expand Down Expand Up @@ -427,7 +438,7 @@
return temporaryFileURL
}

private func onBarcodeRead(barcode: String, codeFormat:CodeFormat) {

Check warning on line 441 in ios/ReactNativeCameraKit/CameraView.swift

View workflow job for this annotation

GitHub Actions / Lint iOS

Colons should be next to the identifier when specifying a type and next to the key in dictionary literals (colon)
// Throttle barcode detection
let now = Date.timeIntervalSinceReferenceDate
guard lastBarcodeDetectedTime + Double(scanThrottleDelay) / 1000 < now else {
Expand All @@ -436,7 +447,7 @@

lastBarcodeDetectedTime = now

onReadCode?(["codeStringValue": barcode,"codeFormat":codeFormat.rawValue])
eventEmitter?.onReadCode(codeStringValue: barcode, codeFormat: codeFormat.rawValue)
}

// MARK: - Gesture selectors
Expand All @@ -449,4 +460,4 @@
camera.zoomPinchChange(pinchScale: pinchRecognizer.scale)
}
}
}

Check warning on line 463 in ios/ReactNativeCameraKit/CameraView.swift

View workflow job for this annotation

GitHub Actions / Lint iOS

File should contain 400 lines or less: currently contains 463 (file_length)
18 changes: 18 additions & 0 deletions ios/ReactNativeCameraKit/NewArchCameraEventEmitter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//
// NewArchCameraEventEmitter.h
// ReactNativeCameraKit
//

#ifdef RCT_NEW_ARCH_ENABLED

@class CKCameraViewComponentView;
@protocol CameraEventEmitter;

/* This unfortunately needs to be in ObjectiveC since it's using C++ implementation */
@interface NewArchCameraEventEmitter : NSObject <CameraEventEmitter>

- (instancetype)initWithCameraViewComponentView:(CKCameraViewComponentView *)viewComponentView;

@end

#endif // RCT_NEW_ARCH_ENABLED
Loading
Loading