Browse Source

feat: add swipe handler to entire bottom sheet

j8
Bettenbuk Zoltan 5 years ago
parent
commit
9b60537e0f

+ 0
- 5
package-lock.json View File

@@ -14873,11 +14873,6 @@
14873 14873
         }
14874 14874
       }
14875 14875
     },
14876
-    "react-native-swipe-gestures": {
14877
-      "version": "1.0.4",
14878
-      "resolved": "https://registry.npmjs.org/react-native-swipe-gestures/-/react-native-swipe-gestures-1.0.4.tgz",
14879
-      "integrity": "sha512-C/vz0KPHNyqHk3uF4Cz/jzd/0N8z34ZgsjAZUh/RsXPH2FtJJf3Fw73pQDWJSoCMtvVadlztb8xQ+/aEQrll7w=="
14880
-    },
14881 14876
     "react-native-swipeout": {
14882 14877
       "version": "2.3.6",
14883 14878
       "resolved": "https://registry.npmjs.org/react-native-swipeout/-/react-native-swipeout-2.3.6.tgz",

+ 0
- 1
package.json View File

@@ -77,7 +77,6 @@
77 77
     "react-native-sound": "0.11.0",
78 78
     "react-native-svg": "9.7.1",
79 79
     "react-native-svg-transformer": "0.13.0",
80
-    "react-native-swipe-gestures": "1.0.4",
81 80
     "react-native-swipeout": "2.3.6",
82 81
     "react-native-watch-connectivity": "0.2.0",
83 82
     "react-native-webrtc": "1.75.2",

+ 77
- 2
react/features/base/dialog/components/native/BottomSheet.js View File

@@ -1,7 +1,7 @@
1 1
 // @flow
2 2
 
3 3
 import React, { PureComponent, type Node } from 'react';
4
-import { SafeAreaView, ScrollView, View } from 'react-native';
4
+import { PanResponder, SafeAreaView, ScrollView, View } from 'react-native';
5 5
 
6 6
 import { ColorSchemeRegistry } from '../../../color-scheme';
7 7
 import { SlidingView } from '../../../react';
@@ -10,6 +10,16 @@ import { StyleType } from '../../../styles';
10 10
 
11 11
 import { bottomSheetStyles as styles } from './styles';
12 12
 
13
+/**
14
+ * Minimal distance that needs to be moved by the finger to consider it a swipe.
15
+ */
16
+const GESTURE_DISTANCE_THRESHOLD = 5;
17
+
18
+/**
19
+ * The minimal speed needed to be achieved by the finger to consider it as a swipe.
20
+ */
21
+const GESTURE_SPEED_THRESHOLD = 0.2;
22
+
13 23
 /**
14 24
  * The type of {@code BottomSheet}'s React {@code Component} prop types.
15 25
  */
@@ -31,6 +41,11 @@ type Props = {
31 41
      */
32 42
     onCancel: ?Function,
33 43
 
44
+    /**
45
+     * Callback to be attached to the custom swipe event of the BottomSheet.
46
+     */
47
+    onSwipe?: Function,
48
+
34 49
     /**
35 50
      * Function to render a bottom sheet header element, if necessary.
36 51
      */
@@ -41,6 +56,23 @@ type Props = {
41 56
  * A component emulating Android's BottomSheet.
42 57
  */
43 58
 class BottomSheet extends PureComponent<Props> {
59
+    panResponder: Object;
60
+
61
+    /**
62
+     * Instantiates a new component.
63
+     *
64
+     * @inheritdoc
65
+     */
66
+    constructor(props: Props) {
67
+        super(props);
68
+
69
+        this.panResponder = PanResponder.create({
70
+            onStartShouldSetPanResponder: this._onShouldSetResponder.bind(this),
71
+            onMoveShouldSetPanResponder: this._onShouldSetResponder.bind(this),
72
+            onPanResponderRelease: this._onGestureEnd.bind(this)
73
+        });
74
+    }
75
+
44 76
     /**
45 77
      * Implements React's {@link Component#render()}.
46 78
      *
@@ -66,7 +98,8 @@ class BottomSheet extends PureComponent<Props> {
66 98
                         style = { [
67 99
                             styles.sheetItemContainer,
68 100
                             _styles.sheet
69
-                        ] }>
101
+                        ] }
102
+                        { ...this.panResponder.panHandlers }>
70 103
                         <ScrollView
71 104
                             bounces = { false }
72 105
                             showsVerticalScrollIndicator = { false }
@@ -78,6 +111,48 @@ class BottomSheet extends PureComponent<Props> {
78 111
             </SlidingView>
79 112
         );
80 113
     }
114
+
115
+    /**
116
+     * Callback to handle a gesture end event.
117
+     *
118
+     * @param {Object} evt - The native gesture event.
119
+     * @param {Object} gestureState - The gesture state.
120
+     * @returns {void}
121
+     */
122
+    _onGestureEnd(evt, gestureState) {
123
+        const verticalSwipe = Math.abs(gestureState.vy) > Math.abs(gestureState.vx)
124
+            && Math.abs(gestureState.vy) > GESTURE_SPEED_THRESHOLD;
125
+
126
+        if (verticalSwipe) {
127
+            const direction = gestureState.vy > 0 ? 'down' : 'up';
128
+            const { onCancel, onSwipe } = this.props;
129
+            let isSwipeHandled = false;
130
+
131
+            if (onSwipe) {
132
+                isSwipeHandled = onSwipe(direction);
133
+            }
134
+
135
+            if (direction === 'down' && !isSwipeHandled) {
136
+                // Swipe down is a special gesture that can be used to close the
137
+                // BottomSheet, so if the swipe is not handled by the parent
138
+                // component, we consider it as a request to close.
139
+                onCancel && onCancel();
140
+            }
141
+        }
142
+    }
143
+
144
+    /**
145
+     * Returns true if the pan responder should activate, false otherwise.
146
+     *
147
+     * @param {Object} evt - The native gesture event.
148
+     * @param {Object} gestureState - The gesture state.
149
+     * @returns {boolean}
150
+     */
151
+    _onShouldSetResponder({ nativeEvent }, gestureState) {
152
+        return nativeEvent.touches.length === 1
153
+            && Math.abs(gestureState.dx) > GESTURE_DISTANCE_THRESHOLD
154
+            && Math.abs(gestureState.dy) > GESTURE_DISTANCE_THRESHOLD;
155
+    }
81 156
 }
82 157
 
83 158
 /**

+ 26
- 28
react/features/toolbox/components/native/OverflowMenu.js View File

@@ -1,9 +1,8 @@
1 1
 // @flow
2 2
 
3 3
 import React, { PureComponent } from 'react';
4
-import { Platform, TouchableOpacity } from 'react-native';
4
+import { Platform, TouchableOpacity, View } from 'react-native';
5 5
 import Collapsible from 'react-native-collapsible';
6
-import GestureRecognizer, { swipeDirections } from 'react-native-swipe-gestures';
7 6
 
8 7
 import { ColorSchemeRegistry } from '../../../base/color-scheme';
9 8
 import { BottomSheet, hideDialog, isDialogOpen } from '../../../base/dialog';
@@ -59,6 +58,11 @@ type Props = {
59 58
 
60 59
 type State = {
61 60
 
61
+    /**
62
+     * True if the bottom scheet is scrolled to the top.
63
+     */
64
+    scrolledToTop: boolean,
65
+
62 66
     /**
63 67
      * True if the 'more' button set needas to be rendered.
64 68
      */
@@ -88,6 +92,7 @@ class OverflowMenu extends PureComponent<Props, State> {
88 92
         super(props);
89 93
 
90 94
         this.state = {
95
+            scrolledToTop: true,
91 96
             showMore: false
92 97
         };
93 98
 
@@ -117,6 +122,7 @@ class OverflowMenu extends PureComponent<Props, State> {
117 122
         return (
118 123
             <BottomSheet
119 124
                 onCancel = { this._onCancel }
125
+                onSwipe = { this._onSwipe }
120 126
                 renderHeader = { this._renderMenuExpandToggle }>
121 127
                 <AudioRouteButton { ...buttonProps } />
122 128
                 <ToggleCameraButton { ...buttonProps } />
@@ -152,12 +158,7 @@ class OverflowMenu extends PureComponent<Props, State> {
152 158
      */
153 159
     _renderMenuExpandToggle() {
154 160
         return (
155
-            <GestureRecognizer
156
-                config = {{
157
-                    velocityThreshold: 0.1,
158
-                    directionalOffsetThreshold: 30
159
-                }}
160
-                onSwipe = { this._onSwipe }
161
+            <View
161 162
                 style = { [
162 163
                     this.props._bottomSheetStyles.sheet,
163 164
                     styles.expandMenuContainer
@@ -166,7 +167,7 @@ class OverflowMenu extends PureComponent<Props, State> {
166 167
                     { /* $FlowFixMeProps */ }
167 168
                     <IconDragHandle style = { this.props._bottomSheetStyles.expandIcon } />
168 169
                 </TouchableOpacity>
169
-            </GestureRecognizer>
170
+            </View>
170 171
         );
171 172
     }
172 173
 
@@ -188,34 +189,31 @@ class OverflowMenu extends PureComponent<Props, State> {
188 189
         return false;
189 190
     }
190 191
 
191
-    _onSwipe: (string) => void;
192
+    _onSwipe: string => void;
192 193
 
193 194
     /**
194
-     * Callback to be invoked when a swipe gesture is detected on the menu.
195
+     * Callback to be invoked when swipe gesture is detected on the menu. Returns true
196
+     * if the swipe gesture is handled by the menu, false otherwise.
195 197
      *
196
-     * @param {string} gestureName - The name of the swipe gesture.
197
-     * @returns {void}
198
+     * @param {string} direction - Direction of 'up' or 'down'.
199
+     * @returns {boolean}
198 200
      */
199
-    _onSwipe(gestureName) {
201
+    _onSwipe(direction) {
200 202
         const { showMore } = this.state;
201 203
 
202
-        switch (gestureName) {
203
-        case swipeDirections.SWIPE_UP:
204
+        switch (direction) {
205
+        case 'up':
204 206
             !showMore && this.setState({
205 207
                 showMore: true
206 208
             });
207
-            break;
208
-        case swipeDirections.SWIPE_DOWN:
209
-            if (showMore) {
210
-                // If the menu is expanded, we collapse it.
211
-                this.setState({
212
-                    showMore: false
213
-                });
214
-            } else {
215
-                // If the menu is not expanded, we close the menu
216
-                this._onCancel();
217
-            }
218
-            break;
209
+
210
+            return !showMore;
211
+        case 'down':
212
+            showMore && this.setState({
213
+                showMore: false
214
+            });
215
+
216
+            return showMore;
219 217
         }
220 218
     }
221 219
 

+ 5
- 0
react/features/toolbox/components/native/styles.js View File

@@ -60,6 +60,11 @@ const styles = {
60 60
         flexDirection: 'column'
61 61
     },
62 62
 
63
+    sheetGestureRecognizer: {
64
+        alignItems: 'stretch',
65
+        flexDirection: 'column'
66
+    },
67
+
63 68
     /**
64 69
      * The style of the toolbar.
65 70
      */

Loading…
Cancel
Save