From 73c358f73962f392493c082b880579523c4b0ff7 Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Tue, 5 Nov 2024 14:40:45 +0100 Subject: [PATCH] Finish migrating to new reanimated --- .../MultiGestureCanvas/usePinchGesture.ts | 88 ++++++++++--------- .../MultiGestureCanvas/useTapGestures.ts | 23 +++-- .../ReportActionItem/ReportPreview.tsx | 19 ++-- .../AnimatedSettlementButton.tsx | 44 +++++----- .../SplashScreenHider/index.native.tsx | 31 ++++--- .../VideoPlayer/BaseVideoPlayer.tsx | 7 +- .../VideoPlayerControls/ProgressBar/index.tsx | 11 ++- .../VolumeButton/index.tsx | 15 ++-- .../VideoPlayerContexts/VolumeContext.tsx | 7 +- src/hooks/useAnimatedHighlightStyle/index.ts | 35 ++++---- src/pages/Search/SearchPageBottomTab.tsx | 15 ++-- .../report/AnimatedEmptyStateBackground.tsx | 9 +- .../home/report/FloatingMessageCounter.tsx | 6 +- .../ComposerWithSuggestions.tsx | 13 ++- .../ReportActionCompose.tsx | 7 +- .../report/ReportActionItemMessageEdit.tsx | 14 ++- .../step/IOURequestStepScan/index.native.tsx | 13 ++- .../BackgroundImage/index.ios.tsx | 13 +-- 18 files changed, 182 insertions(+), 188 deletions(-) diff --git a/src/components/MultiGestureCanvas/usePinchGesture.ts b/src/components/MultiGestureCanvas/usePinchGesture.ts index 46a5e28e5732..7c517ad2f30b 100644 --- a/src/components/MultiGestureCanvas/usePinchGesture.ts +++ b/src/components/MultiGestureCanvas/usePinchGesture.ts @@ -1,8 +1,8 @@ /* eslint-disable no-param-reassign */ -import {useEffect, useState} from 'react'; +import {useCallback, useEffect, useState} from 'react'; import type {PinchGesture} from 'react-native-gesture-handler'; import {Gesture} from 'react-native-gesture-handler'; -import {runOnJS, useAnimatedReaction, useSharedValue, useWorkletCallback, withSpring} from 'react-native-reanimated'; +import {runOnJS, useAnimatedReaction, useSharedValue, withSpring} from 'react-native-reanimated'; import {SPRING_CONFIG, ZOOM_RANGE_BOUNCE_FACTORS} from './constants'; import type {MultiGestureCanvasVariables} from './types'; @@ -61,16 +61,16 @@ const usePinchGesture = ({ return; } - runOnJS(onScaleChanged)(zoomScale.value); + runOnJS(onScaleChanged)(zoomScale.get()); }; // Update the total (pinch) translation based on the regular pinch + bounce useAnimatedReaction( - () => [pinchTranslateX.value, pinchTranslateY.value, pinchBounceTranslateX.value, pinchBounceTranslateY.value], + () => [pinchTranslateX.get(), pinchTranslateY.get(), pinchBounceTranslateX.get(), pinchBounceTranslateY.get()], ([translateX, translateY, bounceX, bounceY]) => { // eslint-disable-next-line react-compiler/react-compiler - totalPinchTranslateX.value = translateX + bounceX; - totalPinchTranslateY.value = translateY + bounceY; + totalPinchTranslateX.set(translateX + bounceX); + totalPinchTranslateY.set(translateY + bounceY); }, ); @@ -78,12 +78,16 @@ const usePinchGesture = ({ * Calculates the adjusted focal point of the pinch gesture, * based on the canvas size and the current offset */ - const getAdjustedFocal = useWorkletCallback( - (focalX: number, focalY: number) => ({ - x: focalX - (canvasSize.width / 2 + offsetX.value), - y: focalY - (canvasSize.height / 2 + offsetY.value), - }), - [canvasSize.width, canvasSize.height], + const getAdjustedFocal = useCallback( + (focalX: number, focalY: number) => { + 'worklet'; + + return { + x: focalX - (canvasSize.width / 2 + offsetX.get()), + y: focalY - (canvasSize.height / 2 + offsetY.get()), + }; + }, + [canvasSize.width, canvasSize.height, offsetX, offsetY], ); // The pinch gesture is disabled when we release one of the fingers @@ -101,7 +105,7 @@ const usePinchGesture = ({ // The first argument is not used, but must be defined .onTouchesDown((_evt, state) => { // We don't want to activate pinch gesture when we are swiping in the pager - if (!shouldDisableTransformationGestures.value) { + if (!shouldDisableTransformationGestures.get()) { return; } @@ -112,8 +116,8 @@ const usePinchGesture = ({ // Set the origin focal point of the pinch gesture at the start of the gesture const adjustedFocal = getAdjustedFocal(evt.focalX, evt.focalY); - pinchOrigin.x.value = adjustedFocal.x; - pinchOrigin.y.value = adjustedFocal.y; + pinchOrigin.x.set(adjustedFocal.x); + pinchOrigin.y.set(adjustedFocal.y); }) .onChange((evt) => { // Disable the pinch gesture if one finger is released, @@ -123,58 +127,58 @@ const usePinchGesture = ({ return; } - const newZoomScale = pinchScale.value * evt.scale; - + const newZoomScale = pinchScale.get() * evt.scale; + const zoomScaleValue = zoomScale.get(); // Limit the zoom scale to zoom range including bounce range - if (zoomScale.value >= zoomRange.min * ZOOM_RANGE_BOUNCE_FACTORS.min && zoomScale.value <= zoomRange.max * ZOOM_RANGE_BOUNCE_FACTORS.max) { - zoomScale.value = newZoomScale; - currentPinchScale.value = evt.scale; + if (zoomScaleValue >= zoomRange.min * ZOOM_RANGE_BOUNCE_FACTORS.min && zoomScaleValue <= zoomRange.max * ZOOM_RANGE_BOUNCE_FACTORS.max) { + zoomScale.set(newZoomScale); + currentPinchScale.set(evt.scale); triggerScaleChangedEvent(); } // Calculate new pinch translation const adjustedFocal = getAdjustedFocal(evt.focalX, evt.focalY); - const newPinchTranslateX = adjustedFocal.x + currentPinchScale.value * pinchOrigin.x.value * -1; - const newPinchTranslateY = adjustedFocal.y + currentPinchScale.value * pinchOrigin.y.value * -1; + const newPinchTranslateX = adjustedFocal.x + currentPinchScale.get() * pinchOrigin.x.get() * -1; + const newPinchTranslateY = adjustedFocal.y + currentPinchScale.get() * pinchOrigin.y.get() * -1; // If the zoom scale is within the zoom range, we perform the regular pinch translation // Otherwise it means that we are "overzoomed" or "underzoomed", so we need to bounce back - if (zoomScale.value >= zoomRange.min && zoomScale.value <= zoomRange.max) { - pinchTranslateX.value = newPinchTranslateX; - pinchTranslateY.value = newPinchTranslateY; + if (zoomScaleValue >= zoomRange.min && zoomScaleValue <= zoomRange.max) { + pinchTranslateX.set(newPinchTranslateX); + pinchTranslateY.set(newPinchTranslateY); } else { // Store x and y translation that is produced while bouncing // so we can revert the bounce once pinch gesture is released - pinchBounceTranslateX.value = newPinchTranslateX - pinchTranslateX.value; - pinchBounceTranslateY.value = newPinchTranslateY - pinchTranslateY.value; + pinchBounceTranslateX.set(newPinchTranslateX - pinchTranslateX.get()); + pinchBounceTranslateY.set(newPinchTranslateY - pinchTranslateY.get()); } }) .onEnd(() => { // Add pinch translation to total offset and reset gesture variables - offsetX.value += pinchTranslateX.value; - offsetY.value += pinchTranslateY.value; - pinchTranslateX.value = 0; - pinchTranslateY.value = 0; - currentPinchScale.value = 1; + offsetX.set((value) => value + pinchTranslateX.get()); + offsetY.set((value) => value + pinchTranslateY.get()); + pinchTranslateX.set(0); + pinchTranslateY.set(0); + currentPinchScale.set(1); // If the content was "overzoomed" or "underzoomed", we need to bounce back with an animation - if (pinchBounceTranslateX.value !== 0 || pinchBounceTranslateY.value !== 0) { - pinchBounceTranslateX.value = withSpring(0, SPRING_CONFIG); - pinchBounceTranslateY.value = withSpring(0, SPRING_CONFIG); + if (pinchBounceTranslateX.get() !== 0 || pinchBounceTranslateY.get() !== 0) { + pinchBounceTranslateX.set(withSpring(0, SPRING_CONFIG)); + pinchBounceTranslateY.set(withSpring(0, SPRING_CONFIG)); } - if (zoomScale.value < zoomRange.min) { + if (zoomScale.get() < zoomRange.min) { // If the zoom scale is less than the minimum zoom scale, we need to set the zoom scale to the minimum - pinchScale.value = zoomRange.min; - zoomScale.value = withSpring(zoomRange.min, SPRING_CONFIG, triggerScaleChangedEvent); - } else if (zoomScale.value > zoomRange.max) { + pinchScale.set(zoomRange.min); + zoomScale.set(withSpring(zoomRange.min, SPRING_CONFIG, triggerScaleChangedEvent)); + } else if (zoomScale.get() > zoomRange.max) { // If the zoom scale is higher than the maximum zoom scale, we need to set the zoom scale to the maximum - pinchScale.value = zoomRange.max; - zoomScale.value = withSpring(zoomRange.max, SPRING_CONFIG, triggerScaleChangedEvent); + pinchScale.set(zoomRange.max); + zoomScale.set(withSpring(zoomRange.max, SPRING_CONFIG, triggerScaleChangedEvent)); } else { // Otherwise, we just update the pinch scale offset - pinchScale.value = zoomScale.value; + pinchScale.set(zoomScale.get()); triggerScaleChangedEvent(); } }); diff --git a/src/components/MultiGestureCanvas/useTapGestures.ts b/src/components/MultiGestureCanvas/useTapGestures.ts index e4bb02bd5d34..a918310d2862 100644 --- a/src/components/MultiGestureCanvas/useTapGestures.ts +++ b/src/components/MultiGestureCanvas/useTapGestures.ts @@ -1,8 +1,8 @@ /* eslint-disable no-param-reassign */ -import {useMemo} from 'react'; +import {useCallback, useMemo} from 'react'; import type {TapGesture} from 'react-native-gesture-handler'; import {Gesture} from 'react-native-gesture-handler'; -import {runOnJS, useWorkletCallback, withSpring} from 'react-native-reanimated'; +import {runOnJS, withSpring} from 'react-native-reanimated'; import {DOUBLE_TAP_SCALE, SPRING_CONFIG} from './constants'; import type {MultiGestureCanvasVariables} from './types'; import * as MultiGestureCanvasUtils from './utils'; @@ -46,7 +46,7 @@ const useTapGestures = ({ // On double tap the content should be zoomed to fill, but at least zoomed by DOUBLE_TAP_SCALE const doubleTapScale = useMemo(() => Math.max(DOUBLE_TAP_SCALE, maxContentScale / minContentScale), [maxContentScale, minContentScale]); - const zoomToCoordinates = useWorkletCallback( + const zoomToCoordinates = useCallback( (focalX: number, focalY: number, callback: () => void) => { 'worklet'; @@ -111,19 +111,18 @@ const useTapGestures = ({ offsetAfterZooming.y = 0; } - // eslint-disable-next-line react-compiler/react-compiler - offsetX.value = withSpring(offsetAfterZooming.x, SPRING_CONFIG); - offsetY.value = withSpring(offsetAfterZooming.y, SPRING_CONFIG); - zoomScale.value = withSpring(doubleTapScale, SPRING_CONFIG, callback); - pinchScale.value = doubleTapScale; + offsetX.set(withSpring(offsetAfterZooming.x, SPRING_CONFIG)); + offsetY.set(withSpring(offsetAfterZooming.y, SPRING_CONFIG)); + zoomScale.set(withSpring(doubleTapScale, SPRING_CONFIG, callback)); + pinchScale.set(doubleTapScale); }, - [scaledContentWidth, scaledContentHeight, canvasSize, doubleTapScale], + [stopAnimation, canvasSize.width, canvasSize.height, scaledContentWidth, scaledContentHeight, doubleTapScale, offsetX, offsetY, zoomScale, pinchScale], ); const doubleTapGesture = Gesture.Tap() // The first argument is not used, but must be defined .onTouchesDown((_evt, state) => { - if (!shouldDisableTransformationGestures.value) { + if (!shouldDisableTransformationGestures.get()) { return; } @@ -137,13 +136,13 @@ const useTapGestures = ({ 'worklet'; if (onScaleChanged != null) { - runOnJS(onScaleChanged)(zoomScale.value); + runOnJS(onScaleChanged)(zoomScale.get()); } }; // If the content is already zoomed, we want to reset the zoom, // otherwise we want to zoom in - if (zoomScale.value > 1) { + if (zoomScale.get() > 1) { reset(true, triggerScaleChangedEvent); } else { zoomToCoordinates(evt.x, evt.y, triggerScaleChangedEvent); diff --git a/src/components/ReportActionItem/ReportPreview.tsx b/src/components/ReportActionItem/ReportPreview.tsx index 9067f1abb11a..684e922e2dc6 100644 --- a/src/components/ReportActionItem/ReportPreview.tsx +++ b/src/components/ReportActionItem/ReportPreview.tsx @@ -135,7 +135,7 @@ function ReportPreview({ const iouSettled = ReportUtils.isSettled(iouReportID) || action?.childStatusNum === CONST.REPORT.STATUS_NUM.REIMBURSED; const previewMessageOpacity = useSharedValue(1); const previewMessageStyle = useAnimatedStyle(() => ({ - opacity: previewMessageOpacity.value, + opacity: previewMessageOpacity.get(), })); const checkMarkScale = useSharedValue(iouSettled ? 1 : 0); @@ -425,11 +425,11 @@ function ReportPreview({ return; } - // eslint-disable-next-line react-compiler/react-compiler - previewMessageOpacity.value = withTiming(0.75, {duration: CONST.ANIMATION_PAID_DURATION / 2}, () => { - // eslint-disable-next-line react-compiler/react-compiler - previewMessageOpacity.value = withTiming(1, {duration: CONST.ANIMATION_PAID_DURATION / 2}); - }); + previewMessageOpacity.set( + withTiming(0.75, {duration: CONST.ANIMATION_PAID_DURATION / 2}, () => { + previewMessageOpacity.set(withTiming(1, {duration: CONST.ANIMATION_PAID_DURATION / 2})); + }), + ); // We only want to animate the text when the text changes // eslint-disable-next-line react-compiler/react-compiler, react-hooks/exhaustive-deps }, [previewMessage, previewMessageOpacity]); @@ -439,12 +439,7 @@ function ReportPreview({ return; } - if (isPaidAnimationRunning) { - // eslint-disable-next-line react-compiler/react-compiler - checkMarkScale.value = withDelay(CONST.ANIMATION_PAID_CHECKMARK_DELAY, withSpring(1, {duration: CONST.ANIMATION_PAID_DURATION})); - } else { - checkMarkScale.value = 1; - } + checkMarkScale.set(isPaidAnimationRunning ? withDelay(CONST.ANIMATION_PAID_CHECKMARK_DELAY, withSpring(1, {duration: CONST.ANIMATION_PAID_DURATION})) : 1); }, [isPaidAnimationRunning, iouSettled, checkMarkScale]); return ( diff --git a/src/components/SettlementButton/AnimatedSettlementButton.tsx b/src/components/SettlementButton/AnimatedSettlementButton.tsx index 5de528d741a2..65c2fd2f493b 100644 --- a/src/components/SettlementButton/AnimatedSettlementButton.tsx +++ b/src/components/SettlementButton/AnimatedSettlementButton.tsx @@ -23,20 +23,20 @@ function AnimatedSettlementButton({isPaidAnimationRunning, onAnimationFinish, is const height = useSharedValue(variables.componentSizeNormal); const buttonMarginTop = useSharedValue(styles.expenseAndReportPreviewTextButtonContainer.gap); const buttonStyles = useAnimatedStyle(() => ({ - transform: [{scale: buttonScale.value}], - opacity: buttonOpacity.value, + transform: [{scale: buttonScale.get()}], + opacity: buttonOpacity.get(), })); const paymentCompleteTextStyles = useAnimatedStyle(() => ({ - transform: [{scale: paymentCompleteTextScale.value}], - opacity: paymentCompleteTextOpacity.value, + transform: [{scale: paymentCompleteTextScale.get()}], + opacity: paymentCompleteTextOpacity.get(), position: 'absolute', alignSelf: 'center', })); const containerStyles = useAnimatedStyle(() => ({ - height: height.value, + height: height.get(), justifyContent: 'center', overflow: 'hidden', - marginTop: buttonMarginTop.value, + marginTop: buttonMarginTop.get(), })); const buttonDisabledStyle = isPaidAnimationRunning ? { @@ -46,13 +46,12 @@ function AnimatedSettlementButton({isPaidAnimationRunning, onAnimationFinish, is : undefined; const resetAnimation = useCallback(() => { - // eslint-disable-next-line react-compiler/react-compiler - buttonScale.value = 1; - buttonOpacity.value = 1; - paymentCompleteTextScale.value = 0; - paymentCompleteTextOpacity.value = 1; - height.value = variables.componentSizeNormal; - buttonMarginTop.value = styles.expenseAndReportPreviewTextButtonContainer.gap; + buttonScale.set(1); + buttonOpacity.set(1); + paymentCompleteTextScale.set(0); + paymentCompleteTextOpacity.set(1); + height.set(variables.componentSizeNormal); + buttonMarginTop.set(styles.expenseAndReportPreviewTextButtonContainer.gap); }, [buttonScale, buttonOpacity, paymentCompleteTextScale, paymentCompleteTextOpacity, height, buttonMarginTop, styles.expenseAndReportPreviewTextButtonContainer.gap]); useEffect(() => { @@ -60,19 +59,20 @@ function AnimatedSettlementButton({isPaidAnimationRunning, onAnimationFinish, is resetAnimation(); return; } - // eslint-disable-next-line react-compiler/react-compiler - buttonScale.value = withTiming(0, {duration: CONST.ANIMATION_PAID_DURATION}); - buttonOpacity.value = withTiming(0, {duration: CONST.ANIMATION_PAID_DURATION}); - paymentCompleteTextScale.value = withTiming(1, {duration: CONST.ANIMATION_PAID_DURATION}); + buttonScale.set(withTiming(0, {duration: CONST.ANIMATION_PAID_DURATION})); + buttonOpacity.set(withTiming(0, {duration: CONST.ANIMATION_PAID_DURATION})); + paymentCompleteTextScale.set(withTiming(1, {duration: CONST.ANIMATION_PAID_DURATION})); // Wait for the above animation + 1s delay before hiding the component const totalDelay = CONST.ANIMATION_PAID_DURATION + CONST.ANIMATION_PAID_BUTTON_HIDE_DELAY; - height.value = withDelay( - totalDelay, - withTiming(0, {duration: CONST.ANIMATION_PAID_DURATION}, () => runOnJS(onAnimationFinish)()), + height.set( + withDelay( + totalDelay, + withTiming(0, {duration: CONST.ANIMATION_PAID_DURATION}, () => runOnJS(onAnimationFinish)()), + ), ); - buttonMarginTop.value = withDelay(totalDelay, withTiming(0, {duration: CONST.ANIMATION_PAID_DURATION})); - paymentCompleteTextOpacity.value = withDelay(totalDelay, withTiming(0, {duration: CONST.ANIMATION_PAID_DURATION})); + buttonMarginTop.set(withDelay(totalDelay, withTiming(0, {duration: CONST.ANIMATION_PAID_DURATION}))); + paymentCompleteTextOpacity.set(withDelay(totalDelay, withTiming(0, {duration: CONST.ANIMATION_PAID_DURATION}))); }, [isPaidAnimationRunning, onAnimationFinish, buttonOpacity, buttonScale, height, paymentCompleteTextOpacity, paymentCompleteTextScale, buttonMarginTop, resetAnimation]); return ( diff --git a/src/components/SplashScreenHider/index.native.tsx b/src/components/SplashScreenHider/index.native.tsx index 7c579519c926..d41770fb7f52 100644 --- a/src/components/SplashScreenHider/index.native.tsx +++ b/src/components/SplashScreenHider/index.native.tsx @@ -17,10 +17,10 @@ function SplashScreenHider({onHide = () => {}}: SplashScreenHiderProps): SplashS const scale = useSharedValue(1); const opacityStyle = useAnimatedStyle(() => ({ - opacity: opacity.value, + opacity: opacity.get(), })); const scaleStyle = useAnimatedStyle(() => ({ - transform: [{scale: scale.value}], + transform: [{scale: scale.get()}], })); const hideHasBeenCalled = useRef(false); @@ -34,19 +34,22 @@ function SplashScreenHider({onHide = () => {}}: SplashScreenHiderProps): SplashS hideHasBeenCalled.current = true; BootSplash.hide().then(() => { - // eslint-disable-next-line react-compiler/react-compiler - scale.value = withTiming(0, { - duration: 200, - easing: Easing.back(2), - }); + scale.set( + withTiming(0, { + duration: 200, + easing: Easing.back(2), + }), + ); - opacity.value = withTiming( - 0, - { - duration: 250, - easing: Easing.out(Easing.ease), - }, - () => runOnJS(onHide)(), + opacity.set( + withTiming( + 0, + { + duration: 250, + easing: Easing.out(Easing.ease), + }, + () => runOnJS(onHide)(), + ), ); }); }, [opacity, scale, onHide]); diff --git a/src/components/VideoPlayer/BaseVideoPlayer.tsx b/src/components/VideoPlayer/BaseVideoPlayer.tsx index 012537b75108..7fd26a177b0c 100644 --- a/src/components/VideoPlayer/BaseVideoPlayer.tsx +++ b/src/components/VideoPlayer/BaseVideoPlayer.tsx @@ -78,7 +78,7 @@ function BaseVideoPlayer({ const [controlStatusState, setControlStatusState] = useState(controlsStatus); const controlsOpacity = useSharedValue(1); const controlsAnimatedStyle = useAnimatedStyle(() => ({ - opacity: controlsOpacity.value, + opacity: controlsOpacity.get(), })); const videoPlayerRef = useRef(null); @@ -106,8 +106,7 @@ function BaseVideoPlayer({ }, [isCurrentlyURLSet, isPlaying, pauseVideo, playVideo, updateCurrentlyPlayingURL, url, videoResumeTryNumberRef]); const hideControl = useCallback(() => { - // eslint-disable-next-line react-compiler/react-compiler - controlsOpacity.value = withTiming(0, {duration: 500}, () => runOnJS(setControlStatusState)(CONST.VIDEO_PLAYER.CONTROLS_STATUS.HIDE)); + controlsOpacity.set(withTiming(0, {duration: 500}, () => runOnJS(setControlStatusState)(CONST.VIDEO_PLAYER.CONTROLS_STATUS.HIDE))); }, [controlsOpacity]); const debouncedHideControl = useMemo(() => debounce(hideControl, 1500), [hideControl]); @@ -144,7 +143,7 @@ function BaseVideoPlayer({ return; } setControlStatusState(CONST.VIDEO_PLAYER.CONTROLS_STATUS.SHOW); - controlsOpacity.value = 1; + controlsOpacity.set(1); }, [controlStatusState, controlsOpacity, hideControl]); const showPopoverMenu = (event?: GestureResponderEvent | KeyboardEvent) => { diff --git a/src/components/VideoPlayer/VideoPlayerControls/ProgressBar/index.tsx b/src/components/VideoPlayer/VideoPlayerControls/ProgressBar/index.tsx index 5d1ea0d85d0b..69273c1444e8 100644 --- a/src/components/VideoPlayer/VideoPlayerControls/ProgressBar/index.tsx +++ b/src/components/VideoPlayer/VideoPlayerControls/ProgressBar/index.tsx @@ -30,13 +30,12 @@ function ProgressBar({duration, position, seekPosition}: ProgressBarProps) { const wasVideoPlayingOnCheck = useSharedValue(false); const onCheckVideoPlaying = (isPlaying: boolean) => { - // eslint-disable-next-line react-compiler/react-compiler - wasVideoPlayingOnCheck.value = isPlaying; + wasVideoPlayingOnCheck.set(isPlaying); }; const progressBarInteraction = (event: GestureUpdateEvent | GestureStateChangeEvent) => { const progress = getProgress(event.x, sliderWidth); - progressWidth.value = progress; + progressWidth.set(progress); runOnJS(seekPosition)((progress * duration) / 100); }; @@ -56,7 +55,7 @@ function ProgressBar({duration, position, seekPosition}: ProgressBarProps) { }) .onFinalize(() => { runOnJS(setIsSliderPressed)(false); - if (!wasVideoPlayingOnCheck.value) { + if (!wasVideoPlayingOnCheck.get()) { return; } runOnJS(playVideo)(); @@ -66,10 +65,10 @@ function ProgressBar({duration, position, seekPosition}: ProgressBarProps) { if (isSliderPressed) { return; } - progressWidth.value = getProgress(position, duration); + progressWidth.set(getProgress(position, duration)); }, [duration, isSliderPressed, position, progressWidth]); - const progressBarStyle: ViewStyle = useAnimatedStyle(() => ({width: `${progressWidth.value}%`})); + const progressBarStyle: ViewStyle = useAnimatedStyle(() => ({width: `${progressWidth.get()}%`})); return ( diff --git a/src/components/VideoPlayer/VideoPlayerControls/VolumeButton/index.tsx b/src/components/VideoPlayer/VideoPlayerControls/VolumeButton/index.tsx index 751bd1b1df26..a6e44607ea62 100644 --- a/src/components/VideoPlayer/VideoPlayerControls/VolumeButton/index.tsx +++ b/src/components/VideoPlayer/VideoPlayerControls/VolumeButton/index.tsx @@ -35,7 +35,7 @@ function VolumeButton({style, small = false}: VolumeButtonProps) { const {translate} = useLocalize(); const {updateVolume, volume} = useVolumeContext(); const [sliderHeight, setSliderHeight] = useState(1); - const [volumeIcon, setVolumeIcon] = useState({icon: getVolumeIcon(volume.value)}); + const [volumeIcon, setVolumeIcon] = useState({icon: getVolumeIcon(volume.get())}); const [isSliderBeingUsed, setIsSliderBeingUsed] = useState(false); const onSliderLayout = useCallback((event: LayoutChangeEvent) => { @@ -45,8 +45,7 @@ function VolumeButton({style, small = false}: VolumeButtonProps) { const changeVolumeOnPan = useCallback( (event: GestureStateChangeEvent | GestureUpdateEvent) => { const val = NumberUtils.roundToTwoDecimalPlaces(1 - event.y / sliderHeight); - // eslint-disable-next-line react-compiler/react-compiler - volume.value = NumberUtils.clamp(val, 0, 1); + volume.set(NumberUtils.clamp(val, 0, 1)); }, [sliderHeight, volume], ); @@ -63,15 +62,15 @@ function VolumeButton({style, small = false}: VolumeButtonProps) { runOnJS(setIsSliderBeingUsed)(false); }); - const progressBarStyle = useAnimatedStyle(() => ({height: `${volume.value * 100}%`})); + const progressBarStyle = useAnimatedStyle(() => ({height: `${volume.get() * 100}%`})); const updateIcon = useCallback((vol: number) => { setVolumeIcon({icon: getVolumeIcon(vol)}); }, []); useDerivedValue(() => { - runOnJS(updateVolume)(volume.value); - runOnJS(updateIcon)(volume.value); + runOnJS(updateVolume)(volume.get()); + runOnJS(updateIcon)(volume.get()); }, [volume]); return ( @@ -95,8 +94,8 @@ function VolumeButton({style, small = false}: VolumeButtonProps) { )} updateVolume(volume.value === 0 ? 1 : 0)} + tooltipText={volume.get() === 0 ? translate('videoPlayer.unmute') : translate('videoPlayer.mute')} + onPress={() => updateVolume(volume.get() === 0 ? 1 : 0)} src={volumeIcon.icon} small={small} shouldForceRenderingTooltipBelow diff --git a/src/components/VideoPlayerContexts/VolumeContext.tsx b/src/components/VideoPlayerContexts/VolumeContext.tsx index f22b524848de..1f7b3bf66551 100644 --- a/src/components/VideoPlayerContexts/VolumeContext.tsx +++ b/src/components/VideoPlayerContexts/VolumeContext.tsx @@ -16,8 +16,7 @@ function VolumeContextProvider({children}: ChildrenProps) { return; } currentVideoPlayerRef.current.setStatusAsync({volume: newVolume, isMuted: newVolume === 0}); - // eslint-disable-next-line react-compiler/react-compiler - volume.value = newVolume; + volume.set(newVolume); }, [currentVideoPlayerRef, volume], ); @@ -28,8 +27,8 @@ function VolumeContextProvider({children}: ChildrenProps) { if (!originalParent) { return; } - updateVolume(volume.value); - }, [originalParent, updateVolume, volume.value]); + updateVolume(volume.get()); + }, [originalParent, updateVolume, volume]); const contextValue = useMemo(() => ({updateVolume, volume}), [updateVolume, volume]); return {children}; diff --git a/src/hooks/useAnimatedHighlightStyle/index.ts b/src/hooks/useAnimatedHighlightStyle/index.ts index e17f30fc60bf..4c9099c7f1ba 100644 --- a/src/hooks/useAnimatedHighlightStyle/index.ts +++ b/src/hooks/useAnimatedHighlightStyle/index.ts @@ -66,9 +66,9 @@ export default function useAnimatedHighlightStyle({ const theme = useTheme(); const highlightBackgroundStyle = useAnimatedStyle(() => ({ - backgroundColor: interpolateColor(repeatableProgress.value, [0, 1], [backgroundColor ?? theme.appBG, highlightColor ?? theme.border]), - height: height ? interpolate(nonRepeatableProgress.value, [0, 1], [0, height]) : 'auto', - opacity: interpolate(nonRepeatableProgress.value, [0, 1], [0, 1]), + backgroundColor: interpolateColor(repeatableProgress.get(), [0, 1], [backgroundColor ?? theme.appBG, highlightColor ?? theme.border]), + height: height ? interpolate(nonRepeatableProgress.get(), [0, 1], [0, height]) : 'auto', + opacity: interpolate(nonRepeatableProgress.get(), [0, 1], [0, 1]), borderRadius, })); @@ -90,19 +90,22 @@ export default function useAnimatedHighlightStyle({ setStartHighlight(false); InteractionManager.runAfterInteractions(() => { runOnJS(() => { - nonRepeatableProgress.value = withDelay( - itemEnterDelay, - withTiming(1, {duration: itemEnterDuration, easing: Easing.inOut(Easing.ease)}, (finished) => { - if (!finished) { - return; - } - - // eslint-disable-next-line react-compiler/react-compiler - repeatableProgress.value = withSequence( - withDelay(highlightStartDelay, withTiming(1, {duration: highlightStartDuration, easing: Easing.inOut(Easing.ease)})), - withDelay(highlightEndDelay, withTiming(0, {duration: highlightEndDuration, easing: Easing.inOut(Easing.ease)})), - ); - }), + nonRepeatableProgress.set( + withDelay( + itemEnterDelay, + withTiming(1, {duration: itemEnterDuration, easing: Easing.inOut(Easing.ease)}, (finished) => { + if (!finished) { + return; + } + + repeatableProgress.set( + withSequence( + withDelay(highlightStartDelay, withTiming(1, {duration: highlightStartDuration, easing: Easing.inOut(Easing.ease)})), + withDelay(highlightEndDelay, withTiming(0, {duration: highlightEndDuration, easing: Easing.inOut(Easing.ease)})), + ), + ); + }), + ), ); })(); }); diff --git a/src/pages/Search/SearchPageBottomTab.tsx b/src/pages/Search/SearchPageBottomTab.tsx index 38efb8eb929f..a34e8a47e0cb 100644 --- a/src/pages/Search/SearchPageBottomTab.tsx +++ b/src/pages/Search/SearchPageBottomTab.tsx @@ -37,7 +37,7 @@ function SearchPageBottomTab() { const scrollOffset = useSharedValue(0); const topBarOffset = useSharedValue(variables.searchHeaderHeight); const topBarAnimatedStyle = useAnimatedStyle(() => ({ - top: topBarOffset.value, + top: topBarOffset.get(), })); const scrollHandler = useAnimatedScrollHandler({ @@ -47,15 +47,14 @@ function SearchPageBottomTab() { return; } const currentOffset = contentOffset.y; - const isScrollingDown = currentOffset > scrollOffset.value; - const distanceScrolled = currentOffset - scrollOffset.value; + const isScrollingDown = currentOffset > scrollOffset.get(); + const distanceScrolled = currentOffset - scrollOffset.get(); if (isScrollingDown && contentOffset.y > TOO_CLOSE_TO_TOP_DISTANCE) { - // eslint-disable-next-line react-compiler/react-compiler - topBarOffset.value = clamp(topBarOffset.value - distanceScrolled, variables.minimalTopBarOffset, variables.searchHeaderHeight); + topBarOffset.set(clamp(topBarOffset.get() - distanceScrolled, variables.minimalTopBarOffset, variables.searchHeaderHeight)); } else if (!isScrollingDown && distanceScrolled < 0 && contentOffset.y + layoutMeasurement.height < contentSize.height - TOO_CLOSE_TO_BOTTOM_DISTANCE) { - topBarOffset.value = withTiming(variables.searchHeaderHeight, {duration: ANIMATION_DURATION_IN_MS}); + topBarOffset.set(withTiming(variables.searchHeaderHeight, {duration: ANIMATION_DURATION_IN_MS})); } - scrollOffset.value = currentOffset; + scrollOffset.set(currentOffset); }, }); @@ -113,7 +112,7 @@ function SearchPageBottomTab() { { - topBarOffset.value = withTiming(variables.searchHeaderHeight, {duration: ANIMATION_DURATION_IN_MS}); + topBarOffset.set(withTiming(variables.searchHeaderHeight, {duration: ANIMATION_DURATION_IN_MS})); }} /> diff --git a/src/pages/home/report/AnimatedEmptyStateBackground.tsx b/src/pages/home/report/AnimatedEmptyStateBackground.tsx index d277862ebf2c..56ae27de5ea1 100644 --- a/src/pages/home/report/AnimatedEmptyStateBackground.tsx +++ b/src/pages/home/report/AnimatedEmptyStateBackground.tsx @@ -35,13 +35,12 @@ function AnimatedEmptyStateBackground() { * We use x and y gyroscope velocity and add it to position offset to move background based on device movements. * Position the phone was in while entering the screen is the initial position for background image. */ - const {x, y} = animatedSensor.sensor.value; + const {x, y} = animatedSensor.sensor.get(); // The x vs y here seems wrong but is the way to make it feel right to the user - // eslint-disable-next-line react-compiler/react-compiler - xOffset.value = clamp(xOffset.value + y * CONST.ANIMATION_GYROSCOPE_VALUE, -IMAGE_OFFSET_X, IMAGE_OFFSET_X); - yOffset.value = clamp(yOffset.value - x * CONST.ANIMATION_GYROSCOPE_VALUE, -IMAGE_OFFSET_Y, IMAGE_OFFSET_Y); + xOffset.set((value) => clamp(value + y * CONST.ANIMATION_GYROSCOPE_VALUE, -IMAGE_OFFSET_X, IMAGE_OFFSET_X)); + yOffset.set((value) => clamp(value - x * CONST.ANIMATION_GYROSCOPE_VALUE, -IMAGE_OFFSET_Y, IMAGE_OFFSET_Y)); return { - transform: [{translateX: withSpring(xOffset.value)}, {translateY: withSpring(yOffset.value, {overshootClamping: true})}, {scale: 1.15}], + transform: [{translateX: withSpring(xOffset.get())}, {translateY: withSpring(yOffset.get(), {overshootClamping: true})}, {scale: 1.15}], }; }, [isReducedMotionEnabled]); diff --git a/src/pages/home/report/FloatingMessageCounter.tsx b/src/pages/home/report/FloatingMessageCounter.tsx index 0d92946e3d66..a196704d2119 100644 --- a/src/pages/home/report/FloatingMessageCounter.tsx +++ b/src/pages/home/report/FloatingMessageCounter.tsx @@ -30,13 +30,13 @@ function FloatingMessageCounter({isActive = false, onClick = () => {}}: Floating const show = useCallback(() => { 'worklet'; - translateY.value = withSpring(MARKER_ACTIVE_TRANSLATE_Y); + translateY.set(withSpring(MARKER_ACTIVE_TRANSLATE_Y)); }, [translateY]); const hide = useCallback(() => { 'worklet'; - translateY.value = withSpring(MARKER_INACTIVE_TRANSLATE_Y); + translateY.set(withSpring(MARKER_INACTIVE_TRANSLATE_Y)); }, [translateY]); useEffect(() => { @@ -49,7 +49,7 @@ function FloatingMessageCounter({isActive = false, onClick = () => {}}: Floating const wrapperStyle = useAnimatedStyle(() => ({ ...styles.floatingMessageCounterWrapper, - transform: [{translateY: translateY.value}], + transform: [{translateY: translateY.get()}], })); return ( diff --git a/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx b/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx index 1cb70fe6c926..9042c30440f7 100644 --- a/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx +++ b/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx @@ -709,20 +709,19 @@ function ComposerWithSuggestions( useEffect(() => { // We use the tag to store the native ID of the text input. Later, we use it in onSelectionChange to pick up the proper text input data. + tag.set(findNodeHandle(textInputRef.current) ?? -1); + }, [tag]); - tag.value = findNodeHandle(textInputRef.current) ?? -1; - // eslint-disable-next-line react-compiler/react-compiler, react-hooks/exhaustive-deps - }, []); useFocusedInputHandler( { onSelectionChange: (event) => { 'worklet'; - if (event.target === tag.value) { - cursorPositionValue.value = { + if (event.target === tag.get()) { + cursorPositionValue.set({ x: event.selection.end.x, y: event.selection.end.y, - }; + }); } }, }, @@ -731,7 +730,7 @@ function ComposerWithSuggestions( const measureParentContainerAndReportCursor = useCallback( (callback: MeasureParentContainerAndCursorCallback) => { const {scrollValue} = getScrollPosition({mobileInputScrollPosition, textInputRef}); - const {x: xPosition, y: yPosition} = getCursorPosition({positionOnMobile: cursorPositionValue.value, positionOnWeb: selection}); + const {x: xPosition, y: yPosition} = getCursorPosition({positionOnMobile: cursorPositionValue.get(), positionOnWeb: selection}); measureParentContainer((x, y, width, height) => { callback({ x, diff --git a/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx b/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx index 23b059f2fda2..4673475063c8 100644 --- a/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx +++ b/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx @@ -342,7 +342,7 @@ function ReportActionCompose({ const handleSendMessage = useCallback(() => { 'worklet'; - const clearComposer = composerRefShared.value.clear; + const clearComposer = composerRefShared.get().clear; if (!clearComposer) { throw new Error('The composerRefShared.clear function is not set yet. This should never happen, and indicates a developer error.'); } @@ -468,10 +468,9 @@ function ReportActionCompose({ { composerRef.current = ref ?? undefined; - // eslint-disable-next-line react-compiler/react-compiler - composerRefShared.value = { + composerRefShared.set({ clear: ref?.clear, - }; + }); }} suggestionsRef={suggestionsRef} isNextModalWillOpenRef={isNextModalWillOpenRef} diff --git a/src/pages/home/report/ReportActionItemMessageEdit.tsx b/src/pages/home/report/ReportActionItemMessageEdit.tsx index fd2dc2d44d4b..8bcf5a462d38 100644 --- a/src/pages/home/report/ReportActionItemMessageEdit.tsx +++ b/src/pages/home/report/ReportActionItemMessageEdit.tsx @@ -417,7 +417,7 @@ function ReportActionItemMessageEdit( const measureParentContainerAndReportCursor = useCallback( (callback: MeasureParentContainerAndCursorCallback) => { const {scrollValue} = getScrollPosition({mobileInputScrollPosition, textInputRef}); - const {x: xPosition, y: yPosition} = getCursorPosition({positionOnMobile: cursorPositionValue.value, positionOnWeb: selection}); + const {x: xPosition, y: yPosition} = getCursorPosition({positionOnMobile: cursorPositionValue.get(), positionOnWeb: selection}); measureContainer((x, y, width, height) => { callback({ x, @@ -429,25 +429,23 @@ function ReportActionItemMessageEdit( }); }); }, - [cursorPositionValue.value, measureContainer, selection], + [cursorPositionValue, measureContainer, selection], ); useEffect(() => { // We use the tag to store the native ID of the text input. Later, we use it in onSelectionChange to pick up the proper text input data. - - // eslint-disable-next-line react-compiler/react-compiler - tag.value = findNodeHandle(textInputRef.current) ?? -1; + tag.set(findNodeHandle(textInputRef.current) ?? -1); }, [tag]); useFocusedInputHandler( { onSelectionChange: (event) => { 'worklet'; - if (event.target === tag.value) { - cursorPositionValue.value = { + if (event.target === tag.get()) { + cursorPositionValue.set({ x: event.selection.end.x, y: event.selection.end.y, - }; + }); } }, }, diff --git a/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx b/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx index d3f0c9cb496d..61c856c856cf 100644 --- a/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx +++ b/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx @@ -120,8 +120,8 @@ function IOURequestStepScan({ const focusIndicatorPosition = useSharedValue({x: 0, y: 0}); const cameraFocusIndicatorAnimatedStyle = useAnimatedStyle(() => ({ - opacity: focusIndicatorOpacity.value, - transform: [{translateX: focusIndicatorPosition.value.x}, {translateY: focusIndicatorPosition.value.y}, {scale: focusIndicatorScale.value}], + opacity: focusIndicatorOpacity.get(), + transform: [{translateX: focusIndicatorPosition.get().x}, {translateY: focusIndicatorPosition.get().y}, {scale: focusIndicatorScale.get()}], })); const focusCamera = (point: Point) => { @@ -143,11 +143,10 @@ function IOURequestStepScan({ .onStart((ev: {x: number; y: number}) => { const point = {x: ev.x, y: ev.y}; - // eslint-disable-next-line react-compiler/react-compiler - focusIndicatorOpacity.value = withSequence(withTiming(0.8, {duration: 250}), withDelay(1000, withTiming(0, {duration: 250}))); - focusIndicatorScale.value = 2; - focusIndicatorScale.value = withSpring(1, {damping: 10, stiffness: 200}); - focusIndicatorPosition.value = point; + focusIndicatorOpacity.set(withSequence(withTiming(0.8, {duration: 250}), withDelay(1000, withTiming(0, {duration: 250})))); + focusIndicatorScale.set(2); + focusIndicatorScale.set(withSpring(1, {damping: 10, stiffness: 200})); + focusIndicatorPosition.set(point); runOnJS(focusCamera)(point); }); diff --git a/src/pages/signin/SignInPageLayout/BackgroundImage/index.ios.tsx b/src/pages/signin/SignInPageLayout/BackgroundImage/index.ios.tsx index 75e0be7e5f7c..fc28dc08fb15 100644 --- a/src/pages/signin/SignInPageLayout/BackgroundImage/index.ios.tsx +++ b/src/pages/signin/SignInPageLayout/BackgroundImage/index.ios.tsx @@ -20,14 +20,15 @@ function BackgroundImage({width, transitionDuration, isSmallScreen = false}: Bac const isAnonymous = isAnonymousUser(); const opacity = useSharedValue(0); - const animatedStyle = useAnimatedStyle(() => ({opacity: opacity.value})); + const animatedStyle = useAnimatedStyle(() => ({opacity: opacity.get()})); // This sets the opacity animation for the background image once it has loaded. function setOpacityAnimation() { - // eslint-disable-next-line react-compiler/react-compiler - opacity.value = withTiming(1, { - duration: CONST.MICROSECONDS_PER_MS, - easing: Easing.ease, - }); + opacity.set( + withTiming(1, { + duration: CONST.MICROSECONDS_PER_MS, + easing: Easing.ease, + }), + ); } useEffect(() => {