diff --git a/src/components/bottomSheet/BottomSheet.tsx b/src/components/bottomSheet/BottomSheet.tsx index 9969e1d6..53885630 100644 --- a/src/components/bottomSheet/BottomSheet.tsx +++ b/src/components/bottomSheet/BottomSheet.tsx @@ -683,9 +683,9 @@ const BottomSheetComponent = forwardRef( method: animateToPosition.name, params: { currentPosition: animatedPosition.value, - position, + nextPosition: position, velocity, - animatedContainerHeight: animatedContainerHeight.value, + source, }, }); @@ -733,6 +733,47 @@ const BottomSheetComponent = forwardRef( }, [handleOnAnimate, _providedAnimationConfigs] ); + /** + * Set to position without animation. + * + * @param targetPosition position to be set. + */ + const setToPosition = useWorkletCallback(function setToPosition( + targetPosition: number + ) { + if ( + targetPosition === animatedPosition.value || + targetPosition === undefined || + (animatedAnimationState.value === ANIMATION_STATE.RUNNING && + targetPosition === animatedNextPosition.value) + ) { + return; + } + + runOnJS(print)({ + component: BottomSheet.name, + method: setToPosition.name, + params: { + currentPosition: animatedPosition.value, + targetPosition, + }, + }); + + /** + * store next position + */ + animatedNextPosition.value = targetPosition; + animatedNextPositionIndex.value = + animatedSnapPoints.value.indexOf(targetPosition); + + stopAnimation(); + + /** + * set position. + */ + animatedPosition.value = targetPosition; + }, + []); //#endregion //#region public methods @@ -1311,16 +1352,8 @@ const BottomSheetComponent = forwardRef( animatedNextPositionIndex.value === -1 && _previousContainerHeight !== containerHeight ) { - animationSource = ANIMATION_SOURCE.CONTAINER_RESIZE; - animationConfig = { - duration: 0, - }; - animateToPosition( - containerHeight, - animationSource, - 0, - animationConfig - ); + setToPosition(containerHeight); + return; } if ( @@ -1361,13 +1394,11 @@ const BottomSheetComponent = forwardRef( /** * if snap points changes because of the container height change, - * then we skip the snap animation by setting the duration to 0. + * then we set the new position without animation. */ if (containerHeight !== _previousContainerHeight) { - animationSource = ANIMATION_SOURCE.CONTAINER_RESIZE; - animationConfig = { - duration: 0, - }; + setToPosition(nextPosition); + return; } } animateToPosition(nextPosition, animationSource, 0, animationConfig); @@ -1524,6 +1555,7 @@ const BottomSheetComponent = forwardRef( }), ({ _animatedIndex, + _animatedPosition, _animationState, _contentGestureState, _handleGestureState, @@ -1535,6 +1567,21 @@ const BottomSheetComponent = forwardRef( return; } + /** + * exit the method if index value is not synced with + * position value. + * + * [read more](https://github.com/gorhom/react-native-bottom-sheet/issues/1356) + */ + if ( + animatedNextPosition.value !== INITIAL_VALUE && + animatedNextPositionIndex.value !== INITIAL_VALUE && + (_animatedPosition !== animatedNextPosition.value || + _animatedIndex !== animatedNextPositionIndex.value) + ) { + return; + } + /** * exit the method if animated index value * has fraction, e.g. 1.99, 0.52 diff --git a/src/hooks/useBottomSheetTimingConfigs.ts b/src/hooks/useBottomSheetTimingConfigs.ts index 5ff60182..1c9ad7e3 100644 --- a/src/hooks/useBottomSheetTimingConfigs.ts +++ b/src/hooks/useBottomSheetTimingConfigs.ts @@ -1,14 +1,10 @@ import { useMemo } from 'react'; import type { EasingFunction } from 'react-native'; -import type { - EasingFunctionFactory, - ReduceMotion, -} from 'react-native-reanimated'; +import type { EasingFunctionFactory } from 'react-native-reanimated'; import { ANIMATION_DURATION, ANIMATION_EASING } from '../constants'; interface TimingConfig { duration?: number; - reduceMotion?: ReduceMotion; easing?: EasingFunction | EasingFunctionFactory; }