fix: Fix torch not staying on while recording (#2249)

* fix: Fix `zoom` on native gesture

* fix: Control `torch` from JS side

* Update CameraView+RecordVideo.kt

* Update CameraView+Zoom.swift
This commit is contained in:
Marc Rousavy 2023-12-04 13:43:17 +03:00 committed by GitHub
parent d78d3ea214
commit a5e10a8606
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 26 additions and 39 deletions

View File

@ -9,9 +9,7 @@ import com.mrousavy.camera.core.MicrophonePermissionError
import com.mrousavy.camera.core.RecorderError import com.mrousavy.camera.core.RecorderError
import com.mrousavy.camera.core.RecordingSession import com.mrousavy.camera.core.RecordingSession
import com.mrousavy.camera.core.code import com.mrousavy.camera.core.code
import com.mrousavy.camera.types.Flash
import com.mrousavy.camera.types.RecordVideoOptions import com.mrousavy.camera.types.RecordVideoOptions
import com.mrousavy.camera.types.Torch
import com.mrousavy.camera.utils.makeErrorMap import com.mrousavy.camera.utils.makeErrorMap
import java.util.* import java.util.*
@ -23,14 +21,6 @@ suspend fun CameraView.startRecording(options: RecordVideoOptions, onRecordCallb
} }
} }
val enableFlash = options.flash == Flash.ON
if (enableFlash) {
// overrides current torch mode value to enable flash while recording
cameraSession.configure { config ->
config.torch = Torch.ON
}
}
val callback = { video: RecordingSession.Video -> val callback = { video: RecordingSession.Video ->
val map = Arguments.createMap() val map = Arguments.createMap()
map.putString("path", video.path) map.putString("path", video.path)
@ -57,8 +47,4 @@ suspend fun CameraView.resumeRecording() {
@SuppressLint("RestrictedApi") @SuppressLint("RestrictedApi")
suspend fun CameraView.stopRecording() { suspend fun CameraView.stopRecording() {
cameraSession.stopRecording() cameraSession.stopRecording()
// Set torch back to it's original value in case we just used it as a flash for the recording.
cameraSession.configure { config ->
config.torch = torch
}
} }

View File

@ -18,13 +18,6 @@ extension CameraView: AVCaptureVideoDataOutputSampleBufferDelegate, AVCaptureAud
do { do {
let options = try RecordVideoOptions(fromJSValue: options) let options = try RecordVideoOptions(fromJSValue: options)
// If flash is on, just enable torch
if options.flash != .off {
cameraSession.configure { config in
config.torch = options.flash
}
}
// Start Recording with success and error callbacks // Start Recording with success and error callbacks
cameraSession.startRecording( cameraSession.startRecording(
options: options, options: options,
@ -47,11 +40,6 @@ extension CameraView: AVCaptureVideoDataOutputSampleBufferDelegate, AVCaptureAud
func stopRecording(promise: Promise) { func stopRecording(promise: Promise) {
cameraSession.stopRecording(promise: promise) cameraSession.stopRecording(promise: promise)
// If flash was used, we had the torch enabled. Now set it back to it's original state.
cameraSession.configure { config in
config.torch = try Torch(jsValue: torch)
}
} }
func pauseRecording(promise: Promise) { func pauseRecording(promise: Promise) {

View File

@ -18,10 +18,9 @@ extension CameraView {
return return
} }
// Update zoom on Camera // Update zoom React prop
cameraSession.configure { configuration in zoom = NSNumber(value: scale)
configuration.zoom = scale didSetProps(["zoom"])
}
} }
func addPinchGestureRecognizer() { func addPinchGestureRecognizer() {

View File

@ -43,14 +43,6 @@ extension CameraSession {
self.deactivateAudioSession() self.deactivateAudioSession()
} }
} }
// Reset flash
if options.flash != .off {
// Set torch mode back to what it was before if we used it for the video flash.
self.configure { config in
let torch = self.configuration?.torch ?? .off
config.torch = torch
}
}
} }
self.isRecording = false self.isRecording = false

View File

@ -40,6 +40,9 @@ type NativeRecordVideoOptions = Omit<RecordVideoOptions, 'onRecordingError' | 'o
videoBitRateMultiplier?: number videoBitRateMultiplier?: number
} }
type RefType = React.Component<NativeCameraViewProps> & Readonly<NativeMethods> type RefType = React.Component<NativeCameraViewProps> & Readonly<NativeMethods>
interface CameraState {
isRecordingWithFlash: boolean
}
//#endregion //#endregion
//#region Camera Component //#region Camera Component
@ -71,7 +74,7 @@ type RefType = React.Component<NativeCameraViewProps> & Readonly<NativeMethods>
* *
* @component * @component
*/ */
export class Camera extends React.PureComponent<CameraProps> { export class Camera extends React.PureComponent<CameraProps, CameraState> {
/** @internal */ /** @internal */
static displayName = 'Camera' static displayName = 'Camera'
/** @internal */ /** @internal */
@ -90,6 +93,9 @@ export class Camera extends React.PureComponent<CameraProps> {
this.onCodeScanned = this.onCodeScanned.bind(this) this.onCodeScanned = this.onCodeScanned.bind(this)
this.ref = React.createRef<RefType>() this.ref = React.createRef<RefType>()
this.lastFrameProcessor = undefined this.lastFrameProcessor = undefined
this.state = {
isRecordingWithFlash: false,
}
} }
private get handle(): number { private get handle(): number {
@ -163,6 +169,13 @@ export class Camera extends React.PureComponent<CameraProps> {
if (typeof onRecordingError !== 'function' || typeof onRecordingFinished !== 'function') if (typeof onRecordingError !== 'function' || typeof onRecordingFinished !== 'function')
throw new CameraRuntimeError('parameter/invalid-parameter', 'The onRecordingError or onRecordingFinished functions were not set!') throw new CameraRuntimeError('parameter/invalid-parameter', 'The onRecordingError or onRecordingFinished functions were not set!')
if (options.flash === 'on') {
// Enable torch for video recording
this.setState({
isRecordingWithFlash: true,
})
}
const nativeOptions: NativeRecordVideoOptions = passThruOptions const nativeOptions: NativeRecordVideoOptions = passThruOptions
if (typeof videoBitRate === 'number') { if (typeof videoBitRate === 'number') {
// If the user passed an absolute number as a bit-rate, we just use this as a full override. // If the user passed an absolute number as a bit-rate, we just use this as a full override.
@ -173,6 +186,13 @@ export class Camera extends React.PureComponent<CameraProps> {
} }
const onRecordCallback = (video?: VideoFile, error?: CameraCaptureError): void => { const onRecordCallback = (video?: VideoFile, error?: CameraCaptureError): void => {
if (this.state.isRecordingWithFlash) {
// disable torch again if it was enabled
this.setState({
isRecordingWithFlash: false,
})
}
if (error != null) return onRecordingError(error) if (error != null) return onRecordingError(error)
if (video != null) return onRecordingFinished(video) if (video != null) return onRecordingFinished(video)
} }
@ -450,12 +470,14 @@ export class Camera extends React.PureComponent<CameraProps> {
} }
const shouldEnableBufferCompression = props.video === true && frameProcessor == null const shouldEnableBufferCompression = props.video === true && frameProcessor == null
const torch = this.state.isRecordingWithFlash ? 'on' : props.torch
return ( return (
<NativeCameraView <NativeCameraView
{...props} {...props}
cameraId={device.id} cameraId={device.id}
ref={this.ref} ref={this.ref}
torch={torch}
onViewReady={this.onViewReady} onViewReady={this.onViewReady}
onInitialized={this.onInitialized} onInitialized={this.onInitialized}
onCodeScanned={this.onCodeScanned} onCodeScanned={this.onCodeScanned}