Skip to content

Feat/new pan view improve animations #1574

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Oct 8, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions demo/src/screens/incubatorScreens/PanViewScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ class PanViewScreen extends Component {
<PanView
directions={[PanView.directions.DOWN]}
dismissible
springBack
animateToOrigin
// threshold={{y: 10}}
containerStyle={styles.panView}
onDismiss={this.onDialogDismissed}
Expand Down Expand Up @@ -113,7 +113,7 @@ class PanViewScreen extends Component {
<PanView
directions={[PanView.directions.LEFT, PanView.directions.DOWN, PanView.directions.RIGHT]}
dismissible
springBack
animateToOrigin
directionLock
threshold={{y: 10}}
containerStyle={styles.panView}
Expand Down
2 changes: 1 addition & 1 deletion generatedTypes/src/incubator/TransitionView/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { PropsWithChildren } from 'react';
import { ViewProps } from '../../components/view';
import { ForwardRefInjectedProps } from '../../commons/new';
import { Direction } from './useHiddenLocation';
import { Direction } from '../hooks/useHiddenLocation';
import { TransitionViewAnimationType } from './useAnimationEndNotifier';
import { AnimatedTransitionProps } from './useAnimatedTransition';
export { Direction, TransitionViewAnimationType };
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Direction, HiddenLocation } from './useHiddenLocation';
import { Direction, HiddenLocation } from '../hooks/useHiddenLocation';
import { AnimationNotifierEndProps } from './useAnimationEndNotifier';
export interface AnimatedTransitionProps extends AnimationNotifierEndProps {
/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Direction } from './useHiddenLocation';
import { Direction } from '../hooks/useHiddenLocation';
export interface TranslatorProps {
initialVisibility: boolean;
}
Expand Down
2 changes: 1 addition & 1 deletion generatedTypes/src/incubator/panView/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export interface PanViewProps extends ViewProps {
/**
* Animate to start if not dismissed.
*/
springBack?: boolean;
animateToOrigin?: boolean;
/**
* Callback to the dismiss animation end
*/
Expand Down
8 changes: 8 additions & 0 deletions generatedTypes/src/uilib-test-renderer/helper.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
interface Props {
style: any;
}
interface Component {
props: Props;
}
declare const findStyle: <T>(key: string, component: Component) => T;
export { findStyle };
3 changes: 3 additions & 0 deletions generatedTypes/src/uilib-test-renderer/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from '@testing-library/react-native';
import { findStyle } from './helper';
export { findStyle };
2 changes: 1 addition & 1 deletion src/incubator/TransitionView/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {View as RNView, LayoutChangeEvent} from 'react-native';
import Animated from 'react-native-reanimated';
import View, {ViewProps} from '../../components/view';
import {forwardRef, ForwardRefInjectedProps} from '../../commons/new';
import useHiddenLocation, {Direction} from './useHiddenLocation';
import useHiddenLocation, {Direction} from '../hooks/useHiddenLocation';
import {TransitionViewAnimationType} from './useAnimationEndNotifier';
import useAnimatedTransition, {AnimatedTransitionProps} from './useAnimatedTransition';
const AnimatedView = Animated.createAnimatedComponent(View);
Expand Down
2 changes: 1 addition & 1 deletion src/incubator/TransitionView/useAnimatedTransition.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* eslint-disable react-hooks/exhaustive-deps */
import {useEffect, useCallback} from 'react';
import {Direction, HiddenLocation} from './useHiddenLocation';
import {Direction, HiddenLocation} from '../hooks/useHiddenLocation';
import useAnimatedTranslator from './useAnimatedTranslator';
import useAnimationEndNotifier, {AnimationNotifierEndProps} from './useAnimationEndNotifier';

Expand Down
2 changes: 1 addition & 1 deletion src/incubator/TransitionView/useAnimatedTranslator.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {useCallback} from 'react';
import {useSharedValue, useAnimatedStyle, withSpring, withTiming} from 'react-native-reanimated';
import {Direction} from './useHiddenLocation';
import {Direction} from '../hooks/useHiddenLocation';

export interface TranslatorProps {
initialVisibility: boolean;
Expand Down
56 changes: 26 additions & 30 deletions src/incubator/panView/index.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import {isEmpty} from 'lodash';
import React, {useCallback} from 'react';
import {StyleProp, ViewStyle} from 'react-native';
import {StyleProp, View as RNView, ViewStyle} from 'react-native';
import {PanGestureHandler, PanGestureHandlerEventPayload} from 'react-native-gesture-handler';
import Animated, {
useSharedValue,
useAnimatedStyle,
withSpring,
withTiming,
useAnimatedGestureHandler,
runOnJS
} from 'react-native-reanimated';
import {asBaseComponent} from '../../commons/new';
import {Constants} from '../../helpers';
import View, {ViewProps} from '../../components/view';
import {
PanViewDirections,
Expand All @@ -20,6 +20,7 @@ import {
getDismissVelocity,
DEFAULT_THRESHOLD
} from './panningUtil';
import useHiddenLocation from '../hooks/useHiddenLocation';
export {PanViewDirections, PanViewDismissThreshold};

export interface PanViewProps extends ViewProps {
Expand All @@ -35,7 +36,7 @@ export interface PanViewProps extends ViewProps {
/**
* Animate to start if not dismissed.
*/
springBack?: boolean;
animateToOrigin?: boolean;
/**
* Callback to the dismiss animation end
*/
Expand Down Expand Up @@ -64,7 +65,7 @@ const PanView = (props: Props) => {
const {
directions = [PanViewDirections.UP, PanViewDirections.DOWN, PanViewDirections.LEFT, PanViewDirections.RIGHT],
dismissible,
springBack,
animateToOrigin,
onDismiss,
directionLock,
threshold,
Expand All @@ -82,6 +83,9 @@ const PanView = (props: Props) => {
};
}, []);

const containerRef = React.createRef<RNView>();
const {onLayout, hiddenLocation} = useHiddenLocation({containerRef});

const getTranslationOptions = () => {
'worklet';
return {
Expand All @@ -105,27 +109,17 @@ const PanView = (props: Props) => {
runOnJS(onDismiss)();
}
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[onDismiss]);

const shouldDismissX = useCallback((isFinished: boolean) => {
'worklet';
dismiss(isFinished);
},
[dismiss]);

const shouldDismissY = useCallback((isFinished: boolean) => {
const returnToOrigin = useCallback(() => {
'worklet';
dismiss(isFinished);
},
[dismiss]);

const springBackIfNeeded = useCallback(() => {
'worklet';
if (springBack) {
if (animateToOrigin) {
translationX.value = withSpring(0, SPRING_BACK_ANIMATION_CONFIG);
translationY.value = withSpring(0, SPRING_BACK_ANIMATION_CONFIG);
}
}, [springBack]);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [animateToOrigin]);

const onGestureEvent = useAnimatedGestureHandler({
onStart: (_event: PanGestureHandlerEventPayload, context: {initialTranslation: Frame}) => {
Expand All @@ -139,28 +133,30 @@ const PanView = (props: Props) => {
const velocity = getDismissVelocity(event, directions, getTranslationOptions(), threshold);
if (velocity) {
waitingForDismiss.value = true;
if (velocity.x !== 0) {
const toX = Math.sign(translationX.value) * (Math.abs(translationX.value) + Constants.screenWidth);
translationX.value = withSpring(toX, {velocity: velocity.x, damping: 50}, shouldDismissX);
if (translationX.value !== 0 && velocity.x !== undefined && velocity.x !== 0) {
const toX = velocity.x > 0 ? hiddenLocation.right : hiddenLocation.left;
const duration = Math.abs((toX - translationX.value) / velocity.x) * 1000;
translationX.value = withTiming(toX, {duration}, dismiss);
}
if (velocity.y !== 0) {
const toY = Math.sign(translationY.value) * (Math.abs(translationY.value) + Constants.screenHeight);
translationY.value = withSpring(toY, {velocity: velocity.y, damping: 50}, shouldDismissY);

if (translationY.value !== 0 && velocity.y !== undefined && velocity.y !== 0) {
const toY = velocity.y > 0 ? hiddenLocation.bottom : hiddenLocation.top;
const duration = Math.abs((toY - translationY.value) / velocity.y) * 1000;
translationY.value = withTiming(toY, {duration}, dismiss);
}
} else {
springBackIfNeeded();
returnToOrigin();
}
} else {
springBackIfNeeded();
returnToOrigin();
}
}
},
[directions, dismissible, setTranslation, springBackIfNeeded]);
[directions, dismissible, setTranslation, returnToOrigin]);

return (
// TODO: delete comments once completed
// <View ref={containerRef} style={containerStyle} onLayout={onLayout}>
<View style={containerStyle}>
<View ref={containerRef} style={containerStyle} onLayout={onLayout}>
<PanGestureHandler onGestureEvent={isEmpty(directions) ? undefined : onGestureEvent}>
<Animated.View
// !visible.current && styles.hidden is done to fix a bug is iOS
Expand Down