react-native-scrollpageviewtest 0.0.1-security → 1.5.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of react-native-scrollpageviewtest might be problematic. Click here for more details.

@@ -0,0 +1,516 @@
1
+ import React, { PureComponent } from 'react';
2
+ import {
3
+ Animated,
4
+ Dimensions,
5
+ findNodeHandle,
6
+ Keyboard,
7
+ NativeModules,
8
+ Platform,
9
+ StyleSheet,
10
+ UIManager,
11
+ View
12
+ } from "react-native";
13
+ import { PanGestureHandler, State } from 'react-native-gesture-handler';
14
+ import {GestureScrollView} from "./GestureScrollView";
15
+ import {GestureNormalHeader} from "./GestureNormalHeader";
16
+ import {GestureNormalFooter} from "./GestureNormalFooter";
17
+
18
+ export class GesturePageView extends GestureScrollView {
19
+ _contentOffset: Offset = { x: 0, y: 0 };
20
+ _keyboardHeight: number;
21
+ _refreshHeader;
22
+ _loadingFooter;
23
+ _width: number;
24
+ _height: number;
25
+ _scrollView: View;
26
+ _indicatorOpacity: Animated.Value = new Animated.Value(1);
27
+ _contentHeight: number;
28
+ _contentWidth: number;
29
+ _refreshStatus: GestureHeaderStatus = "waiting";
30
+ _loadingStatus: FooterStatus = "waiting";
31
+ _indicatorAnimation;
32
+ _scrollEventAttachment;
33
+ _nativeOffset;
34
+ _touching = false;
35
+ _dragging = false;
36
+ _sizeChangeInterval = 0;
37
+
38
+ _renderRefreshHeader() {
39
+ const { onRefresh, refreshHeader: Refresh } = this.props;
40
+ const measured =
41
+ this._height !== undefined && this._contentHeight !== undefined;
42
+ if (!measured) return null;
43
+ return (
44
+ onRefresh && (
45
+ <Animated.View style={this._getRefreshHeaderStyle()}>
46
+ <Refresh
47
+ ref={(ref) => (this._refreshHeader = ref)}
48
+ offset={this._nativeOffset.y}
49
+ maxHeight={Refresh.height}
50
+ />
51
+ </Animated.View>
52
+ )
53
+ );
54
+ }
55
+
56
+ _renderLoadingFooter() {
57
+ const { onLoading, loadingFooter: Footer } = this.props;
58
+ const measured =
59
+ this._height !== undefined && this._contentHeight !== undefined;
60
+ if (!measured) return null;
61
+ return (
62
+ onLoading && (
63
+ <Animated.View style={this._getLoadingFooterStyle()}>
64
+ <Footer
65
+ ref={(ref) => (this._loadingFooter = ref)}
66
+ offset={this._nativeOffset.y}
67
+ maxHeight={Footer.height}
68
+ bottomOffset={this._contentHeight - this._height}
69
+ />
70
+ </Animated.View>
71
+ )
72
+ );
73
+ }
74
+
75
+ _renderVerticalIndicator() {
76
+ if (Platform.OS === "ios") return null;
77
+ const { showsVerticalScrollIndicator } = this.props;
78
+ const measured =
79
+ this._height !== undefined && this._contentHeight !== undefined;
80
+ if (!measured) return null;
81
+ return (
82
+ showsVerticalScrollIndicator &&
83
+ this._contentHeight > this._height && (
84
+ <Animated.View style={this._getVerticalIndicatorStyle()} />
85
+ )
86
+ );
87
+ }
88
+
89
+ _renderHorizontalIndicator() {
90
+ if (Platform.OS === "ios") return null;
91
+ const { showsHorizontalScrollIndicator } = this.props;
92
+ const measured =
93
+ this._height !== undefined && this._contentHeight !== undefined;
94
+ if (!measured) return null;
95
+ return (
96
+ showsHorizontalScrollIndicator &&
97
+ this._contentWidth > this._width && (
98
+ <Animated.View style={this._getHorizontalIndicatorStyle()} />
99
+ )
100
+ );
101
+ }
102
+
103
+ scrollTo(offset: Offset, animated: boolean = true) {
104
+ if (Platform.OS === "ios") {
105
+ NativeModules.SpringScrollView.scrollTo(
106
+ findNodeHandle(this._scrollView),
107
+ offset.x,
108
+ offset.y,
109
+ animated
110
+ );
111
+ } else if (Platform.OS === "android") {
112
+ UIManager.dispatchViewManagerCommand(
113
+ findNodeHandle(this._scrollView),
114
+ "10002",
115
+ [offset.x, offset.y, animated]
116
+ );
117
+ }
118
+ return new Promise((resolve, reject) => {
119
+ if (animated) setTimeout(resolve, 500);
120
+ else resolve();
121
+ });
122
+ }
123
+
124
+ scroll(offset: Offset, animated: boolean = true) {
125
+ return this.scrollTo(
126
+ {
127
+ x: offset.x + this._contentOffset.x,
128
+ y: offset.y + this._contentOffset.y
129
+ },
130
+ animated
131
+ );
132
+ }
133
+
134
+ scrollToBegin(animated: boolean) {
135
+ return this.scrollTo({ x: this._contentOffset.x, y: 0 }, animated);
136
+ }
137
+
138
+ scrollToEnd(animated: boolean = true) {
139
+ let toOffsetY = this._contentHeight - this._height;
140
+ if (toOffsetY < 0) toOffsetY = 0;
141
+ return this.scrollTo({ x: this._contentOffset.x, y: toOffsetY }, animated);
142
+ }
143
+
144
+ beginRefresh() {
145
+ if (!this.props.loadingFooter || this.props.loadingFooter.height <= 0)
146
+ return Promise.reject(
147
+ "SpringScrollView: call beginRefresh without loadingFooter or loadingFooter height"
148
+ );
149
+ return this.scrollTo({
150
+ x: this._contentOffset.x,
151
+ y: -this.props.loadingFooter.height - 1,
152
+ });
153
+ }
154
+
155
+ endRefresh() {
156
+ if (Platform.OS === "ios") {
157
+ NativeModules.SpringScrollView.endRefresh(
158
+ findNodeHandle(this._scrollView)
159
+ );
160
+ } else if (Platform.OS === "android") {
161
+ UIManager.dispatchViewManagerCommand(
162
+ findNodeHandle(this._scrollView),
163
+ "10000",
164
+ []
165
+ );
166
+ }
167
+ }
168
+
169
+ endLoading(rebound: boolean = false) {
170
+ if (Platform.OS === "ios") {
171
+ NativeModules.SpringScrollView.endLoading(
172
+ findNodeHandle(this._scrollView),
173
+ rebound
174
+ );
175
+ } else if (Platform.OS === "android") {
176
+ UIManager.dispatchViewManagerCommand(
177
+ findNodeHandle(this._scrollView),
178
+ "10001",
179
+ [rebound]
180
+ );
181
+ }
182
+ }
183
+
184
+ _onKeyboardWillShow = (evt) => {
185
+ this._touching = false;
186
+ this.props.textInputRefs.every((input) => {
187
+ if (idx(() => input.current.isFocused())) {
188
+ input.current.measureInWindow((x, y, w, h, l, t) => {
189
+ this._keyboardHeight =
190
+ -evt.endCoordinates.screenY + this.props.inputToolBarHeight + y + h;
191
+ this._keyboardHeight > 0 &&
192
+ this.scroll({ x: 0, y: this._keyboardHeight });
193
+ });
194
+ return false;
195
+ }
196
+ return true;
197
+ });
198
+ };
199
+
200
+ _onKeyboardWillHide = () => {
201
+ if (this._keyboardHeight > 0) {
202
+ !this._touching && this.scroll({ x: 0, y: -this._keyboardHeight });
203
+ this._keyboardHeight = 0;
204
+ }
205
+ };
206
+
207
+ _beginIndicatorDismissAnimation() {
208
+ this._indicatorOpacity.setValue(1);
209
+ this._indicatorAnimation && this._indicatorAnimation.stop();
210
+ this._indicatorAnimation = Animated.timing(this._indicatorOpacity, {
211
+ toValue: 0,
212
+ delay: 500,
213
+ duration: 500,
214
+ useNativeDriver: true,
215
+ });
216
+ this._indicatorAnimation.start(({ finished }) => {
217
+ if (!finished) {
218
+ this._indicatorOpacity.setValue(1);
219
+ }
220
+ this._indicatorAnimation = null;
221
+ });
222
+ }
223
+
224
+ _onScroll = (e) => {
225
+ const {
226
+ contentOffset: { x, y },
227
+ refreshStatus,
228
+ loadingStatus,
229
+ } = e.nativeEvent;
230
+ this._contentOffset = { x, y };
231
+ if (this._refreshStatus !== refreshStatus) {
232
+ this._toRefreshStatus(refreshStatus);
233
+ this.props.onRefresh &&
234
+ refreshStatus === "refreshing" &&
235
+ this.props.onRefresh();
236
+ }
237
+ if (this._loadingStatus !== loadingStatus) {
238
+ this._toLoadingStatus(loadingStatus);
239
+ this.props.onLoading &&
240
+ loadingStatus === "loading" &&
241
+ this.props.onLoading();
242
+ }
243
+ this.props.onScroll && this.props.onScroll(e);
244
+ if (!this._indicatorAnimation) {
245
+ this._indicatorOpacity.setValue(1);
246
+ }
247
+ };
248
+
249
+ _toRefreshStatus(status: GestureHeaderStatus) {
250
+ this._refreshStatus = status;
251
+ idx(() => this._refreshHeader.changeToState(status));
252
+ }
253
+
254
+ _toLoadingStatus(status: FooterStatus) {
255
+ this._loadingStatus = status;
256
+ idx(() => this._loadingFooter.changeToState(status));
257
+ }
258
+
259
+ _getVerticalIndicatorStyle() {
260
+ const indicatorHeight = (this._height / this._contentHeight) * this._height;
261
+ return {
262
+ position: "absolute",
263
+ top: 0,
264
+ right: 2,
265
+ height: indicatorHeight,
266
+ width: 3,
267
+ borderRadius: 3,
268
+ opacity: this._indicatorOpacity,
269
+ backgroundColor: "#A8A8A8",
270
+ transform: [
271
+ {
272
+ translateY: Animated.multiply(
273
+ this._nativeOffset.y,
274
+ this._height / this._contentHeight
275
+ ),
276
+ },
277
+ ],
278
+ };
279
+ }
280
+
281
+ _getHorizontalIndicatorStyle() {
282
+ const indicatorWidth = (this._width / this._contentWidth) * this._width;
283
+ return {
284
+ position: "absolute",
285
+ bottom: 2,
286
+ left: 0,
287
+ height: 3,
288
+ width: indicatorWidth,
289
+ borderRadius: 3,
290
+ opacity: this._indicatorOpacity,
291
+ backgroundColor: "#A8A8A8",
292
+ transform: [
293
+ {
294
+ translateX: Animated.multiply(
295
+ this._nativeOffset.x,
296
+ this._width / this._contentWidth
297
+ ),
298
+ },
299
+ ],
300
+ };
301
+ }
302
+
303
+ _getRefreshHeaderStyle() {
304
+ const rHeight = this.props.refreshHeader.height;
305
+ const style = this.props.refreshHeader.style;
306
+ let transform = [];
307
+ if (style === "topping") {
308
+ transform = [
309
+ {
310
+ translateY: this._nativeOffset.y.interpolate({
311
+ inputRange: [-rHeight - 1, -rHeight, 0, 1],
312
+ outputRange: [-1, 0, rHeight, rHeight],
313
+ }),
314
+ },
315
+ ];
316
+ } else if (style === "stickyScrollView") {
317
+ transform = [
318
+ {
319
+ translateY: this._nativeOffset.y.interpolate({
320
+ inputRange: [-rHeight - 1, -rHeight, 0, 1],
321
+ outputRange: [-1, 0, 0, 0],
322
+ }),
323
+ },
324
+ ];
325
+ } else if (style !== "stickyContent") {
326
+ console.warn(
327
+ "unsupported value: '",
328
+ style,
329
+ "' in SpringScrollView, " +
330
+ "select one in 'topping','stickyScrollView','stickyContent' please"
331
+ );
332
+ }
333
+ if (this.props.inverted) transform.push({ scaleY: -1 });
334
+ return {
335
+ position: "absolute",
336
+ top: -rHeight,
337
+ right: 0,
338
+ height: rHeight,
339
+ left: 0,
340
+ transform,
341
+ };
342
+ }
343
+
344
+ _getLoadingFooterStyle() {
345
+ const fHeight = this.props.loadingFooter.height;
346
+ const maxOffset = this._contentHeight - this._height;
347
+ const style = this.props.loadingFooter.style;
348
+ let transform = [];
349
+ if (style === "bottoming") {
350
+ transform = [
351
+ {
352
+ translateY: this._nativeOffset.y.interpolate({
353
+ inputRange: [
354
+ maxOffset - 1,
355
+ maxOffset,
356
+ maxOffset + fHeight,
357
+ maxOffset + fHeight + 1,
358
+ ],
359
+ outputRange: [-fHeight, -fHeight, 0, 1],
360
+ }),
361
+ },
362
+ ];
363
+ } else if (style === "stickyScrollView") {
364
+ transform = [
365
+ {
366
+ translateY: this._nativeOffset.y.interpolate({
367
+ inputRange: [
368
+ maxOffset - 1,
369
+ maxOffset,
370
+ maxOffset + fHeight,
371
+ maxOffset + fHeight + 1,
372
+ ],
373
+ outputRange: [0, 0, 0, 1],
374
+ }),
375
+ },
376
+ ];
377
+ } else if (style !== "stickyContent") {
378
+ console.warn(
379
+ "unsupported value: '",
380
+ style,
381
+ "' in SpringScrollView, " +
382
+ "select one in 'bottoming','stickyScrollView' and 'stickyContent' please!"
383
+ );
384
+ }
385
+ if (this.props.inverted) transform.push({ scaleY: -1 });
386
+ return {
387
+ position: "absolute",
388
+ right: 0,
389
+ top:
390
+ this._height > this._contentHeight ? this._height : this._contentHeight,
391
+ height: fHeight,
392
+ left: 0,
393
+ transform,
394
+ };
395
+ }
396
+
397
+ _onWrapperLayoutChange = ({
398
+ nativeEvent: {
399
+ layout: { x, y, width, height },
400
+ },
401
+ }) => {
402
+ if (this._height !== height || this._width !== width) {
403
+ this.props.onSizeChange && this.props.onSizeChange({ width, height });
404
+ this._height = height;
405
+ this._width = width;
406
+ this._startSizeChangeInterval();
407
+ }
408
+ };
409
+
410
+ _onContentLayoutChange = ({
411
+ nativeEvent: {
412
+ layout: { x, y, width, height },
413
+ },
414
+ }) => {
415
+ if (this._contentHeight !== height || this._contentWidth !== width) {
416
+ this.props.onContentSizeChange &&
417
+ this.props.onContentSizeChange({ width, height });
418
+ this._contentHeight = height;
419
+ this._contentWidth = width;
420
+ this._startSizeChangeInterval();
421
+ }
422
+ };
423
+
424
+ _startSizeChangeInterval = () => {
425
+ if (this._sizeChangeInterval) clearInterval(this._sizeChangeInterval);
426
+ this._sizeChangeInterval = setInterval(() => {
427
+ if (!this._height || !this._contentHeight) return;
428
+ if (this._contentHeight < this._height)
429
+ this._contentHeight = this._height;
430
+ let { x: maxX, y: maxY } = this._contentOffset;
431
+ if (this._contentOffset.y > this._contentHeight - this._height) {
432
+ maxY = this._contentHeight - this._height;
433
+ if (maxY < 0) maxY = 0;
434
+ }
435
+ if (this._contentOffset.x > this._contentWidth - this._width) {
436
+ maxX = this._contentWidth - this._width;
437
+ if (maxX < 0) maxX = 0;
438
+ }
439
+ if (maxX !== this._contentOffset.x || maxY !== this._contentOffset.y) {
440
+ Platform.OS === "android" && this.scrollTo({ x: maxX, y: maxY }, false);
441
+ }
442
+ this.forceUpdate();
443
+ clearInterval(this._sizeChangeInterval);
444
+ this._sizeChangeInterval = 0;
445
+ }, Platform.select({ ios: 10, android: 30 }));
446
+ };
447
+
448
+ render() {
449
+ const {
450
+ showHeader,
451
+ showFooter,
452
+ pageWidth,
453
+ children,
454
+ onMomentumScrollEnd,
455
+ onMomentumScrollBegin,
456
+ scrollEnabled,
457
+ onGestureEvent,
458
+ onMomentumScrollActive,
459
+ onStateChange,
460
+ onGestureStateChange
461
+ } = this.props;
462
+ return (
463
+ <View style={{width: pageWidth}}>
464
+ {showHeader && this._renderRefreshHeader()}
465
+ <PanGestureHandler
466
+ onFocus
467
+ enabled={scrollEnabled}
468
+ shouldCancelWhenOutside
469
+ maxPointers={1}
470
+ onGestureEvent={onGestureEvent}
471
+ onHandlerStateChange={onGestureStateChange}
472
+ onContentLayoutChange={this._sizeChangeInterval}
473
+ beginRefresh={this.beginRefresh}
474
+ endRefresh={this.endRefresh}
475
+ >
476
+ <Animated.View
477
+ style={{
478
+ width: pageWidth
479
+ }}
480
+ >
481
+ {children}
482
+ </Animated.View>
483
+ </PanGestureHandler>
484
+ {showFooter && this._renderLoadingFooter()}
485
+ </View>
486
+ );
487
+ };
488
+
489
+ _onTouchBegin = (e) => {
490
+ this._touching = true;
491
+ this.props.onTouchBegin && this.props.onTouchBegin(e);
492
+ };
493
+
494
+ _onTouchEnd = (e) => {
495
+ this._touching = false;
496
+ this.props.onTouchEnd && this.props.onTouchEnd(e);
497
+ };
498
+
499
+ _onMomentumScrollEnd = () => {
500
+ this._touching = false;
501
+ this._dragging = false;
502
+ this._beginIndicatorDismissAnimation();
503
+ this.props.onMomentumScrollEnd && this.props.onMomentumScrollEnd();
504
+ };
505
+
506
+ _onScrollBeginDrag = () => {
507
+ this._dragging = true;
508
+ if (this.props.dragToHideKeyboard) Keyboard.dismiss();
509
+ this.props.onScrollBeginDrag && this.props.onScrollBeginDrag();
510
+ };
511
+
512
+ _onScrollEndDrag = () => {
513
+ this._dragging = false;
514
+ this.props.onScrollEndDrag && this.props.onScrollEndDrag();
515
+ };
516
+ }
@@ -0,0 +1,68 @@
1
+ import {Animated, ViewProps, ViewStyle} from 'react-native';
2
+ // import {RefreshHeader} from './RefreshHeader';
3
+ // import {LoadingFooter} from './LoadingFooter';
4
+
5
+ export interface PageIndexPath {
6
+ section: number;
7
+ row: number;
8
+ }
9
+
10
+ export interface PageOffset {
11
+ x: number;
12
+ y: number;
13
+ }
14
+
15
+ export interface PageNativeContentOffset {
16
+ x?: Animated.Value;
17
+ y?: Animated.Value;
18
+ }
19
+
20
+ export type RefreshStyle = 'topping' | 'stickyScrollView' | 'stickyContent';
21
+
22
+ export type LoadingStyle = 'bottoming' | 'stickyScrollView' | 'stickyContent';
23
+
24
+ export interface PageScrollEvent {
25
+ nativeEvent: {
26
+ contentOffset: {
27
+ x: number,
28
+ y: number,
29
+ },
30
+ };
31
+ }
32
+
33
+ export interface GesturePropType extends ViewProps {
34
+ style?: ViewStyle;
35
+ contentStyle?: ViewStyle;
36
+ bounces?: boolean;
37
+ pagingEnabled?: boolean;
38
+ decelerationRate?: number;
39
+ directionalLockEnabled?: boolean;
40
+ initialContentOffset?: Offset;
41
+ showsVerticalScrollIndicator?: boolean;
42
+ showsHorizontalScrollIndicator?: boolean;
43
+ showHeader?: boolean;
44
+ showFooter?: boolean;
45
+ onRefresh?: () => any;
46
+ onLoading?: () => any;
47
+ allLoaded?: boolean;
48
+ textInputRefs?: any[];
49
+ inputToolBarHeight?: number;
50
+ tapToHideKeyboard?: boolean;
51
+ onTouchBegin?: () => any;
52
+ onTouchEnd?: () => any;
53
+ inverted?: boolean;
54
+ onScroll?: (evt: ScrollEvent) => any;
55
+ keyboardShouldPersistTaps?: 'always' | 'never' | 'handled';
56
+ onNativeContentOffsetExtract?: NativeContentOffset;
57
+ onSizeChange?: ({width: number, height: number}) => any;
58
+ onContentSizeChange?: ({width: number, height: number}) => any;
59
+ pageWidth?: number;
60
+ children: any;
61
+ pageSize?: number;
62
+ onMomentumScrollEnd?: () => any;
63
+ onMomentumScrollBegin?: () => any;
64
+ onMomentumScrollActive?: () => any;
65
+ onGestureEvent?: any;
66
+ scrollEnabled?: boolean;
67
+ onGestureStateChange: () => any;
68
+ }
@@ -0,0 +1,53 @@
1
+ import React from "react";
2
+ import { ActivityIndicator, Animated, Image, Text, View } from "react-native";
3
+
4
+ export class GestureRefreshHeader extends React.Component<
5
+ GestureHeaderPropType,
6
+ GestureHeaderStateType
7
+ > {
8
+
9
+ static height = 80;
10
+
11
+ static style = "stickyContent";
12
+
13
+ constructor(props: GestureHeaderPropType) {
14
+ super(props);
15
+ this.state = { status: "waiting" };
16
+ }
17
+
18
+ changeToState(newStatus: GestureHeaderStatus) {
19
+ this.state.status !== newStatus &&
20
+ this.onStateChange(this.state.status, newStatus);
21
+ }
22
+
23
+ onStateChange(oldStatus: GestureHeaderStatus, newStatus: GestureHeaderStatus) {
24
+ // console.log("newStatus", newStatus);
25
+ this.setState({ status: newStatus });
26
+ }
27
+
28
+ render() {
29
+ return (
30
+ <View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
31
+ <Text style={{ fontSize:18 }}>{this.state.status}</Text>
32
+ </View>
33
+ );
34
+ }
35
+ }
36
+
37
+ export type GestureHeaderStatus =
38
+ | "waiting"
39
+ | "pulling"
40
+ | "pullingEnough"
41
+ | "pullingCancel"
42
+ | "refreshing"
43
+ | "rebound";
44
+
45
+ interface GestureHeaderPropType {
46
+ offset?: Animated.Value;
47
+ maxHeight?: number;
48
+ bottomOffset?: number;
49
+ }
50
+
51
+ interface GestureHeaderStateType {
52
+ status?: GestureHeaderStatus;
53
+ }