@@ -9,17 +9,14 @@ import {
9
9
StatusBar ,
10
10
Text ,
11
11
TouchableWithoutFeedback ,
12
- View
12
+ View ,
13
13
} from 'react-native' ;
14
14
import Icon from 'react-native-vector-icons/Ionicons' ;
15
- import ExtraDimensions from 'react-native-extra-dimensions-android' ;
16
15
17
16
// Get screen dimensions
18
- const { width } = Dimensions . get ( 'window' ) ;
19
- const height = Platform . OS === 'ios' ? Dimensions . get ( 'screen' ) . height : Dimensions . get ( 'screen' ) . height - ExtraDimensions . get ( 'SOFT_MENU_BAR_HEIGHT' ) ;
17
+ const { width, height } = Dimensions . get ( 'window' ) ;
20
18
21
19
export default class Drawer extends Component {
22
-
23
20
// Define prop types
24
21
static propTypes = {
25
22
// Pass messages to show as children
@@ -32,7 +29,6 @@ export default class Drawer extends Component {
32
29
headerHeight : PropTypes . number ,
33
30
// Height of the visible teaser area at the bottom of the screen
34
31
teaserHeight : PropTypes . number ,
35
- onClose : PropTypes . func ,
36
32
} ;
37
33
38
34
// Set default prop values
@@ -41,7 +37,6 @@ export default class Drawer extends Component {
41
37
header : 'Messages' ,
42
38
headerHeight : 70 ,
43
39
teaserHeight : 75 ,
44
- onClose :( ) => { }
45
40
} ;
46
41
47
42
// Define state
@@ -67,20 +62,17 @@ export default class Drawer extends Component {
67
62
// minimal possible value - a bit lower the top of the screen
68
63
min : this . props . headerHeight ,
69
64
// When animated triggers these value updates
70
- animates : [
71
- ( ) => this . _animatedOpacity ,
72
- ( ) => this . _animatedWidth
73
- ]
65
+ animates : [ ( ) => this . _animatedOpacity , ( ) => this . _animatedWidth ] ,
74
66
} ,
75
67
// Window width
76
68
width : {
77
- end : width , // takes full with once opened
78
- start : width - 20 , // slightly narrower than screen when closed
69
+ end : width , // takes full with once opened
70
+ start : width - 20 , // slightly narrower than screen when closed
79
71
} ,
80
72
// Window backdrop opacity
81
73
opacity : {
82
- start : 0 , // fully transparent when closed
83
- end : 1 // not transparent once opened
74
+ start : 0 , // fully transparent when closed
75
+ end : 1 , // not transparent once opened
84
76
} ,
85
77
} ;
86
78
@@ -94,9 +86,9 @@ export default class Drawer extends Component {
94
86
_animatedWidth = new Animated . Value ( this . config . width . start ) ;
95
87
96
88
// Animates window position
97
- _animatedPosition = new Animated . Value ( this . props . isOpen
98
- ? this . config . position . end
99
- : this . config . position . start ) ;
89
+ _animatedPosition = new Animated . Value (
90
+ this . props . isOpen ? this . config . position . end : this . config . position . start ,
91
+ ) ;
100
92
101
93
componentWillMount ( ) {
102
94
// Set current position
@@ -106,9 +98,9 @@ export default class Drawer extends Component {
106
98
// Update _currentPosition
107
99
this . _currentPosition = value . value ;
108
100
// Animate depending values
109
- this . config . position . animates . map ( item => {
101
+ this . config . position . animates . map ( ( item ) => {
110
102
item ( ) . setValue ( value . value ) ;
111
- } )
103
+ } ) ;
112
104
} ) ;
113
105
// Reset value once listener is registered to update depending animations
114
106
this . _animatedPosition . setValue ( this . _animatedPosition . _value ) ;
@@ -132,9 +124,8 @@ export default class Drawer extends Component {
132
124
// isOpen prop changed to true from false
133
125
if ( ! this . props . isOpen && nextProps . isOpen ) {
134
126
this . open ( ) ;
135
- }
136
- // isOpen prop changed to false from true
137
- else if ( this . props . isOpen && ! nextProps . isOpen ) {
127
+ } else if ( this . props . isOpen && ! nextProps . isOpen ) {
128
+ // isOpen prop changed to false from true
138
129
this . close ( ) ;
139
130
}
140
131
}
@@ -148,21 +139,23 @@ export default class Drawer extends Component {
148
139
} ) ,
149
140
// Interpolate position value into width value
150
141
animatedWidth = this . _animatedWidth . interpolate ( {
151
- inputRange : [ this . config . position . min , // top of the screen
152
- this . config . position . start - 50 , // 50 pixels higher than next point
153
- this . config . position . start , // a bit higher than the bottom of the screen
154
- this . config . position . max // the bottom of the screen
142
+ inputRange : [
143
+ this . config . position . min , // top of the screen
144
+ this . config . position . start - 50 , // 50 pixels higher than next point
145
+ this . config . position . start , // a bit higher than the bottom of the screen
146
+ this . config . position . max , // the bottom of the screen
155
147
] ,
156
- outputRange : [ this . config . width . end , // keep max width after next point
157
- this . config . width . end , // end: max width at 50 pixel higher
158
- this . config . width . start , // start: min width at the bottom
159
- this . config . width . start // keep min width before previous point
148
+ outputRange : [
149
+ this . config . width . end , // keep max width after next point
150
+ this . config . width . end , // end: max width at 50 pixel higher
151
+ this . config . width . start , // start: min width at the bottom
152
+ this . config . width . start , // keep min width before previous point
160
153
] ,
161
154
} ) ;
162
155
return (
163
156
< Animated . View style = { [ styles . container , this . getContainerStyle ( ) ] } >
164
157
{ /* Use light status bar because we have dark background */ }
165
- < StatusBar barStyle = { " light-content" } />
158
+ < StatusBar barStyle = { ' light-content' } />
166
159
{ /* Backdrop with animated opacity */ }
167
160
< Animated . View style = { [ styles . backdrop , { opacity : animatedOpacity } ] } >
168
161
{ /* Close window when tapped on header */ }
@@ -181,20 +174,28 @@ export default class Drawer extends Component {
181
174
</ Animated . View >
182
175
{ /* Content container */ }
183
176
< Animated . View
184
- style = { [ styles . content , {
185
- // Add padding at the bottom to fit all content on the screen
186
- paddingBottom : this . props . headerHeight ,
187
- // Animate width
188
- width : animatedWidth ,
189
- // Animate position on the screen
190
- transform : [ { translateY : this . _animatedPosition } , { translateX : 0 } ]
191
- } ] }
177
+ style = { [
178
+ styles . content ,
179
+ {
180
+ // Add padding at the bottom to fit all content on the screen
181
+ paddingBottom : this . props . headerHeight ,
182
+ // Animate width
183
+ width : animatedWidth ,
184
+ // Animate position on the screen
185
+ transform : [
186
+ { translateY : this . _animatedPosition } ,
187
+ { translateX : 0 } ,
188
+ ] ,
189
+ } ,
190
+ ] }
192
191
// Handle gestures
193
192
{ ...this . _panResponder . panHandlers }
194
193
>
195
194
{ /* Put all content in a scrollable container */ }
196
195
< ScrollView
197
- ref = { ( scrollView ) => { this . _scrollView = scrollView ; } }
196
+ ref = { ( scrollView ) => {
197
+ this . _scrollView = scrollView ;
198
+ } }
198
199
// Enable scrolling only when the window is open
199
200
scrollEnabled = { this . state . open }
200
201
// Hide all scrolling indicators
@@ -217,13 +218,11 @@ export default class Drawer extends Component {
217
218
// Allow if is not open
218
219
if ( ! this . state . open ) {
219
220
return true ;
220
- }
221
- // Allow if user haven't scroll the content yet
222
- else if ( this . pulledDown ( gestureState ) && this . state . scrollOffset <= 0 ) {
221
+ } else if ( this . pulledDown ( gestureState ) && this . state . scrollOffset <= 0 ) {
222
+ // Allow if user haven't scroll the content yet
223
223
return true ;
224
- }
225
- // Allow if pulled down rapidly
226
- else if ( this . pulledDown ( gestureState ) && this . pulledFast ( gestureState ) ) {
224
+ } else if ( this . pulledDown ( gestureState ) && this . pulledFast ( gestureState ) ) {
225
+ // Allow if pulled down rapidly
227
226
return true ;
228
227
}
229
228
// Deny otherwise
@@ -257,46 +256,42 @@ export default class Drawer extends Component {
257
256
// Pulled down and far enough to trigger close
258
257
if ( this . pulledDown ( gestureState ) && this . pulledFar ( gestureState ) ) {
259
258
return this . close ( ) ;
260
- }
261
- // Pulled up and far enough to trigger open
262
- else if ( this . pulledUp ( gestureState ) && this . pulledFar ( gestureState ) ) {
259
+ } else if ( this . pulledUp ( gestureState ) && this . pulledFar ( gestureState ) ) {
260
+ // Pulled up and far enough to trigger open
263
261
return this . open ( ) ;
264
- }
265
- // Toggle if tapped
266
- else if ( this . tapped ( gestureState ) ) {
262
+ } else if ( this . tapped ( gestureState ) ) {
263
+ // Toggle if tapped
267
264
return this . toggle ( ) ;
268
265
}
269
266
// Restore back to appropriate position otherwise
270
- else {
271
- this . restore ( ) ;
272
- }
267
+ this . restore ( ) ;
273
268
} ;
274
269
275
270
// Handle content scrolling
276
- _handleScroll = event => {
271
+ _handleScroll = ( event ) => {
277
272
const { y } = event . nativeEvent . contentOffset ;
278
273
this . setState ( { scrollOffset : y } ) ;
279
274
} ;
280
275
281
276
// Check if gesture was a tap
282
- tapped = ( gestureState ) => gestureState . dx === 0 && gestureState . dy === 0 ;
277
+ tapped = gestureState => gestureState . dx === 0 && gestureState . dy === 0 ;
283
278
284
279
// Check if pulled up
285
- pulledUp = ( gestureState ) => gestureState . dy < 0 ;
280
+ pulledUp = gestureState => gestureState . dy < 0 ;
286
281
287
282
// Check if pulled down
288
- pulledDown = ( gestureState ) => gestureState . dy > 0 ;
283
+ pulledDown = gestureState => gestureState . dy > 0 ;
289
284
290
285
// Check if pulled rapidly
291
- pulledFast = ( gestureState ) => Math . abs ( gestureState . vy ) > 0.75 ;
286
+ pulledFast = gestureState => Math . abs ( gestureState . vy ) > 0.75 ;
292
287
293
288
// Check if pulled far
294
- pulledFar = ( gestureState ) => Math . abs ( gestureState . dy ) > 50 ;
289
+ pulledFar = gestureState => Math . abs ( gestureState . dy ) > 50 ;
295
290
296
291
// Check if current position is inside allowed range
297
292
insideAllowedRange = ( ) =>
298
- this . _currentPosition >= this . config . position . min
299
- && this . _currentPosition <= this . config . position . max ;
293
+ this . _currentPosition >= this . config . position . min &&
294
+ this . _currentPosition <= this . config . position . max ;
300
295
301
296
// Open up the window on full screen
302
297
open = ( ) => {
@@ -310,22 +305,24 @@ export default class Drawer extends Component {
310
305
311
306
// Minimize window and keep a teaser at the bottom
312
307
close = ( ) => {
313
- this . props . onClose ( ) ;
314
308
this . _scrollView . scrollTo ( { y : 0 } ) ;
315
309
Animated . timing ( this . _animatedPosition , {
316
310
toValue : this . config . position . start ,
317
311
duration : 400 ,
318
- } ) . start ( ( ) => this . setState ( {
319
- open : false ,
320
- } ) ) ;
312
+ } ) . start ( ( ) => {
313
+ this . setState ( {
314
+ open : false ,
315
+ } ) ;
316
+
317
+ this . _scrollView . scrollTo ( { y : 0 } ) ;
318
+ } ) ;
321
319
} ;
322
320
323
321
// Toggle window state between opened and closed
324
322
toggle = ( ) => {
325
323
if ( ! this . state . open ) {
326
324
this . open ( ) ;
327
- }
328
- else {
325
+ } else {
329
326
this . close ( ) ;
330
327
}
331
328
} ;
@@ -334,17 +331,17 @@ export default class Drawer extends Component {
334
331
restore = ( ) => {
335
332
if ( this . state . open ) {
336
333
this . open ( ) ;
337
- }
338
- else {
334
+ } else {
339
335
this . close ( ) ;
340
336
}
341
337
} ;
342
338
343
339
// Get header style
344
340
getHeaderStyle = ( ) => ( {
345
- height : Platform . OS === 'ios'
346
- ? this . props . headerHeight
347
- : this . props . headerHeight - 40 , // compensate for the status bar
341
+ height :
342
+ Platform . OS === 'ios'
343
+ ? this . props . headerHeight
344
+ : this . props . headerHeight - 40 , // compensate for the status bar
348
345
} ) ;
349
346
350
347
// Get container style
@@ -358,36 +355,36 @@ export default class Drawer extends Component {
358
355
const styles = StyleSheet . create ( {
359
356
// Main container
360
357
container : {
361
- ...StyleSheet . absoluteFillObject , // fill up all screen
362
- alignItems : 'center' , // center children
363
- justifyContent : 'flex-end' , // align popup at the bottom
364
- backgroundColor : 'transparent' , // transparent background
365
- elevation : 999 , // fix android dynamic zindex issue
358
+ ...StyleSheet . absoluteFillObject , // fill up all screen
359
+ alignItems : 'center' , // center children
360
+ justifyContent : 'flex-end' , // align popup at the bottom
361
+ backgroundColor : 'transparent' , // transparent background
362
+ elevation : 999 , // fix android dynamic zindex issue
366
363
} ,
367
364
// Semi-transparent background below popup
368
365
backdrop : {
369
- ...StyleSheet . absoluteFillObject , // fill up all screen
370
- alignItems : 'center' , // center children
371
- justifyContent : 'flex-start' , // align popup at the bottom
366
+ ...StyleSheet . absoluteFillObject , // fill up all screen
367
+ alignItems : 'center' , // center children
368
+ justifyContent : 'flex-start' , // align popup at the bottom
372
369
backgroundColor : 'black' ,
373
370
} ,
374
371
// Body
375
372
content : {
376
373
backgroundColor : 'black' ,
377
- height : height ,
374
+ height,
378
375
} ,
379
376
// Header
380
377
header : {
381
- flexDirection : 'row' , // arrange children in a row
382
- alignItems : 'center' , // center vertically
378
+ flexDirection : 'row' , // arrange children in a row
379
+ alignItems : 'center' , // center vertically
383
380
paddingTop : 20 ,
384
381
paddingHorizontal : 20 ,
385
382
} ,
386
383
headerIcon : {
387
384
marginRight : 10 ,
388
385
} ,
389
386
headerTitle : {
390
- flex : 1 , // take up all available space
387
+ flex : 1 , // take up all available space
391
388
} ,
392
389
headerText : {
393
390
color : 'white' ,
0 commit comments