Skip to content

Commit

Permalink
feat: rewrite gesture apis with gesture handler 2 (gorhom#1126)
Browse files Browse the repository at this point in the history
* chore: updated dependencies

* feat: rewrite the gesture api with gh2

gorhom@6a4d296

fix(gorhom#1119): fixed race condition between onmount and keyboard animations
  • Loading branch information
yayvery committed Mar 18, 2024
1 parent 54dc2e0 commit 4ffdf5c
Show file tree
Hide file tree
Showing 21 changed files with 1,113 additions and 976 deletions.
8 changes: 4 additions & 4 deletions example/bare/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -382,9 +382,9 @@ PODS:
- React-perflogger (= 0.69.4)
- RNCMaskedView (0.1.11):
- React
- RNGestureHandler (2.5.0):
- RNGestureHandler (2.6.2):
- React-Core
- RNReanimated (2.9.1):
- RNReanimated (2.10.0):
- DoubleConversion
- FBLazyVector
- FBReactNativeSpec
Expand Down Expand Up @@ -644,8 +644,8 @@ SPEC CHECKSUMS:
React-runtimeexecutor: 61ee22a8cdf8b6bb2a7fb7b4ba2cc763e5285196
ReactCommon: 8f67bd7e0a6afade0f20718f859dc8c2275f2e83
RNCMaskedView: 0e1bc4bfa8365eba5fbbb71e07fbdc0555249489
RNGestureHandler: bad495418bcbd3ab47017a38d93d290ebd406f50
RNReanimated: 2cf7451318bb9cc430abeec8d67693f9cf4e039c
RNGestureHandler: 4defbd70b2faf3d6761b82fa7880285241762cb0
RNReanimated: 7faa787e8d4493fbc95fab2ad331fa7625828cfa
RNScreens: 4a1af06327774490d97342c00aee0c2bafb497b7
SocketRocket: fccef3f9c5cedea1353a9ef6ada904fde10d6608
Yoga: ff994563b2fd98c982ca58e8cd9db2cdaf4dda74
Expand Down
4 changes: 2 additions & 2 deletions example/bare/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@
"nanoid": "^3.3.3",
"react": "18.0.0",
"react-native": "0.69.4",
"react-native-gesture-handler": "^2.5.0",
"react-native-gesture-handler": "^2.6.2",
"react-native-maps": "^0.30.1",
"react-native-pager-view": "^5.4.9",
"react-native-reanimated": "^2.9.1",
"react-native-reanimated": "^2.10.0",
"react-native-redash": "^16.0.11",
"react-native-safe-area-context": "4.2.4",
"react-native-screens": "^3.15.0",
Expand Down
2 changes: 1 addition & 1 deletion lint-staged.config.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module.exports = {
'**/*.js': ['eslint'],
'**/*.{ts,tsx}': [() => 'tsc --skipLibCheck --noEmit', 'eslint'],
'**/*.{ts,tsx}': [() => 'tsc --skipLibCheck --noEmit', 'eslint --fix'],
};
16 changes: 8 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,16 +50,16 @@
"@types/react-native": "^0.67.7",
"auto-changelog": "^2.4.0",
"copyfiles": "^2.4.1",
"eslint": "^7.32.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-prettier": "^3.4.0",
"eslint": "^8.21.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-prettier": "^4.2.1",
"husky": "^4.3.8",
"lint-staged": "^11.1.2",
"prettier": "^2.3.2",
"lint-staged": "^13.0.3",
"prettier": "^2.7.1",
"react": "~16.9.0",
"react-native": "^0.62.2",
"react-native-builder-bob": "^0.18.1",
"react-native-gesture-handler": "^1.10.3",
"react-native-gesture-handler": "^2.12.0",
"react-native-reanimated": "^3.4.2",
"release-it": "^17.0.1",
"typescript": "^5.0.3"
Expand All @@ -70,8 +70,8 @@
"@shopify/flash-list": "*",
"react": "*",
"react-native": "*",
"react-native-gesture-handler": ">=1.10.1",
"react-native-reanimated": ">=2.2.0"
"react-native-gesture-handler": ">=2.5.0",
"react-native-reanimated": ">=2.9.0"
},
"peerDependenciesMeta": {
"@types/react-native": {
Expand Down
91 changes: 55 additions & 36 deletions src/components/bottomSheet/BottomSheet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -593,6 +593,10 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
return animatedPosition.value;
}

if (!isAnimatedOnMount.value) {
return snapPoints[_providedIndex];
}

return snapPoints[currentIndex];
},
[
Expand All @@ -605,8 +609,10 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
animatedPosition,
animatedSnapPoints,
isInTemporaryPosition,
isAnimatedOnMount,
keyboardBehavior,
keyboardBlurBehavior,
_providedIndex,
]
);
const handleOnChange = useCallback(
Expand Down Expand Up @@ -1271,7 +1277,7 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
nextPosition = animatedClosedPosition.value;
animatedNextPositionIndex.value = -1;
} else {
nextPosition = animatedSnapPoints.value[_providedIndex];
nextPosition = getNextPosition();
}

