1
1
import { isEmpty } from 'lodash' ;
2
2
import React , { useCallback } from 'react' ;
3
- import { StyleProp , ViewStyle } from 'react-native' ;
3
+ import { StyleProp , View as RNView , ViewStyle } from 'react-native' ;
4
4
import { PanGestureHandler , PanGestureHandlerEventPayload } from 'react-native-gesture-handler' ;
5
5
import Animated , {
6
6
useSharedValue ,
7
7
useAnimatedStyle ,
8
8
withSpring ,
9
+ withTiming ,
9
10
useAnimatedGestureHandler ,
10
11
runOnJS
11
12
} from 'react-native-reanimated' ;
12
13
import { asBaseComponent } from '../../commons/new' ;
13
- import { Constants } from '../../helpers' ;
14
14
import View , { ViewProps } from '../../components/view' ;
15
15
import {
16
16
PanViewDirections ,
@@ -20,6 +20,7 @@ import {
20
20
getDismissVelocity ,
21
21
DEFAULT_THRESHOLD
22
22
} from './panningUtil' ;
23
+ import useHiddenLocation from '../hooks/useHiddenLocation' ;
23
24
export { PanViewDirections , PanViewDismissThreshold } ;
24
25
25
26
export interface PanViewProps extends ViewProps {
@@ -35,7 +36,7 @@ export interface PanViewProps extends ViewProps {
35
36
/**
36
37
* Animate to start if not dismissed.
37
38
*/
38
- springBack ?: boolean ;
39
+ animateToOrigin ?: boolean ;
39
40
/**
40
41
* Callback to the dismiss animation end
41
42
*/
@@ -64,7 +65,7 @@ const PanView = (props: Props) => {
64
65
const {
65
66
directions = [ PanViewDirections . UP , PanViewDirections . DOWN , PanViewDirections . LEFT , PanViewDirections . RIGHT ] ,
66
67
dismissible,
67
- springBack ,
68
+ animateToOrigin ,
68
69
onDismiss,
69
70
directionLock,
70
71
threshold,
@@ -82,6 +83,9 @@ const PanView = (props: Props) => {
82
83
} ;
83
84
} , [ ] ) ;
84
85
86
+ const containerRef = React . createRef < RNView > ( ) ;
87
+ const { onLayout, hiddenLocation} = useHiddenLocation ( { containerRef} ) ;
88
+
85
89
const getTranslationOptions = ( ) => {
86
90
'worklet' ;
87
91
return {
@@ -105,27 +109,17 @@ const PanView = (props: Props) => {
105
109
runOnJS ( onDismiss ) ( ) ;
106
110
}
107
111
} ,
112
+ // eslint-disable-next-line react-hooks/exhaustive-deps
108
113
[ onDismiss ] ) ;
109
114
110
- const shouldDismissX = useCallback ( ( isFinished : boolean ) => {
111
- 'worklet' ;
112
- dismiss ( isFinished ) ;
113
- } ,
114
- [ dismiss ] ) ;
115
-
116
- const shouldDismissY = useCallback ( ( isFinished : boolean ) => {
115
+ const returnToOrigin = useCallback ( ( ) => {
117
116
'worklet' ;
118
- dismiss ( isFinished ) ;
119
- } ,
120
- [ dismiss ] ) ;
121
-
122
- const springBackIfNeeded = useCallback ( ( ) => {
123
- 'worklet' ;
124
- if ( springBack ) {
117
+ if ( animateToOrigin ) {
125
118
translationX . value = withSpring ( 0 , SPRING_BACK_ANIMATION_CONFIG ) ;
126
119
translationY . value = withSpring ( 0 , SPRING_BACK_ANIMATION_CONFIG ) ;
127
120
}
128
- } , [ springBack ] ) ;
121
+ // eslint-disable-next-line react-hooks/exhaustive-deps
122
+ } , [ animateToOrigin ] ) ;
129
123
130
124
const onGestureEvent = useAnimatedGestureHandler ( {
131
125
onStart : ( _event : PanGestureHandlerEventPayload , context : { initialTranslation : Frame } ) => {
@@ -139,28 +133,30 @@ const PanView = (props: Props) => {
139
133
const velocity = getDismissVelocity ( event , directions , getTranslationOptions ( ) , threshold ) ;
140
134
if ( velocity ) {
141
135
waitingForDismiss . value = true ;
142
- if ( velocity . x !== 0 ) {
143
- const toX = Math . sign ( translationX . value ) * ( Math . abs ( translationX . value ) + Constants . screenWidth ) ;
144
- translationX . value = withSpring ( toX , { velocity : velocity . x , damping : 50 } , shouldDismissX ) ;
136
+ if ( translationX . value !== 0 && velocity . x !== undefined && velocity . x !== 0 ) {
137
+ const toX = velocity . x > 0 ? hiddenLocation . right : hiddenLocation . left ;
138
+ const duration = Math . abs ( ( toX - translationX . value ) / velocity . x ) * 1000 ;
139
+ translationX . value = withTiming ( toX , { duration} , dismiss ) ;
145
140
}
146
- if ( velocity . y !== 0 ) {
147
- const toY = Math . sign ( translationY . value ) * ( Math . abs ( translationY . value ) + Constants . screenHeight ) ;
148
- translationY . value = withSpring ( toY , { velocity : velocity . y , damping : 50 } , shouldDismissY ) ;
141
+
142
+ if ( translationY . value !== 0 && velocity . y !== undefined && velocity . y !== 0 ) {
143
+ const toY = velocity . y > 0 ? hiddenLocation . bottom : hiddenLocation . top ;
144
+ const duration = Math . abs ( ( toY - translationY . value ) / velocity . y ) * 1000 ;
145
+ translationY . value = withTiming ( toY , { duration} , dismiss ) ;
149
146
}
150
147
} else {
151
- springBackIfNeeded ( ) ;
148
+ returnToOrigin ( ) ;
152
149
}
153
150
} else {
154
- springBackIfNeeded ( ) ;
151
+ returnToOrigin ( ) ;
155
152
}
156
153
}
157
154
} ,
158
- [ directions , dismissible , setTranslation , springBackIfNeeded ] ) ;
155
+ [ directions , dismissible , setTranslation , returnToOrigin ] ) ;
159
156
160
157
return (
161
158
// TODO: delete comments once completed
162
- // <View ref={containerRef} style={containerStyle} onLayout={onLayout}>
163
- < View style = { containerStyle } >
159
+ < View ref = { containerRef } style = { containerStyle } onLayout = { onLayout } >
164
160
< PanGestureHandler onGestureEvent = { isEmpty ( directions ) ? undefined : onGestureEvent } >
165
161
< Animated . View
166
162
// !visible.current && styles.hidden is done to fix a bug is iOS
0 commit comments