fix: Fix nullable props (#2573)

* fix: Fix nullable props

* Update CameraView.kt

* Pass error to JS
This commit is contained in:
Marc Rousavy 2024-02-16 13:46:13 +01:00 committed by GitHub
parent b105de0194
commit bda43d3984
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 80 additions and 67 deletions

View File

@ -7,7 +7,6 @@ import android.util.Log
import android.view.Gravity import android.view.Gravity
import android.view.ScaleGestureDetector import android.view.ScaleGestureDetector
import android.widget.FrameLayout import android.widget.FrameLayout
import com.facebook.react.bridge.ReadableMap
import com.google.mlkit.vision.barcode.common.Barcode import com.google.mlkit.vision.barcode.common.Barcode
import com.mrousavy.camera.core.CameraConfiguration import com.mrousavy.camera.core.CameraConfiguration
import com.mrousavy.camera.core.CameraQueues import com.mrousavy.camera.core.CameraQueues
@ -48,24 +47,23 @@ class CameraView(context: Context) :
// props that require reconfiguring // props that require reconfiguring
var cameraId: String? = null var cameraId: String? = null
var enableDepthData = false var enableDepthData = false
var enableHighQualityPhotos: Boolean? = null
var enablePortraitEffectsMatteDelivery = false var enablePortraitEffectsMatteDelivery = false
// use-cases // use-cases
var photo: Boolean? = null var photo = false
var video: Boolean? = null var video = false
var audio: Boolean? = null var audio = false
var enableFrameProcessor = false var enableFrameProcessor = false
var pixelFormat: PixelFormat = PixelFormat.NATIVE var pixelFormat: PixelFormat = PixelFormat.NATIVE
// props that require format reconfiguring // props that require format reconfiguring
var format: ReadableMap? = null var format: CameraDeviceFormat? = null
var fps: Int? = null var fps: Int? = null
var videoStabilizationMode: VideoStabilizationMode? = null var videoStabilizationMode: VideoStabilizationMode? = null
var videoHdr = false var videoHdr = false
var photoHdr = false var photoHdr = false
var lowLightBoost: Boolean? = null // nullable bool var lowLightBoost = false
var enableGpuBuffers: Boolean = false var enableGpuBuffers = false
// other props // other props
var isActive = false var isActive = false
@ -73,7 +71,7 @@ class CameraView(context: Context) :
var zoom: Float = 1f // in "factor" var zoom: Float = 1f // in "factor"
var exposure: Double = 1.0 var exposure: Double = 1.0
var orientation: Orientation = Orientation.PORTRAIT var orientation: Orientation = Orientation.PORTRAIT
var enableZoomGesture: Boolean = false var enableZoomGesture = false
set(value) { set(value) {
field = value field = value
updateZoomGesture() updateZoomGesture()
@ -83,7 +81,7 @@ class CameraView(context: Context) :
previewView.resizeMode = value previewView.resizeMode = value
field = value field = value
} }
var enableFpsGraph: Boolean = false var enableFpsGraph = false
set(value) { set(value) {
field = value field = value
updateFpsGraph() updateFpsGraph()
@ -155,14 +153,14 @@ class CameraView(context: Context) :
config.cameraId = cameraId config.cameraId = cameraId
// Photo // Photo
if (photo == true) { if (photo) {
config.photo = CameraConfiguration.Output.Enabled.create(CameraConfiguration.Photo(photoHdr)) config.photo = CameraConfiguration.Output.Enabled.create(CameraConfiguration.Photo(photoHdr))
} else { } else {
config.photo = CameraConfiguration.Output.Disabled.create() config.photo = CameraConfiguration.Output.Disabled.create()
} }
// Video/Frame Processor // Video/Frame Processor
if (video == true || enableFrameProcessor) { if (video || enableFrameProcessor) {
config.video = CameraConfiguration.Output.Enabled.create( config.video = CameraConfiguration.Output.Enabled.create(
CameraConfiguration.Video( CameraConfiguration.Video(
videoHdr, videoHdr,
@ -176,7 +174,7 @@ class CameraView(context: Context) :
} }
// Audio // Audio
if (audio == true) { if (audio) {
config.audio = CameraConfiguration.Output.Enabled.create(CameraConfiguration.Audio(Unit)) config.audio = CameraConfiguration.Output.Enabled.create(CameraConfiguration.Audio(Unit))
} else { } else {
config.audio = CameraConfiguration.Output.Disabled.create() config.audio = CameraConfiguration.Output.Disabled.create()
@ -196,12 +194,7 @@ class CameraView(context: Context) :
config.orientation = orientation config.orientation = orientation
// Format // Format
val format = format config.format = format
if (format != null) {
config.format = CameraDeviceFormat.fromJSValue(format)
} else {
config.format = null
}
// Side-Props // Side-Props
config.fps = fps config.fps = fps

View File

@ -5,6 +5,7 @@ import com.facebook.react.common.MapBuilder
import com.facebook.react.uimanager.ThemedReactContext import com.facebook.react.uimanager.ThemedReactContext
import com.facebook.react.uimanager.ViewGroupManager import com.facebook.react.uimanager.ViewGroupManager
import com.facebook.react.uimanager.annotations.ReactProp import com.facebook.react.uimanager.annotations.ReactProp
import com.mrousavy.camera.types.CameraDeviceFormat
import com.mrousavy.camera.types.CodeScannerOptions import com.mrousavy.camera.types.CodeScannerOptions
import com.mrousavy.camera.types.Orientation import com.mrousavy.camera.types.Orientation
import com.mrousavy.camera.types.PixelFormat import com.mrousavy.camera.types.PixelFormat
@ -44,17 +45,17 @@ class CameraViewManager : ViewGroupManager<CameraView>() {
} }
@ReactProp(name = "photo") @ReactProp(name = "photo")
fun setPhoto(view: CameraView, photo: Boolean?) { fun setPhoto(view: CameraView, photo: Boolean) {
view.photo = photo view.photo = photo
} }
@ReactProp(name = "video") @ReactProp(name = "video")
fun setVideo(view: CameraView, video: Boolean?) { fun setVideo(view: CameraView, video: Boolean) {
view.video = video view.video = video
} }
@ReactProp(name = "audio") @ReactProp(name = "audio")
fun setAudio(view: CameraView, audio: Boolean?) { fun setAudio(view: CameraView, audio: Boolean) {
view.audio = audio view.audio = audio
} }
@ -65,8 +66,12 @@ class CameraViewManager : ViewGroupManager<CameraView>() {
@ReactProp(name = "pixelFormat") @ReactProp(name = "pixelFormat")
fun setPixelFormat(view: CameraView, pixelFormat: String?) { fun setPixelFormat(view: CameraView, pixelFormat: String?) {
val newPixelFormat = PixelFormat.fromUnionValue(pixelFormat) if (pixelFormat != null) {
view.pixelFormat = newPixelFormat val newPixelFormat = PixelFormat.fromUnionValue(pixelFormat)
view.pixelFormat = newPixelFormat
} else {
view.pixelFormat = PixelFormat.NATIVE
}
} }
@ReactProp(name = "enableDepthData") @ReactProp(name = "enableDepthData")
@ -91,13 +96,12 @@ class CameraViewManager : ViewGroupManager<CameraView>() {
@ReactProp(name = "videoStabilizationMode") @ReactProp(name = "videoStabilizationMode")
fun setVideoStabilizationMode(view: CameraView, videoStabilizationMode: String?) { fun setVideoStabilizationMode(view: CameraView, videoStabilizationMode: String?) {
val newMode = VideoStabilizationMode.fromUnionValue(videoStabilizationMode) if (videoStabilizationMode != null) {
view.videoStabilizationMode = newMode val newMode = VideoStabilizationMode.fromUnionValue(videoStabilizationMode)
} view.videoStabilizationMode = newMode
} else {
@ReactProp(name = "enableHighQualityPhotos") view.videoStabilizationMode = null
fun setEnableHighQualityPhotos(view: CameraView, enableHighQualityPhotos: Boolean?) { }
view.enableHighQualityPhotos = enableHighQualityPhotos
} }
@ReactProp(name = "enablePortraitEffectsMatteDelivery") @ReactProp(name = "enablePortraitEffectsMatteDelivery")
@ -107,13 +111,22 @@ class CameraViewManager : ViewGroupManager<CameraView>() {
@ReactProp(name = "format") @ReactProp(name = "format")
fun setFormat(view: CameraView, format: ReadableMap?) { 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") @ReactProp(name = "resizeMode")
fun setResizeMode(view: CameraView, resizeMode: String) { fun setResizeMode(view: CameraView, resizeMode: String?) {
val newMode = ResizeMode.fromUnionValue(resizeMode) if (resizeMode != null) {
view.resizeMode = newMode val newMode = ResizeMode.fromUnionValue(resizeMode)
view.resizeMode = newMode
} else {
view.resizeMode = ResizeMode.COVER
}
} }
// TODO: Change when TurboModules release. // TODO: Change when TurboModules release.
@ -124,30 +137,34 @@ class CameraViewManager : ViewGroupManager<CameraView>() {
view.fps = if (fps > 0) fps else null view.fps = if (fps > 0) fps else null
} }
@ReactProp(name = "photoHdr", defaultBoolean = false) @ReactProp(name = "photoHdr")
fun setPhotoHdr(view: CameraView, photoHdr: Boolean) { fun setPhotoHdr(view: CameraView, photoHdr: Boolean) {
view.photoHdr = photoHdr view.photoHdr = photoHdr
} }
@ReactProp(name = "videoHdr", defaultBoolean = false) @ReactProp(name = "videoHdr")
fun setVideoHdr(view: CameraView, videoHdr: Boolean) { fun setVideoHdr(view: CameraView, videoHdr: Boolean) {
view.videoHdr = videoHdr view.videoHdr = videoHdr
} }
@ReactProp(name = "lowLightBoost") @ReactProp(name = "lowLightBoost")
fun setLowLightBoost(view: CameraView, lowLightBoost: Boolean?) { fun setLowLightBoost(view: CameraView, lowLightBoost: Boolean) {
view.lowLightBoost = lowLightBoost view.lowLightBoost = lowLightBoost
} }
@ReactProp(name = "isActive", defaultBoolean = false) @ReactProp(name = "isActive")
fun setIsActive(view: CameraView, isActive: Boolean) { fun setIsActive(view: CameraView, isActive: Boolean) {
view.isActive = isActive view.isActive = isActive
} }
@ReactProp(name = "torch") @ReactProp(name = "torch")
fun setTorch(view: CameraView, torch: String) { fun setTorch(view: CameraView, torch: String?) {
val newMode = Torch.fromUnionValue(torch) if (torch != null) {
view.torch = newMode val newMode = Torch.fromUnionValue(torch)
view.torch = newMode
} else {
view.torch = Torch.OFF
}
} }
@ReactProp(name = "zoom") @ReactProp(name = "zoom")
@ -162,14 +179,22 @@ class CameraViewManager : ViewGroupManager<CameraView>() {
@ReactProp(name = "orientation") @ReactProp(name = "orientation")
fun setOrientation(view: CameraView, orientation: String?) { fun setOrientation(view: CameraView, orientation: String?) {
val newMode = Orientation.fromUnionValue(orientation) if (orientation != null) {
view.orientation = newMode val newMode = Orientation.fromUnionValue(orientation)
view.orientation = newMode
} else {
view.orientation = Orientation.PORTRAIT
}
} }
@ReactProp(name = "codeScannerOptions") @ReactProp(name = "codeScannerOptions")
fun setCodeScanner(view: CameraView, codeScannerOptions: ReadableMap) { fun setCodeScanner(view: CameraView, codeScannerOptions: ReadableMap?) {
val newCodeScannerOptions = CodeScannerOptions(codeScannerOptions) if (codeScannerOptions != null) {
view.codeScannerOptions = newCodeScannerOptions val newCodeScannerOptions = CodeScannerOptions.fromJSValue(codeScannerOptions)
view.codeScannerOptions = newCodeScannerOptions
} else {
view.codeScannerOptions = null
}
} }
companion object { companion object {

View File

@ -33,7 +33,7 @@ class VideoPipeline(
val format: PixelFormat = PixelFormat.NATIVE, val format: PixelFormat = PixelFormat.NATIVE,
private val isMirrored: Boolean = false, private val isMirrored: Boolean = false,
private val enableFrameProcessor: Boolean = false, private val enableFrameProcessor: Boolean = false,
private val enableGpuBuffers: Boolean = false, enableGpuBuffers: Boolean = false,
private val callback: CameraSession.Callback private val callback: CameraSession.Callback
) : SurfaceTexture.OnFrameAvailableListener, ) : SurfaceTexture.OnFrameAvailableListener,
Closeable { Closeable {
@ -116,7 +116,7 @@ class VideoPipeline(
} }
} catch (e: Throwable) { } catch (e: Throwable) {
Log.e(TAG, "FrameProcessor/ImageReader pipeline threw an error!", e) Log.e(TAG, "FrameProcessor/ImageReader pipeline threw an error!", e)
throw e callback.onError(e)
} finally { } finally {
frame.decrementRefCount() frame.decrementRefCount()
} }

View File

@ -3,20 +3,12 @@ package com.mrousavy.camera.types
import com.facebook.react.bridge.ReadableMap import com.facebook.react.bridge.ReadableMap
import com.mrousavy.camera.core.InvalidTypeScriptUnionError import com.mrousavy.camera.core.InvalidTypeScriptUnionError
class CodeScannerOptions(map: ReadableMap) { data class CodeScannerOptions(val codeTypes: List<CodeType>) {
val codeTypes: List<CodeType> companion object {
fun fromJSValue(value: ReadableMap): CodeScannerOptions {
init { val jsCodeTypes = value.getArray("codeTypes") ?: throw InvalidTypeScriptUnionError("codeScanner", value.toString())
val codeTypes = map.getArray("codeTypes")?.toArrayList() ?: throw InvalidTypeScriptUnionError("codeScanner", map.toString()) val codeTypes = jsCodeTypes.toArrayList().map { CodeType.fromUnionValue(it as String) }
this.codeTypes = codeTypes.map { return CodeScannerOptions(codeTypes)
return@map CodeType.fromUnionValue(it as String)
} }
} }
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()
} }

View File

@ -1,5 +1,7 @@
package com.mrousavy.camera.types package com.mrousavy.camera.types
import com.mrousavy.camera.core.InvalidTypeScriptUnionError
enum class ResizeMode(override val unionValue: String) : JSUnionValue { enum class ResizeMode(override val unionValue: String) : JSUnionValue {
COVER("cover"), COVER("cover"),
CONTAIN("contain"); CONTAIN("contain");
@ -9,7 +11,7 @@ enum class ResizeMode(override val unionValue: String) : JSUnionValue {
when (unionValue) { when (unionValue) {
"cover" -> COVER "cover" -> COVER
"contain" -> CONTAIN "contain" -> CONTAIN
else -> COVER else -> throw InvalidTypeScriptUnionError("resizeMode", unionValue)
} }
} }
} }

View File

@ -484,7 +484,7 @@ PODS:
- libwebp (~> 1.0) - libwebp (~> 1.0)
- SDWebImage/Core (~> 5.10) - SDWebImage/Core (~> 5.10)
- SocketRocket (0.6.1) - SocketRocket (0.6.1)
- VisionCamera (3.9.0-beta.3): - VisionCamera (3.9.0-beta.6):
- React - React
- React-callinvoker - React-callinvoker
- React-Core - React-Core
@ -724,9 +724,9 @@ SPEC CHECKSUMS:
SDWebImage: a7f831e1a65eb5e285e3fb046a23fcfbf08e696d SDWebImage: a7f831e1a65eb5e285e3fb046a23fcfbf08e696d
SDWebImageWebPCoder: 908b83b6adda48effe7667cd2b7f78c897e5111d SDWebImageWebPCoder: 908b83b6adda48effe7667cd2b7f78c897e5111d
SocketRocket: f32cd54efbe0f095c4d7594881e52619cfe80b17 SocketRocket: f32cd54efbe0f095c4d7594881e52619cfe80b17
VisionCamera: 666b0baa70060c0a472b30fc6d3a37f77e40fa9c VisionCamera: 33c90675adf75528199f840f81dfbe74a2fe6c3f
Yoga: 4c3aa327e4a6a23eeacd71f61c81df1bcdf677d5 Yoga: 4c3aa327e4a6a23eeacd71f61c81df1bcdf677d5
PODFILE CHECKSUM: 27f53791141a3303d814e09b55770336416ff4eb PODFILE CHECKSUM: 27f53791141a3303d814e09b55770336416ff4eb
COCOAPODS: 1.11.3 COCOAPODS: 1.14.3

View File

@ -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)) * * 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)) * * Sets the maximum quality prioritization to `.quality` ([`maxPhotoQualityPrioritization`](https://developer.apple.com/documentation/avfoundation/avcapturephotooutput/3182995-maxphotoqualityprioritization))
* *
* @platform iOS
* @default false * @default false
*/ */
enableHighQualityPhotos?: boolean enableHighQualityPhotos?: boolean