runOnJS(print)({
Expand Down Expand Up @@ -1425,41 +1431,52 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
)
: Math.abs(_keyboardHeight - animatedContainerOffset.value.bottom);

/**
* if keyboard state is equal to the previous state, then exit the method
*/
if (
_keyboardState === _previousKeyboardState &&
_keyboardHeight === _previousKeyboardHeight
) {
return;
}

/**
* if user is interacting with sheet, then exit the method
*/
const hasActiveGesture =
animatedContentGestureState.value === State.ACTIVE ||
animatedContentGestureState.value === State.BEGAN ||
animatedHandleGestureState.value === State.ACTIVE ||
animatedHandleGestureState.value === State.BEGAN;
if (hasActiveGesture) {
return;
}

/**
* if sheet not animated on mount yet, then exit the method
*/
if (!isAnimatedOnMount.value) {
return;
}

/**
* if new keyboard state is hidden and blur behavior is none, then exit the method
*/
if (
_keyboardState === KEYBOARD_STATE.HIDDEN &&
keyboardBlurBehavior === KEYBOARD_BLUR_BEHAVIOR.none
) {
return;
}

/**
* if platform is android and the input mode is resize, then exit the method
*/
if (
/**
* if keyboard state is equal to the previous state, then exit the method
*/
(_keyboardState === _previousKeyboardState &&
_keyboardHeight === _previousKeyboardHeight) ||
/**
* if user is interacting with sheet, then exit the method
*/
hasActiveGesture ||
/**
* if sheet not animated on mount yet, then exit the method
*/
!isAnimatedOnMount.value ||
/**
* if new keyboard state is hidden and blur behavior is none, then exit the method
*/
(_keyboardState === KEYBOARD_STATE.HIDDEN &&
keyboardBlurBehavior === KEYBOARD_BLUR_BEHAVIOR.none) ||
/**
* if platform is android and the input mode is resize, then exit the method
*/
(Platform.OS === 'android' &&
keyboardBehavior === KEYBOARD_BEHAVIOR.interactive &&
android_keyboardInputMode === KEYBOARD_INPUT_MODE.adjustResize) ||
/**
* if the sheet is closing, then exit then method
*/
animatedNextPositionIndex.value === -1
Platform.OS === 'android' &&
keyboardBehavior === KEYBOARD_BEHAVIOR.interactive &&
android_keyboardInputMode === KEYBOARD_INPUT_MODE.adjustResize
) {
animatedKeyboardHeightInContainer.value = 0;
return;
Expand Down Expand Up @@ -1706,13 +1723,15 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
// isScrollableRefreshable,
// animatedScrollableContentOffsetY,
// keyboardState,
// animatedIndex,
// animatedCurrentIndex,
// animatedPosition,
animatedContainerHeight,
animatedSheetHeight,
animatedHandleHeight,
animatedContentHeight,
animatedIndex,
animatedCurrentIndex,
animatedPosition,
animatedHandleGestureState,
animatedContentGestureState,
// animatedContainerHeight,
// animatedSheetHeight,
// animatedHandleHeight,
// animatedContentHeight,
// // keyboardHeight,
// isLayoutCalculated,
// isContentHeightFixed,
Expand Down
27 changes: 15 additions & 12 deletions src/components/bottomSheet/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import type {
WithSpringConfig,
WithTimingConfig,
} from 'react-native-reanimated';
import type { PanGestureHandlerProps } from 'react-native-gesture-handler';
import type { PanGesture } from 'react-native-gesture-handler';
import type { BottomSheetHandleProps } from '../bottomSheetHandle';
import type { BottomSheetBackdropProps } from '../bottomSheetBackdrop';
import type { BottomSheetBackgroundProps } from '../bottomSheetBackground';
Expand All @@ -24,17 +24,7 @@ import type {

export interface BottomSheetProps
extends BottomSheetAnimationConfigs,
Partial<
Pick<
PanGestureHandlerProps,
| 'activeOffsetY'
| 'activeOffsetX'
| 'failOffsetY'
| 'failOffsetX'
| 'waitFor'
| 'simultaneousHandlers'
>
>,
Partial<BottomSheetGestureProps>,
Omit<NullableAccessibilityProps, 'accessibilityHint'> {
//#region configuration
/**
Expand Down Expand Up @@ -346,3 +336,16 @@ export type AnimateToPositionType = (
velocity?: number,
configs?: WithTimingConfig | WithSpringConfig
) => void;

export type BottomSheetGestureProps = {
activeOffsetX: Parameters<PanGesture['activeOffsetX']>[0];
activeOffsetY: Parameters<PanGesture['activeOffsetY']>[0];

failOffsetY: Parameters<PanGesture['failOffsetY']>[0];
failOffsetX: Parameters<PanGesture['failOffsetX']>[0];

simultaneousHandlers: Parameters<
PanGesture['simultaneousWithExternalGesture']
>[0];
waitFor: Parameters<PanGesture['requireExternalGestureToFail']>[0];
};
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import React, { useMemo, useRef, memo } from 'react';
import React, { useMemo, memo } from 'react';
import Animated from 'react-native-reanimated';
import { PanGestureHandler } from 'react-native-gesture-handler';
import { GestureDetector, Gesture } from 'react-native-gesture-handler';
import {
useBottomSheetGestureHandlers,
useBottomSheetInternal,
} from '../../hooks';
import { GESTURE_SOURCE } from '../../constants';
import type { BottomSheetDraggableViewProps } from './types';
import { BottomSheetDraggableContext } from '../../contexts/gesture';

const BottomSheetDraggableViewComponent = ({
gestureType = GESTURE_SOURCE.CONTENT,
nativeGestureRef,
refreshControlGestureRef,
style,
Expand All @@ -26,19 +25,10 @@ const BottomSheetDraggableViewComponent = ({
failOffsetX,
failOffsetY,
} = useBottomSheetInternal();
const { contentPanGestureHandler, scrollablePanGestureHandler } =
useBottomSheetGestureHandlers();
const { contentPanGestureHandler } = useBottomSheetGestureHandlers();
//#endregion

//#region variables
const panGestureRef = useRef<PanGestureHandler>(null);
const gestureHandler = useMemo(
() =>
gestureType === GESTURE_SOURCE.CONTENT
? contentPanGestureHandler
: scrollablePanGestureHandler,
[gestureType, contentPanGestureHandler, scrollablePanGestureHandler]
);
const simultaneousHandlers = useMemo(() => {
const refs = [];

Expand All @@ -64,25 +54,66 @@ const BottomSheetDraggableViewComponent = ({
nativeGestureRef,
refreshControlGestureRef,
]);
const draggableGesture = useMemo(() => {
let gesture = Gesture.Pan()
.enabled(enableContentPanningGesture)
.shouldCancelWhenOutside(false)
.runOnJS(false)
.onStart(contentPanGestureHandler.handleOnStart)
.onChange(contentPanGestureHandler.handleOnChange)
.onEnd(contentPanGestureHandler.handleOnEnd)
.onFinalize(contentPanGestureHandler.handleOnFinalize);

if (waitFor) {
gesture = gesture.requireExternalGestureToFail(waitFor);
}

if (simultaneousHandlers) {
gesture = gesture.simultaneousWithExternalGesture(
simultaneousHandlers as any
);
}

if (activeOffsetX) {
gesture = gesture.activeOffsetX(activeOffsetX);
}

if (activeOffsetY) {
gesture = gesture.activeOffsetY(activeOffsetY);
}

if (failOffsetX) {
gesture = gesture.failOffsetX(failOffsetX);
}

if (failOffsetY) {
gesture = gesture.failOffsetY(failOffsetY);
}

return gesture;
}, [
activeOffsetX,
activeOffsetY,
enableContentPanningGesture,
failOffsetX,
failOffsetY,
simultaneousHandlers,
waitFor,
contentPanGestureHandler.handleOnChange,
contentPanGestureHandler.handleOnEnd,
contentPanGestureHandler.handleOnFinalize,
contentPanGestureHandler.handleOnStart,
]);
//#endregion

return (
<PanGestureHandler
ref={panGestureRef}
enabled={enableContentPanningGesture}
simultaneousHandlers={simultaneousHandlers}
shouldCancelWhenOutside={false}
waitFor={waitFor}
onGestureEvent={gestureHandler}
activeOffsetX={activeOffsetX}
activeOffsetY={activeOffsetY}
failOffsetX={failOffsetX}
failOffsetY={failOffsetY}
>
<Animated.View style={style} {...rest}>
{children}
</Animated.View>
</PanGestureHandler>
<GestureDetector gesture={draggableGesture}>
<BottomSheetDraggableContext.Provider value={draggableGesture}>
<Animated.View style={style} {...rest}>
{children}
</Animated.View>
</BottomSheetDraggableContext.Provider>
</GestureDetector>
);
};

Expand Down
Loading

0 comments on commit 4ffdf5c

Please sign in to comment.