From bda43d39846f2a874233e8882f133c4be417ef36 Mon Sep 17 00:00:00 2001 From: Marc Rousavy Date: Fri, 16 Feb 2024 13:46:13 +0100 Subject: [PATCH] fix: Fix nullable props (#2573) * fix: Fix nullable props * Update CameraView.kt * Pass error to JS --- .../java/com/mrousavy/camera/CameraView.kt | 31 +++---- .../com/mrousavy/camera/CameraViewManager.kt | 81 ++++++++++++------- .../com/mrousavy/camera/core/VideoPipeline.kt | 4 +- .../camera/types/CodeScannerOptions.kt | 20 ++--- .../com/mrousavy/camera/types/ResizeMode.kt | 4 +- package/example/ios/Podfile.lock | 6 +- package/src/CameraProps.ts | 1 + 7 files changed, 80 insertions(+), 67 deletions(-) diff --git a/package/android/src/main/java/com/mrousavy/camera/CameraView.kt b/package/android/src/main/java/com/mrousavy/camera/CameraView.kt index 12bffc7..bbff079 100644 --- a/package/android/src/main/java/com/mrousavy/camera/CameraView.kt +++ b/package/android/src/main/java/com/mrousavy/camera/CameraView.kt @@ -7,7 +7,6 @@ import android.util.Log import android.view.Gravity import android.view.ScaleGestureDetector import android.widget.FrameLayout -import com.facebook.react.bridge.ReadableMap import com.google.mlkit.vision.barcode.common.Barcode import com.mrousavy.camera.core.CameraConfiguration import com.mrousavy.camera.core.CameraQueues @@ -48,24 +47,23 @@ class CameraView(context: Context) : // props that require reconfiguring var cameraId: String? = null var enableDepthData = false - var enableHighQualityPhotos: Boolean? = null var enablePortraitEffectsMatteDelivery = false // use-cases - var photo: Boolean? = null - var video: Boolean? = null - var audio: Boolean? = null + var photo = false + var video = false + var audio = false var enableFrameProcessor = false var pixelFormat: PixelFormat = PixelFormat.NATIVE // props that require format reconfiguring - var format: ReadableMap? = null + var format: CameraDeviceFormat? = null var fps: Int? = null var videoStabilizationMode: VideoStabilizationMode? = null var videoHdr = false var photoHdr = false - var lowLightBoost: Boolean? = null // nullable bool - var enableGpuBuffers: Boolean = false + var lowLightBoost = false + var enableGpuBuffers = false // other props var isActive = false @@ -73,7 +71,7 @@ class CameraView(context: Context) : var zoom: Float = 1f // in "factor" var exposure: Double = 1.0 var orientation: Orientation = Orientation.PORTRAIT - var enableZoomGesture: Boolean = false + var enableZoomGesture = false set(value) { field = value updateZoomGesture() @@ -83,7 +81,7 @@ class CameraView(context: Context) : previewView.resizeMode = value field = value } - var enableFpsGraph: Boolean = false + var enableFpsGraph = false set(value) { field = value updateFpsGraph() @@ -155,14 +153,14 @@ class CameraView(context: Context) : config.cameraId = cameraId // Photo - if (photo == true) { + if (photo) { config.photo = CameraConfiguration.Output.Enabled.create(CameraConfiguration.Photo(photoHdr)) } else { config.photo = CameraConfiguration.Output.Disabled.create() } // Video/Frame Processor - if (video == true || enableFrameProcessor) { + if (video || enableFrameProcessor) { config.video = CameraConfiguration.Output.Enabled.create( CameraConfiguration.Video( videoHdr, @@ -176,7 +174,7 @@ class CameraView(context: Context) : } // Audio - if (audio == true) { + if (audio) { config.audio = CameraConfiguration.Output.Enabled.create(CameraConfiguration.Audio(Unit)) } else { config.audio = CameraConfiguration.Output.Disabled.create() @@ -196,12 +194,7 @@ class CameraView(context: Context) : config.orientation = orientation // Format - val format = format - if (format != null) { - config.format = CameraDeviceFormat.fromJSValue(format) - } else { - config.format = null - } + config.format = format // Side-Props config.fps = fps diff --git a/package/android/src/main/java/com/mrousavy/camera/CameraViewManager.kt b/package/android/src/main/java/com/mrousavy/camera/CameraViewManager.kt index ab047d7..9d67dfd 100644 --- a/package/android/src/main/java/com/mrousavy/camera/CameraViewManager.kt +++ b/package/android/src/main/java/com/mrousavy/camera/CameraViewManager.kt @@ -5,6 +5,7 @@ import com.facebook.react.common.MapBuilder import com.facebook.react.uimanager.ThemedReactContext import com.facebook.react.uimanager.ViewGroupManager import com.facebook.react.uimanager.annotations.ReactProp +import com.mrousavy.camera.types.CameraDeviceFormat import com.mrousavy.camera.types.CodeScannerOptions import com.mrousavy.camera.types.Orientation import com.mrousavy.camera.types.PixelFormat @@ -44,17 +45,17 @@ class CameraViewManager : ViewGroupManager() { } @ReactProp(name = "photo") - fun setPhoto(view: CameraView, photo: Boolean?) { + fun setPhoto(view: CameraView, photo: Boolean) { view.photo = photo } @ReactProp(name = "video") - fun setVideo(view: CameraView, video: Boolean?) { + fun setVideo(view: CameraView, video: Boolean) { view.video = video } @ReactProp(name = "audio") - fun setAudio(view: CameraView, audio: Boolean?) { + fun setAudio(view: CameraView, audio: Boolean) { view.audio = audio } @@ -65,8 +66,12 @@ class CameraViewManager : ViewGroupManager() { @ReactProp(name = "pixelFormat") fun setPixelFormat(view: CameraView, pixelFormat: String?) { - val newPixelFormat = PixelFormat.fromUnionValue(pixelFormat) - view.pixelFormat = newPixelFormat + if (pixelFormat != null) { + val newPixelFormat = PixelFormat.fromUnionValue(pixelFormat) + view.pixelFormat = newPixelFormat + } else { + view.pixelFormat = PixelFormat.NATIVE + } } @ReactProp(name = "enableDepthData") @@ -91,13 +96,12 @@ class CameraViewManager : ViewGroupManager() { @ReactProp(name = "videoStabilizationMode") fun setVideoStabilizationMode(view: CameraView, videoStabilizationMode: String?) { - val newMode = VideoStabilizationMode.fromUnionValue(videoStabilizationMode) - view.videoStabilizationMode = newMode - } - - @ReactProp(name = "enableHighQualityPhotos") - fun setEnableHighQualityPhotos(view: CameraView, enableHighQualityPhotos: Boolean?) { - view.enableHighQualityPhotos = enableHighQualityPhotos + if (videoStabilizationMode != null) { + val newMode = VideoStabilizationMode.fromUnionValue(videoStabilizationMode) + view.videoStabilizationMode = newMode + } else { + view.videoStabilizationMode = null + } } @ReactProp(name = "enablePortraitEffectsMatteDelivery") @@ -107,13 +111,22 @@ class CameraViewManager : ViewGroupManager() { @ReactProp(name = "format") fun setFormat(view: CameraView, format: ReadableMap?) { - view.format = format + if (format != null) { + val newFormat = CameraDeviceFormat.fromJSValue(format) + view.format = newFormat + } else { + view.format = null + } } @ReactProp(name = "resizeMode") - fun setResizeMode(view: CameraView, resizeMode: String) { - val newMode = ResizeMode.fromUnionValue(resizeMode) - view.resizeMode = newMode + fun setResizeMode(view: CameraView, resizeMode: String?) { + if (resizeMode != null) { + val newMode = ResizeMode.fromUnionValue(resizeMode) + view.resizeMode = newMode + } else { + view.resizeMode = ResizeMode.COVER + } } // TODO: Change when TurboModules release. @@ -124,30 +137,34 @@ class CameraViewManager : ViewGroupManager() { view.fps = if (fps > 0) fps else null } - @ReactProp(name = "photoHdr", defaultBoolean = false) + @ReactProp(name = "photoHdr") fun setPhotoHdr(view: CameraView, photoHdr: Boolean) { view.photoHdr = photoHdr } - @ReactProp(name = "videoHdr", defaultBoolean = false) + @ReactProp(name = "videoHdr") fun setVideoHdr(view: CameraView, videoHdr: Boolean) { view.videoHdr = videoHdr } @ReactProp(name = "lowLightBoost") - fun setLowLightBoost(view: CameraView, lowLightBoost: Boolean?) { + fun setLowLightBoost(view: CameraView, lowLightBoost: Boolean) { view.lowLightBoost = lowLightBoost } - @ReactProp(name = "isActive", defaultBoolean = false) + @ReactProp(name = "isActive") fun setIsActive(view: CameraView, isActive: Boolean) { view.isActive = isActive } @ReactProp(name = "torch") - fun setTorch(view: CameraView, torch: String) { - val newMode = Torch.fromUnionValue(torch) - view.torch = newMode + fun setTorch(view: CameraView, torch: String?) { + if (torch != null) { + val newMode = Torch.fromUnionValue(torch) + view.torch = newMode + } else { + view.torch = Torch.OFF + } } @ReactProp(name = "zoom") @@ -162,14 +179,22 @@ class CameraViewManager : ViewGroupManager() { @ReactProp(name = "orientation") fun setOrientation(view: CameraView, orientation: String?) { - val newMode = Orientation.fromUnionValue(orientation) - view.orientation = newMode + if (orientation != null) { + val newMode = Orientation.fromUnionValue(orientation) + view.orientation = newMode + } else { + view.orientation = Orientation.PORTRAIT + } } @ReactProp(name = "codeScannerOptions") - fun setCodeScanner(view: CameraView, codeScannerOptions: ReadableMap) { - val newCodeScannerOptions = CodeScannerOptions(codeScannerOptions) - view.codeScannerOptions = newCodeScannerOptions + fun setCodeScanner(view: CameraView, codeScannerOptions: ReadableMap?) { + if (codeScannerOptions != null) { + val newCodeScannerOptions = CodeScannerOptions.fromJSValue(codeScannerOptions) + view.codeScannerOptions = newCodeScannerOptions + } else { + view.codeScannerOptions = null + } } companion object { diff --git a/package/android/src/main/java/com/mrousavy/camera/core/VideoPipeline.kt b/package/android/src/main/java/com/mrousavy/camera/core/VideoPipeline.kt index ae2c107..f46ad2b 100644 --- a/package/android/src/main/java/com/mrousavy/camera/core/VideoPipeline.kt +++ b/package/android/src/main/java/com/mrousavy/camera/core/VideoPipeline.kt @@ -33,7 +33,7 @@ class VideoPipeline( val format: PixelFormat = PixelFormat.NATIVE, private val isMirrored: Boolean = false, private val enableFrameProcessor: Boolean = false, - private val enableGpuBuffers: Boolean = false, + enableGpuBuffers: Boolean = false, private val callback: CameraSession.Callback ) : SurfaceTexture.OnFrameAvailableListener, Closeable { @@ -116,7 +116,7 @@ class VideoPipeline( } } catch (e: Throwable) { Log.e(TAG, "FrameProcessor/ImageReader pipeline threw an error!", e) - throw e + callback.onError(e) } finally { frame.decrementRefCount() } diff --git a/package/android/src/main/java/com/mrousavy/camera/types/CodeScannerOptions.kt b/package/android/src/main/java/com/mrousavy/camera/types/CodeScannerOptions.kt index ee47657..618f4aa 100644 --- a/package/android/src/main/java/com/mrousavy/camera/types/CodeScannerOptions.kt +++ b/package/android/src/main/java/com/mrousavy/camera/types/CodeScannerOptions.kt @@ -3,20 +3,12 @@ package com.mrousavy.camera.types import com.facebook.react.bridge.ReadableMap import com.mrousavy.camera.core.InvalidTypeScriptUnionError -class CodeScannerOptions(map: ReadableMap) { - val codeTypes: List - - init { - val codeTypes = map.getArray("codeTypes")?.toArrayList() ?: throw InvalidTypeScriptUnionError("codeScanner", map.toString()) - this.codeTypes = codeTypes.map { - return@map CodeType.fromUnionValue(it as String) +data class CodeScannerOptions(val codeTypes: List) { + companion object { + fun fromJSValue(value: ReadableMap): CodeScannerOptions { + val jsCodeTypes = value.getArray("codeTypes") ?: throw InvalidTypeScriptUnionError("codeScanner", value.toString()) + val codeTypes = jsCodeTypes.toArrayList().map { CodeType.fromUnionValue(it as String) } + return CodeScannerOptions(codeTypes) } } - - override fun equals(other: Any?): Boolean { - if (other !is CodeScannerOptions) return false - return codeTypes.size == other.codeTypes.size && codeTypes.containsAll(other.codeTypes) - } - - override fun hashCode(): Int = codeTypes.hashCode() } diff --git a/package/android/src/main/java/com/mrousavy/camera/types/ResizeMode.kt b/package/android/src/main/java/com/mrousavy/camera/types/ResizeMode.kt index b3fa76d..8d03d17 100644 --- a/package/android/src/main/java/com/mrousavy/camera/types/ResizeMode.kt +++ b/package/android/src/main/java/com/mrousavy/camera/types/ResizeMode.kt @@ -1,5 +1,7 @@ package com.mrousavy.camera.types +import com.mrousavy.camera.core.InvalidTypeScriptUnionError + enum class ResizeMode(override val unionValue: String) : JSUnionValue { COVER("cover"), CONTAIN("contain"); @@ -9,7 +11,7 @@ enum class ResizeMode(override val unionValue: String) : JSUnionValue { when (unionValue) { "cover" -> COVER "contain" -> CONTAIN - else -> COVER + else -> throw InvalidTypeScriptUnionError("resizeMode", unionValue) } } } diff --git a/package/example/ios/Podfile.lock b/package/example/ios/Podfile.lock index cc03551..34be125 100644 --- a/package/example/ios/Podfile.lock +++ b/package/example/ios/Podfile.lock @@ -484,7 +484,7 @@ PODS: - libwebp (~> 1.0) - SDWebImage/Core (~> 5.10) - SocketRocket (0.6.1) - - VisionCamera (3.9.0-beta.3): + - VisionCamera (3.9.0-beta.6): - React - React-callinvoker - React-Core @@ -724,9 +724,9 @@ SPEC CHECKSUMS: SDWebImage: a7f831e1a65eb5e285e3fb046a23fcfbf08e696d SDWebImageWebPCoder: 908b83b6adda48effe7667cd2b7f78c897e5111d SocketRocket: f32cd54efbe0f095c4d7594881e52619cfe80b17 - VisionCamera: 666b0baa70060c0a472b30fc6d3a37f77e40fa9c + VisionCamera: 33c90675adf75528199f840f81dfbe74a2fe6c3f Yoga: 4c3aa327e4a6a23eeacd71f61c81df1bcdf677d5 PODFILE CHECKSUM: 27f53791141a3303d814e09b55770336416ff4eb -COCOAPODS: 1.11.3 +COCOAPODS: 1.14.3 diff --git a/package/src/CameraProps.ts b/package/src/CameraProps.ts index e264cb3..eea1fdd 100644 --- a/package/src/CameraProps.ts +++ b/package/src/CameraProps.ts @@ -246,6 +246,7 @@ export interface CameraProps extends ViewProps { * * Dual Device fusion for greater detail ([`isDualCameraDualPhotoDeliveryEnabled`](https://developer.apple.com/documentation/avfoundation/avcapturephotosettings/2873917-isdualcameradualphotodeliveryena)) * * Sets the maximum quality prioritization to `.quality` ([`maxPhotoQualityPrioritization`](https://developer.apple.com/documentation/avfoundation/avcapturephotooutput/3182995-maxphotoqualityprioritization)) * + * @platform iOS * @default false */ enableHighQualityPhotos?: boolean