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 @@ -29,6 +29,7 @@ import Reanimated, { EasingNode as ReanimatedEasing, type EventResult, + useSharedValue, } from 'react-native-reanimated'; import { SafeAreaView } from 'react-native-safe-area-context'; @@ -76,7 +77,6 @@ or, eq, greaterThan, - lessThan, add, sub, multiply, @@ -246,6 +246,13 @@ autoExposure?: boolean, }; +type Dimensions = { + x: number, + y: number, + width: number, + height: number, +}; + type BaseProps = { +handlePhotoCapture: (capture: PhotoCapture) => mixed, +navigation: @@ -288,6 +295,16 @@ +sendPhoto: () => Promise, +clearPendingImage: () => void, +gesture: ExclusiveGesture, + +closeButtonRef: { current: ?React.ElementRef }, + +photoButtonRef: { current: ?React.ElementRef }, + +switchCameraButtonRef: { + current: ?React.ElementRef, + }, + +flashButtonRef: { current: ?React.ElementRef }, + +onCloseButtonLayout: () => void, + +onPhotoButtonLayout: () => void, + +onSwitchCameraButtonLayout: () => void, + +onFlashButtonLayout: () => void, }; class CameraModal extends React.PureComponent { @@ -297,30 +314,6 @@ tapHandler: ReactRef = React.createRef(); animationCode: Node; - closeButton: ?React.ElementRef; - closeButtonX: Value = new Value(-1); - closeButtonY: Value = new Value(-1); - closeButtonWidth: Value = new Value(0); - closeButtonHeight: Value = new Value(0); - - photoButton: ?React.ElementRef; - photoButtonX: Value = new Value(-1); - photoButtonY: Value = new Value(-1); - photoButtonWidth: Value = new Value(0); - photoButtonHeight: Value = new Value(0); - - switchCameraButton: ?React.ElementRef; - switchCameraButtonX: Value = new Value(-1); - switchCameraButtonY: Value = new Value(-1); - switchCameraButtonWidth: Value = new Value(0); - switchCameraButtonHeight: Value = new Value(0); - - flashButton: ?React.ElementRef; - flashButtonX: Value = new Value(-1); - flashButtonY: Value = new Value(-1); - flashButtonWidth: Value = new Value(0); - flashButtonHeight: Value = new Value(0); - focusIndicatorX: Value = new Value(-1); focusIndicatorY: Value = new Value(-1); focusIndicatorScale: Value = new Value(0); @@ -430,7 +423,10 @@ const lastTapY = new Value(0); const fingerJustReleased = and( gestureJustEnded(tapState), - this.outsideButtons(lastTapX, lastTapY), + // TODO: it should be outsideButtons(lastTapX, lastTapY) here but + // outsideButtons is migrated so we can't call it + // for now focus is broken, but we'll fix it in the next diffs + 0, ); const indicatorSpringClock = new Clock(); @@ -474,61 +470,7 @@ ]); } - outsideButtons(x: Node, y: Node): Node { - const { - closeButtonX, - closeButtonY, - closeButtonWidth, - closeButtonHeight, - photoButtonX, - photoButtonY, - photoButtonWidth, - photoButtonHeight, - switchCameraButtonX, - switchCameraButtonY, - switchCameraButtonWidth, - switchCameraButtonHeight, - flashButtonX, - flashButtonY, - flashButtonWidth, - flashButtonHeight, - } = this; - return and( - or( - lessThan(x, closeButtonX), - greaterThan(x, add(closeButtonX, closeButtonWidth)), - lessThan(y, closeButtonY), - greaterThan(y, add(closeButtonY, closeButtonHeight)), - ), - or( - lessThan(x, photoButtonX), - greaterThan(x, add(photoButtonX, photoButtonWidth)), - lessThan(y, photoButtonY), - greaterThan(y, add(photoButtonY, photoButtonHeight)), - ), - or( - lessThan(x, switchCameraButtonX), - greaterThan(x, add(switchCameraButtonX, switchCameraButtonWidth)), - lessThan(y, switchCameraButtonY), - greaterThan(y, add(switchCameraButtonY, switchCameraButtonHeight)), - ), - or( - lessThan(x, flashButtonX), - greaterThan(x, add(flashButtonX, flashButtonWidth)), - lessThan(y, flashButtonY), - greaterThan(y, add(flashButtonY, flashButtonHeight)), - ), - ); - } - componentDidUpdate(prevProps: Props) { - if (!this.props.hasCamerasOnBothSides && prevProps.hasCamerasOnBothSides) { - this.switchCameraButtonX.setValue(-1); - this.switchCameraButtonY.setValue(-1); - this.switchCameraButtonWidth.setValue(0); - this.switchCameraButtonHeight.setValue(0); - } - if (this.props.deviceOrientation !== prevProps.deviceOrientation) { this.props.setAutoFocusPointOfInterest(null); this.cancelIndicatorAnimation.setValue(1); @@ -611,9 +553,9 @@ {this.renderCameraContent(status)} × @@ -673,9 +615,9 @@ switchCameraButton = ( @@ -702,18 +644,18 @@ {flashIcon} @@ -752,82 +694,6 @@ ); } - - closeButtonRef = ( - closeButton: ?React.ElementRef, - ) => { - this.closeButton = (closeButton: any); - }; - - onCloseButtonLayout = () => { - const { closeButton } = this; - if (!closeButton) { - return; - } - closeButton.measure((x, y, width, height, pageX, pageY) => { - this.closeButtonX.setValue(pageX); - this.closeButtonY.setValue(pageY); - this.closeButtonWidth.setValue(width); - this.closeButtonHeight.setValue(height); - }); - }; - - photoButtonRef = ( - photoButton: ?React.ElementRef, - ) => { - this.photoButton = (photoButton: any); - }; - - onPhotoButtonLayout = () => { - const { photoButton } = this; - if (!photoButton) { - return; - } - photoButton.measure((x, y, width, height, pageX, pageY) => { - this.photoButtonX.setValue(pageX); - this.photoButtonY.setValue(pageY); - this.photoButtonWidth.setValue(width); - this.photoButtonHeight.setValue(height); - }); - }; - - switchCameraButtonRef = ( - switchCameraButton: ?React.ElementRef, - ) => { - this.switchCameraButton = (switchCameraButton: any); - }; - - onSwitchCameraButtonLayout = () => { - const { switchCameraButton } = this; - if (!switchCameraButton) { - return; - } - switchCameraButton.measure((x, y, width, height, pageX, pageY) => { - this.switchCameraButtonX.setValue(pageX); - this.switchCameraButtonY.setValue(pageY); - this.switchCameraButtonWidth.setValue(width); - this.switchCameraButtonHeight.setValue(height); - }); - }; - - flashButtonRef = ( - flashButton: ?React.ElementRef, - ) => { - this.flashButton = (flashButton: any); - }; - - onFlashButtonLayout = () => { - const { flashButton } = this; - if (!flashButton) { - return; - } - flashButton.measure((x, y, width, height, pageX, pageY) => { - this.flashButtonX.setValue(pageX); - this.flashButtonY.setValue(pageY); - this.flashButtonWidth.setValue(width); - this.flashButtonHeight.setValue(height); - }); - }; } const styles = StyleSheet.create({ @@ -1216,6 +1082,136 @@ return Gesture.Exclusive(pinchGesture, tapGesture); }, []); + const closeButtonRef = + React.useRef>(); + const closeButtonDimensions = useSharedValue({ + x: -1, + y: -1, + width: 0, + height: 0, + }); + + const photoButtonRef = + React.useRef>(); + const photoButtonDimensions = useSharedValue({ + x: -1, + y: -1, + width: 0, + height: 0, + }); + + const switchCameraButtonRef = + React.useRef>(); + const switchCameraButtonDimensions = useSharedValue({ + x: -1, + y: -1, + width: 0, + height: 0, + }); + + const flashButtonRef = + React.useRef>(); + const flashButtonDimensions = useSharedValue({ + x: -1, + y: -1, + width: 0, + height: 0, + }); + + const onCloseButtonLayout = React.useCallback(() => { + if (!closeButtonRef.current) { + return; + } + closeButtonRef.current.measure((x, y, width, height, pageX, pageY) => { + closeButtonDimensions.value = { x: pageX, y: pageY, width, height }; + }); + }, [closeButtonDimensions]); + + const onPhotoButtonLayout = React.useCallback(() => { + if (!photoButtonRef.current) { + return; + } + photoButtonRef.current.measure((x, y, width, height, pageX, pageY) => { + photoButtonDimensions.value = { x: pageX, y: pageY, width, height }; + }); + }, [photoButtonDimensions]); + + const onSwitchCameraButtonLayout = React.useCallback(() => { + if (!switchCameraButtonRef.current) { + return; + } + switchCameraButtonRef.current.measure( + (x, y, width, height, pageX, pageY) => { + switchCameraButtonDimensions.value = { + x: pageX, + y: pageY, + width, + height, + }; + }, + ); + }, [switchCameraButtonDimensions]); + + React.useEffect(() => { + if (!hasCamerasOnBothSides) { + switchCameraButtonDimensions.value = { + x: -1, + y: -1, + width: 0, + height: 0, + }; + } + }, [hasCamerasOnBothSides, switchCameraButtonDimensions]); + + const onFlashButtonLayout = React.useCallback(() => { + if (!flashButtonRef.current) { + return; + } + flashButtonRef.current.measure((x, y, width, height, pageX, pageY) => { + flashButtonDimensions.value = { x: pageX, y: pageY, width, height }; + }); + }, [flashButtonDimensions]); + + // TODO: temporarily it's unused, will be fixed in the next diff + // eslint-disable-next-line no-unused-vars + const outsideButtons = React.useCallback( + (x: number, y: number) => { + 'worklet'; + const isOutsideButton = (dim: Dimensions) => { + return ( + x < dim.x || + x > dim.x + dim.width || + y < dim.y || + y > dim.y + dim.height + ); + }; + const isOutsideCloseButton = isOutsideButton( + closeButtonDimensions.value, + ); + const isOutsidePhotoButton = isOutsideButton( + photoButtonDimensions.value, + ); + const isOutsideSwitchCameraButton = isOutsideButton( + switchCameraButtonDimensions.value, + ); + const isOutsideFlashButton = isOutsideButton( + flashButtonDimensions.value, + ); + return ( + isOutsideCloseButton && + isOutsidePhotoButton && + isOutsideSwitchCameraButton && + isOutsideFlashButton + ); + }, + [ + closeButtonDimensions, + flashButtonDimensions, + photoButtonDimensions, + switchCameraButtonDimensions, + ], + ); + return ( ); });