diff --git a/native/media/camera-modal.react.js b/native/media/camera-modal.react.js --- a/native/media/camera-modal.react.js +++ b/native/media/camera-modal.react.js @@ -228,6 +228,12 @@ NativeMethods, >; +type AutoFocusPointOfInterest = ?{ + x: number, + y: number, + autoExposure?: boolean, +}; + type BaseProps = { +handlePhotoCapture: (capture: PhotoCapture) => mixed, +navigation: @@ -254,14 +260,12 @@ +switchCamera: () => void, +hasCamerasOnBothSides: boolean, +fetchCameraIDs: (camera: RNCamera) => Promise, + +autoFocusPointOfInterest: AutoFocusPointOfInterest, + +setAutoFocusPointOfInterest: AutoFocusPointOfInterest => void, + +focusOnPoint: (input: [number, number]) => void, }; type State = { +zoom: number, - +autoFocusPointOfInterest: ?{ - x: number, - y: number, - autoExposure?: boolean, - }, +stagingMode: boolean, +pendingPhotoCapture: ?PhotoCapture, }; @@ -315,7 +319,6 @@ this.state = { zoom: 0, - autoFocusPointOfInterest: undefined, stagingMode: false, pendingPhotoCapture: undefined, }; @@ -428,7 +431,7 @@ return block([ cond(fingerJustReleased, [ - call([tapX, tapY], this.focusOnPoint), + call([tapX, tapY], this.props.focusOnPoint), set(this.focusIndicatorX, tapX), set(this.focusIndicatorY, tapY), stopClock(indicatorSpringClock), @@ -514,7 +517,7 @@ } if (this.props.deviceOrientation !== prevProps.deviceOrientation) { - this.setState({ autoFocusPointOfInterest: null }); + this.props.setAutoFocusPointOfInterest(null); this.cancelIndicatorAnimation.setValue(1); } @@ -747,7 +750,7 @@ maxZoom={maxZoom} zoom={this.state.zoom} flashMode={this.props.flashMode} - autoFocusPointOfInterest={this.state.autoFocusPointOfInterest} + autoFocusPointOfInterest={this.props.autoFocusPointOfInterest} style={styles.fill} androidCameraPermissionOptions={null} ref={this.cameraRef} @@ -893,10 +896,10 @@ retries: 0, }; + this.props.setAutoFocusPointOfInterest(undefined); this.setState({ pendingPhotoCapture, zoom: 0, - autoFocusPointOfInterest: undefined, }); }; @@ -930,33 +933,6 @@ updateZoom = ([zoom]: [number]) => { this.setState({ zoom }); }; - - focusOnPoint = ([inputX, inputY]: [number, number]) => { - const { width: screenWidth, height: screenHeight } = this.props.dimensions; - const relativeX = inputX / screenWidth; - const relativeY = inputY / screenHeight; - - // react-native-camera's autoFocusPointOfInterest prop is based on a - // LANDSCAPE-LEFT orientation, so we need to map to that - let x, y; - if (this.props.deviceOrientation === 'LANDSCAPE-LEFT') { - x = relativeX; - y = relativeY; - } else if (this.props.deviceOrientation === 'LANDSCAPE-RIGHT') { - x = 1 - relativeX; - y = 1 - relativeY; - } else if (this.props.deviceOrientation === 'PORTRAIT-UPSIDEDOWN') { - x = 1 - relativeY; - y = relativeX; - } else { - x = relativeY; - y = 1 - relativeX; - } - - const autoFocusPointOfInterest = - Platform.OS === 'ios' ? { x, y, autoExposure: true } : { x, y }; - this.setState({ autoFocusPointOfInterest }); - }; } const styles = StyleSheet.create({ @@ -1209,6 +1185,38 @@ [deviceCameraInfo, dispatch, hasCamerasOnBothSides], ); + const [autoFocusPointOfInterest, setAutoFocusPointOfInterest] = + React.useState(); + + const focusOnPoint = React.useCallback( + ([inputX, inputY]: [number, number]) => { + const { width: screenWidth, height: screenHeight } = dimensions; + const relativeX = inputX / screenWidth; + const relativeY = inputY / screenHeight; + + // react-native-camera's autoFocusPointOfInterest prop is based on a + // LANDSCAPE-LEFT orientation, so we need to map to that + let x, y; + if (deviceOrientation === 'LANDSCAPE-LEFT') { + x = relativeX; + y = relativeY; + } else if (deviceOrientation === 'LANDSCAPE-RIGHT') { + x = 1 - relativeX; + y = 1 - relativeY; + } else if (deviceOrientation === 'PORTRAIT-UPSIDEDOWN') { + x = 1 - relativeY; + y = relativeX; + } else { + x = relativeY; + y = 1 - relativeX; + } + setAutoFocusPointOfInterest( + Platform.OS === 'ios' ? { x, y, autoExposure: true } : { x, y }, + ); + }, + [deviceOrientation, dimensions], + ); + return ( ); });