@mpxjs/webpack-plugin 2.9.69-beta.1 → 2.9.69-beta.2
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.
- package/lib/runtime/components/react/dist/mpx-picker-view-column-item.jsx +1 -1
- package/lib/runtime/components/react/dist/mpx-picker-view-column.jsx +42 -51
- package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +12 -2
- package/lib/runtime/components/react/dist/mpx-web-view.jsx +2 -2
- package/lib/runtime/components/react/dist/utils.jsx +3 -2
- package/lib/runtime/components/react/mpx-picker-view-column-item.tsx +2 -2
- package/lib/runtime/components/react/mpx-picker-view-column.tsx +45 -59
- package/lib/runtime/components/react/mpx-scroll-view.tsx +11 -3
- package/lib/runtime/components/react/mpx-web-view.tsx +15 -15
- package/lib/runtime/components/react/utils.tsx +3 -2
- package/package.json +1 -1
|
@@ -3,7 +3,7 @@ import Reanimated, { Extrapolation, interpolate, useAnimatedStyle, useSharedValu
|
|
|
3
3
|
import { wrapChildren, extendObject } from './utils';
|
|
4
4
|
import { createFaces } from './pickerFaces';
|
|
5
5
|
import { usePickerViewColumnAnimationContext } from './pickerVIewContext';
|
|
6
|
-
const _PickerViewColumnItem = ({ item, index, itemHeight, itemWidth, textStyleFromParent, textStyle, hasVarDec, varContext, textProps, visibleCount, onItemLayout }) => {
|
|
6
|
+
const _PickerViewColumnItem = ({ item, index, itemHeight, itemWidth = '100%', textStyleFromParent, textStyle, hasVarDec, varContext, textProps, visibleCount, onItemLayout }) => {
|
|
7
7
|
const offsetYShared = usePickerViewColumnAnimationContext();
|
|
8
8
|
const facesShared = useSharedValue(createFaces(itemHeight, visibleCount));
|
|
9
9
|
useEffect(() => {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, { forwardRef, useRef, useState, useMemo, useEffect, useCallback } from 'react';
|
|
2
2
|
import { SafeAreaView, StyleSheet } from 'react-native';
|
|
3
3
|
import Reanimated, { useAnimatedRef, useScrollViewOffset } from 'react-native-reanimated';
|
|
4
|
-
import { useTransformStyle, splitStyle, splitProps, useLayout, usePrevious, isAndroid } from './utils';
|
|
4
|
+
import { useTransformStyle, splitStyle, splitProps, useLayout, usePrevious, isAndroid, useDebounceCallback, useStableCallback, isIOS } from './utils';
|
|
5
5
|
import useNodesRef from './useNodesRef';
|
|
6
6
|
import PickerOverlay from './pickerViewOverlay';
|
|
7
7
|
import PickerMask from './pickerViewMask';
|
|
@@ -20,11 +20,8 @@ const _PickerViewColumn = forwardRef((props, ref) => {
|
|
|
20
20
|
style: normalStyle
|
|
21
21
|
});
|
|
22
22
|
const { height: pickerH, itemHeight } = wrapperStyle;
|
|
23
|
-
const [scrollViewWidth, setScrollViewWidth] = useState('100%');
|
|
24
|
-
const [itemRawW, setItemRawW] = useState('100%');
|
|
25
23
|
const [itemRawH, setItemRawH] = useState(itemHeight);
|
|
26
24
|
const maxIndex = useMemo(() => columnData.length - 1, [columnData]);
|
|
27
|
-
const maxScrollViewWidth = useRef(-1);
|
|
28
25
|
const prevScrollingInfo = useRef({ index: initialIndex, y: 0 });
|
|
29
26
|
const touching = useRef(false);
|
|
30
27
|
const scrolling = useRef(false);
|
|
@@ -39,10 +36,6 @@ const _PickerViewColumn = forwardRef((props, ref) => {
|
|
|
39
36
|
nodeRef: scrollViewRef
|
|
40
37
|
});
|
|
41
38
|
// console.log('[mpx-picker-view-column], render ---> columnIndex=', columnIndex, 'initialIndex=', initialIndex, 'columnData=', columnData.length, 'pickerH=', pickerH, 'itemRawH=', itemRawH, 'itemHeight=', itemHeight)
|
|
42
|
-
// const initialOffset = useMemo(() => ({
|
|
43
|
-
// x: 0,
|
|
44
|
-
// y: itemRawH * initialIndex
|
|
45
|
-
// }), [itemRawH])
|
|
46
39
|
const paddingHeight = useMemo(() => Math.round((pickerH - itemHeight) / 2), [pickerH, itemHeight]);
|
|
47
40
|
const snapToOffsets = useMemo(() => columnData.map((_, i) => i * itemRawH), [columnData, itemRawH]);
|
|
48
41
|
const contentContainerStyle = useMemo(() => {
|
|
@@ -52,8 +45,27 @@ const _PickerViewColumn = forwardRef((props, ref) => {
|
|
|
52
45
|
const calc = Math.round(y / itemRawH);
|
|
53
46
|
return Math.max(0, Math.min(calc, maxIndex));
|
|
54
47
|
}, [itemRawH, maxIndex]);
|
|
48
|
+
const getYofIndex = useCallback((index) => {
|
|
49
|
+
return index * itemRawH;
|
|
50
|
+
}, [itemRawH]);
|
|
51
|
+
const stableResetScrollPosition = useStableCallback((y) => {
|
|
52
|
+
console.log('[mpx-picker-view-column], reset --->', 'columnIndex=', columnIndex, 'y=', y, touching.current, scrolling.current);
|
|
53
|
+
if (touching.current || scrolling.current) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
// needReset.current = true
|
|
57
|
+
if (y % itemRawH !== 0) {
|
|
58
|
+
scrolling.current = true;
|
|
59
|
+
const targetIndex = getIndex(y);
|
|
60
|
+
const targetY = getYofIndex(targetIndex);
|
|
61
|
+
scrollViewRef.current?.scrollTo({ x: 0, y: targetY, animated: false });
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
onMomentumScrollEnd({ nativeEvent: { contentOffset: { y } } });
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
const debounceResetScrollPosition = useDebounceCallback(stableResetScrollPosition, 10);
|
|
55
68
|
useEffect(() => {
|
|
56
|
-
// console.log('[mpx-picker-view-column], useEffect000 --->', 'columnIndex=', columnIndex, 'initialIndex=', initialIndex, 'prevIndex=', prevIndex, 'activeIndex=', activeIndex.current, 'maxIndex=', maxIndex, 'prevMaxIndex=', prevMaxIndex)
|
|
57
69
|
if (!scrollViewRef.current ||
|
|
58
70
|
!itemRawH ||
|
|
59
71
|
touching.current ||
|
|
@@ -64,84 +76,64 @@ const _PickerViewColumn = forwardRef((props, ref) => {
|
|
|
64
76
|
maxIndex !== prevMaxIndex) {
|
|
65
77
|
return;
|
|
66
78
|
}
|
|
67
|
-
// console.log('[mpx-picker-view-column], useEffect ---> columnIndex=', columnIndex, 'initialIndex=', initialIndex, 'y=', itemRawH * initialIndex, `${scrollViewRef.current?.scrollTo}`)
|
|
68
79
|
setTimeout(() => {
|
|
69
80
|
scrollViewRef.current?.scrollTo({
|
|
70
81
|
x: 0,
|
|
71
|
-
y:
|
|
82
|
+
y: getYofIndex(initialIndex),
|
|
72
83
|
animated: false
|
|
73
84
|
});
|
|
74
85
|
}, isAndroid ? 200 : 0);
|
|
75
86
|
activeIndex.current = initialIndex;
|
|
76
87
|
}, [itemRawH, initialIndex]);
|
|
77
88
|
const onContentSizeChange = (_w, h) => {
|
|
78
|
-
const y =
|
|
79
|
-
// console.log('[mpx-picker-view-column], onContentSizeChange --->', 'columnIndex=', columnIndex, '_w=', _w, 'h=', h, 'y=', y, 'itemRawH=', itemRawH)
|
|
89
|
+
const y = getYofIndex(initialIndex);
|
|
80
90
|
if (y <= h) {
|
|
81
91
|
setTimeout(() => {
|
|
82
92
|
scrollViewRef.current?.scrollTo({ x: 0, y, animated: false });
|
|
83
93
|
}, 0);
|
|
84
94
|
}
|
|
85
95
|
};
|
|
86
|
-
const onScrollViewLayout = (e) => {
|
|
87
|
-
if (isAndroid) {
|
|
88
|
-
return;
|
|
89
|
-
}
|
|
90
|
-
// RN iOS bug: https://github.com/facebook/react-native/issues/36135
|
|
91
|
-
const { width } = e.nativeEvent.layout;
|
|
92
|
-
const widthInt = Math.ceil(width);
|
|
93
|
-
// console.log('[mpx-picker-view-column], onScrollViewLayout --->', 'columnIndex=', columnIndex, 'width=', width, 'widthInt=', widthInt, 'scrollViewWidth=', scrollViewWidth)
|
|
94
|
-
if (widthInt !== scrollViewWidth) {
|
|
95
|
-
const maxW = maxScrollViewWidth.current;
|
|
96
|
-
if (maxW !== -1 && widthInt > maxW) {
|
|
97
|
-
return;
|
|
98
|
-
}
|
|
99
|
-
if (maxW === -1) {
|
|
100
|
-
maxScrollViewWidth.current = Math.ceil(widthInt * 1.5);
|
|
101
|
-
}
|
|
102
|
-
setScrollViewWidth(widthInt);
|
|
103
|
-
}
|
|
104
|
-
if (itemRawW === '100%') {
|
|
105
|
-
setItemRawW(widthInt);
|
|
106
|
-
}
|
|
107
|
-
};
|
|
108
96
|
const onItemLayout = (e) => {
|
|
109
97
|
const { height: rawH } = e.nativeEvent.layout;
|
|
110
|
-
// console.log('[mpx-picker-view-column], onItemLayout --->', 'columnIndex=', columnIndex, 'width=', width)
|
|
111
98
|
if (rawH && itemRawH !== rawH) {
|
|
112
99
|
setItemRawH(rawH);
|
|
113
100
|
}
|
|
114
101
|
};
|
|
115
|
-
const
|
|
102
|
+
const onScrollBeginDrag = () => {
|
|
103
|
+
isIOS && debounceResetScrollPosition.clear();
|
|
116
104
|
touching.current = true;
|
|
117
105
|
prevScrollingInfo.current = {
|
|
118
106
|
index: activeIndex.current,
|
|
119
|
-
y: activeIndex.current
|
|
107
|
+
y: getYofIndex(activeIndex.current)
|
|
120
108
|
};
|
|
121
109
|
};
|
|
122
|
-
const
|
|
123
|
-
touching.current = false;
|
|
124
|
-
};
|
|
125
|
-
const onTouchCancel = () => {
|
|
110
|
+
const onScrollEndDrag = (e) => {
|
|
126
111
|
touching.current = false;
|
|
112
|
+
const { y } = e.nativeEvent.contentOffset;
|
|
113
|
+
if (isIOS) {
|
|
114
|
+
if (y > 0 && y < snapToOffsets[maxIndex]) {
|
|
115
|
+
debounceResetScrollPosition(y);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
127
118
|
};
|
|
128
119
|
const onMomentumScrollBegin = () => {
|
|
120
|
+
isIOS && debounceResetScrollPosition.clear();
|
|
129
121
|
scrolling.current = true;
|
|
130
122
|
};
|
|
131
123
|
const onMomentumScrollEnd = (e) => {
|
|
132
124
|
scrolling.current = false;
|
|
133
|
-
if (!itemRawH) {
|
|
134
|
-
return;
|
|
135
|
-
}
|
|
136
125
|
const { y: scrollY } = e.nativeEvent.contentOffset;
|
|
137
|
-
|
|
126
|
+
if (isIOS && scrollY % itemRawH !== 0) {
|
|
127
|
+
return debounceResetScrollPosition(scrollY);
|
|
128
|
+
}
|
|
129
|
+
const calcIndex = getIndex(scrollY);
|
|
138
130
|
activeIndex.current = calcIndex;
|
|
139
131
|
if (calcIndex !== initialIndex) {
|
|
140
|
-
calcIndex = Math.max(0, Math.min(calcIndex, maxIndex)) || 0;
|
|
141
132
|
onSelectChange(calcIndex);
|
|
142
133
|
}
|
|
143
134
|
};
|
|
144
135
|
const onScroll = (e) => {
|
|
136
|
+
const { y } = e.nativeEvent.contentOffset;
|
|
145
137
|
if (isAndroid) {
|
|
146
138
|
return;
|
|
147
139
|
}
|
|
@@ -150,7 +142,6 @@ const _PickerViewColumn = forwardRef((props, ref) => {
|
|
|
150
142
|
if (typeof pickerVibrate !== 'function') {
|
|
151
143
|
return;
|
|
152
144
|
}
|
|
153
|
-
const { y } = e.nativeEvent.contentOffset;
|
|
154
145
|
const { index: prevIndex, y: _y } = prevScrollingInfo.current;
|
|
155
146
|
if (touching.current || scrolling.current) {
|
|
156
147
|
if (Math.abs(y - _y) >= itemRawH) {
|
|
@@ -158,7 +149,7 @@ const _PickerViewColumn = forwardRef((props, ref) => {
|
|
|
158
149
|
if (currentId !== prevIndex) {
|
|
159
150
|
prevScrollingInfo.current = {
|
|
160
151
|
index: currentId,
|
|
161
|
-
y: currentId
|
|
152
|
+
y: getYofIndex(currentId)
|
|
162
153
|
};
|
|
163
154
|
// vibrateShort({ type: 'selection' })
|
|
164
155
|
pickerVibrate();
|
|
@@ -167,11 +158,11 @@ const _PickerViewColumn = forwardRef((props, ref) => {
|
|
|
167
158
|
}
|
|
168
159
|
};
|
|
169
160
|
const renderInnerchild = () => columnData.map((item, index) => {
|
|
170
|
-
return (<MpxPickerVIewColumnItem key={index} item={item} index={index} itemHeight={itemHeight}
|
|
161
|
+
return (<MpxPickerVIewColumnItem key={index} item={item} index={index} itemHeight={itemHeight} textStyleFromParent={textStyleFromParent} textStyle={textStyle} hasVarDec={hasVarDec} varContext={varContextRef.current} textProps={textProps} visibleCount={visibleCount} onItemLayout={onItemLayout}/>);
|
|
171
162
|
});
|
|
172
163
|
const renderScollView = () => {
|
|
173
164
|
return (<PickerViewColumnAnimationContext.Provider value={offsetYShared}>
|
|
174
|
-
<Reanimated.ScrollView ref={scrollViewRef} bounces={true} horizontal={false} nestedScrollEnabled={true} removeClippedSubviews={false} showsVerticalScrollIndicator={false} showsHorizontalScrollIndicator={false} scrollEventThrottle={16} {...layoutProps} style={[{ width:
|
|
165
|
+
<Reanimated.ScrollView ref={scrollViewRef} bounces={true} horizontal={false} nestedScrollEnabled={true} removeClippedSubviews={false} showsVerticalScrollIndicator={false} showsHorizontalScrollIndicator={false} scrollEventThrottle={16} {...layoutProps} style={[{ width: '100%' }]} decelerationRate="fast" snapToOffsets={snapToOffsets} onScroll={onScroll} onScrollBeginDrag={onScrollBeginDrag} onScrollEndDrag={onScrollEndDrag} onMomentumScrollBegin={onMomentumScrollBegin} onMomentumScrollEnd={onMomentumScrollEnd} onContentSizeChange={onContentSizeChange} contentContainerStyle={contentContainerStyle}>
|
|
175
166
|
{renderInnerchild()}
|
|
176
167
|
</Reanimated.ScrollView>
|
|
177
168
|
</PickerViewColumnAnimationContext.Provider>);
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
* ✔ bindscroll
|
|
33
33
|
*/
|
|
34
34
|
import { ScrollView } from 'react-native-gesture-handler';
|
|
35
|
-
import { RefreshControl } from 'react-native';
|
|
35
|
+
import { RefreshControl, Platform } from 'react-native';
|
|
36
36
|
import { useRef, useState, useEffect, forwardRef, useContext, createElement, useMemo } from 'react';
|
|
37
37
|
import { useAnimatedRef } from 'react-native-reanimated';
|
|
38
38
|
import { warn } from '@mpxjs/utils';
|
|
@@ -184,6 +184,7 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
|
|
|
184
184
|
visibleLength
|
|
185
185
|
});
|
|
186
186
|
}
|
|
187
|
+
const observerTimers = {};
|
|
187
188
|
function onScroll(e) {
|
|
188
189
|
const { bindscroll } = props;
|
|
189
190
|
const { x: scrollLeft, y: scrollTop } = e.nativeEvent.contentOffset;
|
|
@@ -203,7 +204,16 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
|
|
|
203
204
|
updateScrollOptions(e, { scrollLeft, scrollTop });
|
|
204
205
|
if (enableTriggerIntersectionObserver && intersectionObservers) {
|
|
205
206
|
for (const key in intersectionObservers) {
|
|
206
|
-
|
|
207
|
+
if (Platform.OS === 'android') {
|
|
208
|
+
intersectionObservers[key].throttleMeasure();
|
|
209
|
+
}
|
|
210
|
+
else {
|
|
211
|
+
// TODO: 由于iOS在onScroll滚动的过程中view的计算measureInWindow计算的值不发生变化,所以暂时在ios上加一个延时计算
|
|
212
|
+
observerTimers[key] && clearTimeout(observerTimers[key]);
|
|
213
|
+
observerTimers[key] = setTimeout(() => {
|
|
214
|
+
intersectionObservers[key].throttleMeasure();
|
|
215
|
+
}, 300);
|
|
216
|
+
}
|
|
207
217
|
}
|
|
208
218
|
}
|
|
209
219
|
}
|
|
@@ -62,7 +62,7 @@ const _WebView = forwardRef((props, ref) => {
|
|
|
62
62
|
src: res.nativeEvent?.url
|
|
63
63
|
}
|
|
64
64
|
};
|
|
65
|
-
bindload(result);
|
|
65
|
+
bindload?.(result);
|
|
66
66
|
};
|
|
67
67
|
const _error = function (res) {
|
|
68
68
|
const result = {
|
|
@@ -72,7 +72,7 @@ const _WebView = forwardRef((props, ref) => {
|
|
|
72
72
|
src: ''
|
|
73
73
|
}
|
|
74
74
|
};
|
|
75
|
-
binderror(result);
|
|
75
|
+
binderror?.(result);
|
|
76
76
|
};
|
|
77
77
|
const injectedJavaScript = `
|
|
78
78
|
if (window.ReactNativeWebView && window.ReactNativeWebView.postMessage) {
|
|
@@ -451,13 +451,14 @@ export function wrapChildren(props = {}, { hasVarDec, varContext, textStyle, tex
|
|
|
451
451
|
export const debounce = (func, delay) => {
|
|
452
452
|
let timer;
|
|
453
453
|
const wrapper = (...args) => {
|
|
454
|
-
clearTimeout(timer);
|
|
454
|
+
timer && clearTimeout(timer);
|
|
455
455
|
timer = setTimeout(() => {
|
|
456
456
|
func(...args);
|
|
457
457
|
}, delay);
|
|
458
458
|
};
|
|
459
459
|
wrapper.clear = () => {
|
|
460
|
-
clearTimeout(timer);
|
|
460
|
+
timer && clearTimeout(timer);
|
|
461
|
+
timer = null;
|
|
461
462
|
};
|
|
462
463
|
return wrapper;
|
|
463
464
|
};
|
|
@@ -9,7 +9,7 @@ interface PickerColumnItemProps {
|
|
|
9
9
|
item: React.ReactElement
|
|
10
10
|
index: number
|
|
11
11
|
itemHeight: number
|
|
12
|
-
itemWidth
|
|
12
|
+
itemWidth?: number | '100%'
|
|
13
13
|
textStyleFromParent: Record<string, any>
|
|
14
14
|
textStyle: Record<string, any>
|
|
15
15
|
hasVarDec: boolean
|
|
@@ -23,7 +23,7 @@ const _PickerViewColumnItem: React.FC<PickerColumnItemProps> = ({
|
|
|
23
23
|
item,
|
|
24
24
|
index,
|
|
25
25
|
itemHeight,
|
|
26
|
-
itemWidth,
|
|
26
|
+
itemWidth = '100%',
|
|
27
27
|
textStyleFromParent,
|
|
28
28
|
textStyle,
|
|
29
29
|
hasVarDec,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, { forwardRef, useRef, useState, useMemo, useEffect, useCallback } from 'react'
|
|
2
2
|
import { LayoutChangeEvent, NativeScrollEvent, NativeSyntheticEvent, SafeAreaView, ScrollView, StyleSheet, View } from 'react-native'
|
|
3
3
|
import Reanimated, { AnimatedRef, useAnimatedRef, useScrollViewOffset } from 'react-native-reanimated'
|
|
4
|
-
import { useTransformStyle, splitStyle, splitProps, useLayout, usePrevious, isAndroid } from './utils'
|
|
4
|
+
import { useTransformStyle, splitStyle, splitProps, useLayout, usePrevious, isAndroid, useDebounceCallback, useStableCallback, isIOS } from './utils'
|
|
5
5
|
import useNodesRef, { HandlerRef } from './useNodesRef'
|
|
6
6
|
import PickerOverlay from './pickerViewOverlay'
|
|
7
7
|
import PickerMask from './pickerViewMask'
|
|
@@ -64,11 +64,8 @@ const _PickerViewColumn = forwardRef<HandlerRef<ScrollView & View, ColumnProps>,
|
|
|
64
64
|
})
|
|
65
65
|
|
|
66
66
|
const { height: pickerH, itemHeight } = wrapperStyle
|
|
67
|
-
const [scrollViewWidth, setScrollViewWidth] = useState<number | '100%'>('100%')
|
|
68
|
-
const [itemRawW, setItemRawW] = useState<number | '100%'>('100%')
|
|
69
67
|
const [itemRawH, setItemRawH] = useState(itemHeight)
|
|
70
68
|
const maxIndex = useMemo(() => columnData.length - 1, [columnData])
|
|
71
|
-
const maxScrollViewWidth = useRef(-1)
|
|
72
69
|
const prevScrollingInfo = useRef({ index: initialIndex, y: 0 })
|
|
73
70
|
const touching = useRef(false)
|
|
74
71
|
const scrolling = useRef(false)
|
|
@@ -88,11 +85,6 @@ const _PickerViewColumn = forwardRef<HandlerRef<ScrollView & View, ColumnProps>,
|
|
|
88
85
|
|
|
89
86
|
// console.log('[mpx-picker-view-column], render ---> columnIndex=', columnIndex, 'initialIndex=', initialIndex, 'columnData=', columnData.length, 'pickerH=', pickerH, 'itemRawH=', itemRawH, 'itemHeight=', itemHeight)
|
|
90
87
|
|
|
91
|
-
// const initialOffset = useMemo(() => ({
|
|
92
|
-
// x: 0,
|
|
93
|
-
// y: itemRawH * initialIndex
|
|
94
|
-
// }), [itemRawH])
|
|
95
|
-
|
|
96
88
|
const paddingHeight = useMemo(
|
|
97
89
|
() => Math.round((pickerH - itemHeight) / 2),
|
|
98
90
|
[pickerH, itemHeight]
|
|
@@ -112,8 +104,28 @@ const _PickerViewColumn = forwardRef<HandlerRef<ScrollView & View, ColumnProps>,
|
|
|
112
104
|
return Math.max(0, Math.min(calc, maxIndex))
|
|
113
105
|
}, [itemRawH, maxIndex])
|
|
114
106
|
|
|
107
|
+
const getYofIndex = useCallback((index: number) => {
|
|
108
|
+
return index * itemRawH
|
|
109
|
+
}, [itemRawH])
|
|
110
|
+
|
|
111
|
+
const stableResetScrollPosition = useStableCallback((y: number) => {
|
|
112
|
+
console.log('[mpx-picker-view-column], reset --->', 'columnIndex=', columnIndex, 'y=', y, touching.current, scrolling.current)
|
|
113
|
+
if (touching.current || scrolling.current) {
|
|
114
|
+
return
|
|
115
|
+
}
|
|
116
|
+
// needReset.current = true
|
|
117
|
+
if (y % itemRawH !== 0) {
|
|
118
|
+
scrolling.current = true
|
|
119
|
+
const targetIndex = getIndex(y)
|
|
120
|
+
const targetY = getYofIndex(targetIndex)
|
|
121
|
+
scrollViewRef.current?.scrollTo({ x: 0, y: targetY, animated: false })
|
|
122
|
+
} else {
|
|
123
|
+
onMomentumScrollEnd({ nativeEvent: { contentOffset: { y } } })
|
|
124
|
+
}
|
|
125
|
+
})
|
|
126
|
+
const debounceResetScrollPosition = useDebounceCallback(stableResetScrollPosition, 10)
|
|
127
|
+
|
|
115
128
|
useEffect(() => {
|
|
116
|
-
// console.log('[mpx-picker-view-column], useEffect000 --->', 'columnIndex=', columnIndex, 'initialIndex=', initialIndex, 'prevIndex=', prevIndex, 'activeIndex=', activeIndex.current, 'maxIndex=', maxIndex, 'prevMaxIndex=', prevMaxIndex)
|
|
117
129
|
if (
|
|
118
130
|
!scrollViewRef.current ||
|
|
119
131
|
!itemRawH ||
|
|
@@ -126,11 +138,10 @@ const _PickerViewColumn = forwardRef<HandlerRef<ScrollView & View, ColumnProps>,
|
|
|
126
138
|
) {
|
|
127
139
|
return
|
|
128
140
|
}
|
|
129
|
-
// console.log('[mpx-picker-view-column], useEffect ---> columnIndex=', columnIndex, 'initialIndex=', initialIndex, 'y=', itemRawH * initialIndex, `${scrollViewRef.current?.scrollTo}`)
|
|
130
141
|
setTimeout(() => {
|
|
131
142
|
scrollViewRef.current?.scrollTo({
|
|
132
143
|
x: 0,
|
|
133
|
-
y:
|
|
144
|
+
y: getYofIndex(initialIndex),
|
|
134
145
|
animated: false
|
|
135
146
|
})
|
|
136
147
|
}, isAndroid ? 200 : 0)
|
|
@@ -138,8 +149,7 @@ const _PickerViewColumn = forwardRef<HandlerRef<ScrollView & View, ColumnProps>,
|
|
|
138
149
|
}, [itemRawH, initialIndex])
|
|
139
150
|
|
|
140
151
|
const onContentSizeChange = (_w: number, h: number) => {
|
|
141
|
-
const y =
|
|
142
|
-
// console.log('[mpx-picker-view-column], onContentSizeChange --->', 'columnIndex=', columnIndex, '_w=', _w, 'h=', h, 'y=', y, 'itemRawH=', itemRawH)
|
|
152
|
+
const y = getYofIndex(initialIndex)
|
|
143
153
|
if (y <= h) {
|
|
144
154
|
setTimeout(() => {
|
|
145
155
|
scrollViewRef.current?.scrollTo({ x: 0, y, animated: false })
|
|
@@ -147,72 +157,52 @@ const _PickerViewColumn = forwardRef<HandlerRef<ScrollView & View, ColumnProps>,
|
|
|
147
157
|
}
|
|
148
158
|
}
|
|
149
159
|
|
|
150
|
-
const onScrollViewLayout = (e: LayoutChangeEvent) => {
|
|
151
|
-
if (isAndroid) {
|
|
152
|
-
return
|
|
153
|
-
}
|
|
154
|
-
// RN iOS bug: https://github.com/facebook/react-native/issues/36135
|
|
155
|
-
const { width } = e.nativeEvent.layout
|
|
156
|
-
const widthInt = Math.ceil(width)
|
|
157
|
-
// console.log('[mpx-picker-view-column], onScrollViewLayout --->', 'columnIndex=', columnIndex, 'width=', width, 'widthInt=', widthInt, 'scrollViewWidth=', scrollViewWidth)
|
|
158
|
-
if (widthInt !== scrollViewWidth) {
|
|
159
|
-
const maxW = maxScrollViewWidth.current
|
|
160
|
-
if (maxW !== -1 && widthInt > maxW) {
|
|
161
|
-
return
|
|
162
|
-
}
|
|
163
|
-
if (maxW === -1) {
|
|
164
|
-
maxScrollViewWidth.current = Math.ceil(widthInt * 1.5)
|
|
165
|
-
}
|
|
166
|
-
setScrollViewWidth(widthInt)
|
|
167
|
-
}
|
|
168
|
-
if (itemRawW === '100%') {
|
|
169
|
-
setItemRawW(widthInt)
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
|
|
173
160
|
const onItemLayout = (e: LayoutChangeEvent) => {
|
|
174
161
|
const { height: rawH } = e.nativeEvent.layout
|
|
175
|
-
// console.log('[mpx-picker-view-column], onItemLayout --->', 'columnIndex=', columnIndex, 'width=', width)
|
|
176
162
|
if (rawH && itemRawH !== rawH) {
|
|
177
163
|
setItemRawH(rawH)
|
|
178
164
|
}
|
|
179
165
|
}
|
|
180
166
|
|
|
181
|
-
const
|
|
167
|
+
const onScrollBeginDrag = () => {
|
|
168
|
+
isIOS && debounceResetScrollPosition.clear()
|
|
182
169
|
touching.current = true
|
|
183
170
|
prevScrollingInfo.current = {
|
|
184
171
|
index: activeIndex.current,
|
|
185
|
-
y: activeIndex.current
|
|
172
|
+
y: getYofIndex(activeIndex.current)
|
|
186
173
|
}
|
|
187
174
|
}
|
|
188
175
|
|
|
189
|
-
const
|
|
190
|
-
touching.current = false
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
const onTouchCancel = () => {
|
|
176
|
+
const onScrollEndDrag = (e: NativeSyntheticEvent<NativeScrollEvent>) => {
|
|
194
177
|
touching.current = false
|
|
178
|
+
const { y } = e.nativeEvent.contentOffset
|
|
179
|
+
if (isIOS) {
|
|
180
|
+
if (y > 0 && y < snapToOffsets[maxIndex]) {
|
|
181
|
+
debounceResetScrollPosition(y)
|
|
182
|
+
}
|
|
183
|
+
}
|
|
195
184
|
}
|
|
196
185
|
|
|
197
186
|
const onMomentumScrollBegin = () => {
|
|
187
|
+
isIOS && debounceResetScrollPosition.clear()
|
|
198
188
|
scrolling.current = true
|
|
199
189
|
}
|
|
200
190
|
|
|
201
|
-
const onMomentumScrollEnd = (e: NativeSyntheticEvent<NativeScrollEvent>) => {
|
|
191
|
+
const onMomentumScrollEnd = (e: NativeSyntheticEvent<NativeScrollEvent> | { nativeEvent: { contentOffset: { y: number } } }) => {
|
|
202
192
|
scrolling.current = false
|
|
203
|
-
if (!itemRawH) {
|
|
204
|
-
return
|
|
205
|
-
}
|
|
206
193
|
const { y: scrollY } = e.nativeEvent.contentOffset
|
|
207
|
-
|
|
194
|
+
if (isIOS && scrollY % itemRawH !== 0) {
|
|
195
|
+
return debounceResetScrollPosition(scrollY)
|
|
196
|
+
}
|
|
197
|
+
const calcIndex = getIndex(scrollY)
|
|
208
198
|
activeIndex.current = calcIndex
|
|
209
199
|
if (calcIndex !== initialIndex) {
|
|
210
|
-
calcIndex = Math.max(0, Math.min(calcIndex, maxIndex)) || 0
|
|
211
200
|
onSelectChange(calcIndex)
|
|
212
201
|
}
|
|
213
202
|
}
|
|
214
203
|
|
|
215
204
|
const onScroll = (e: NativeSyntheticEvent<NativeScrollEvent>) => {
|
|
205
|
+
const { y } = e.nativeEvent.contentOffset
|
|
216
206
|
if (isAndroid) {
|
|
217
207
|
return
|
|
218
208
|
}
|
|
@@ -221,7 +211,6 @@ const _PickerViewColumn = forwardRef<HandlerRef<ScrollView & View, ColumnProps>,
|
|
|
221
211
|
if (typeof pickerVibrate !== 'function') {
|
|
222
212
|
return
|
|
223
213
|
}
|
|
224
|
-
const { y } = e.nativeEvent.contentOffset
|
|
225
214
|
const { index: prevIndex, y: _y } = prevScrollingInfo.current
|
|
226
215
|
if (touching.current || scrolling.current) {
|
|
227
216
|
if (Math.abs(y - _y) >= itemRawH) {
|
|
@@ -229,7 +218,7 @@ const _PickerViewColumn = forwardRef<HandlerRef<ScrollView & View, ColumnProps>,
|
|
|
229
218
|
if (currentId !== prevIndex) {
|
|
230
219
|
prevScrollingInfo.current = {
|
|
231
220
|
index: currentId,
|
|
232
|
-
y: currentId
|
|
221
|
+
y: getYofIndex(currentId)
|
|
233
222
|
}
|
|
234
223
|
// vibrateShort({ type: 'selection' })
|
|
235
224
|
pickerVibrate()
|
|
@@ -246,7 +235,6 @@ const _PickerViewColumn = forwardRef<HandlerRef<ScrollView & View, ColumnProps>,
|
|
|
246
235
|
item={item}
|
|
247
236
|
index={index}
|
|
248
237
|
itemHeight={itemHeight}
|
|
249
|
-
itemWidth={itemRawW}
|
|
250
238
|
textStyleFromParent={textStyleFromParent}
|
|
251
239
|
textStyle={textStyle}
|
|
252
240
|
hasVarDec={hasVarDec}
|
|
@@ -271,14 +259,12 @@ const _PickerViewColumn = forwardRef<HandlerRef<ScrollView & View, ColumnProps>,
|
|
|
271
259
|
showsHorizontalScrollIndicator={false}
|
|
272
260
|
scrollEventThrottle={16}
|
|
273
261
|
{...layoutProps}
|
|
274
|
-
style={[{ width:
|
|
262
|
+
style={[{ width: '100%' }]}
|
|
275
263
|
decelerationRate="fast"
|
|
276
264
|
snapToOffsets={snapToOffsets}
|
|
277
265
|
onScroll={onScroll}
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
onTouchEnd={onTouchEnd}
|
|
281
|
-
onTouchCancel={onTouchCancel}
|
|
266
|
+
onScrollBeginDrag={onScrollBeginDrag}
|
|
267
|
+
onScrollEndDrag={onScrollEndDrag}
|
|
282
268
|
onMomentumScrollBegin={onMomentumScrollBegin}
|
|
283
269
|
onMomentumScrollEnd={onMomentumScrollEnd}
|
|
284
270
|
onContentSizeChange={onContentSizeChange}
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
* ✔ bindscroll
|
|
33
33
|
*/
|
|
34
34
|
import { ScrollView } from 'react-native-gesture-handler'
|
|
35
|
-
import { View, RefreshControl, NativeSyntheticEvent, NativeScrollEvent, LayoutChangeEvent, ViewStyle } from 'react-native'
|
|
35
|
+
import { View, RefreshControl, NativeSyntheticEvent, NativeScrollEvent, LayoutChangeEvent, ViewStyle, Platform } from 'react-native'
|
|
36
36
|
import { JSX, ReactNode, RefObject, useRef, useState, useEffect, forwardRef, useContext, createElement, useMemo } from 'react'
|
|
37
37
|
import { useAnimatedRef } from 'react-native-reanimated'
|
|
38
38
|
import { warn } from '@mpxjs/utils'
|
|
@@ -40,7 +40,6 @@ import useInnerProps, { getCustomEvent } from './getInnerListeners'
|
|
|
40
40
|
import useNodesRef, { HandlerRef } from './useNodesRef'
|
|
41
41
|
import { splitProps, splitStyle, useTransformStyle, useLayout, wrapChildren, extendObject, flatGesture, GestureHandler } from './utils'
|
|
42
42
|
import { IntersectionObserverContext, ScrollViewContext } from './context'
|
|
43
|
-
|
|
44
43
|
interface ScrollViewProps {
|
|
45
44
|
children?: ReactNode;
|
|
46
45
|
enhanced?: boolean;
|
|
@@ -319,6 +318,7 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
|
|
|
319
318
|
})
|
|
320
319
|
}
|
|
321
320
|
|
|
321
|
+
const observerTimers: {[key: string]: any} = {}
|
|
322
322
|
function onScroll (e: NativeSyntheticEvent<NativeScrollEvent>) {
|
|
323
323
|
const { bindscroll } = props
|
|
324
324
|
const { x: scrollLeft, y: scrollTop } = e.nativeEvent.contentOffset
|
|
@@ -340,7 +340,15 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
|
|
|
340
340
|
updateScrollOptions(e, { scrollLeft, scrollTop })
|
|
341
341
|
if (enableTriggerIntersectionObserver && intersectionObservers) {
|
|
342
342
|
for (const key in intersectionObservers) {
|
|
343
|
-
|
|
343
|
+
if (Platform.OS === 'android') {
|
|
344
|
+
intersectionObservers[key].throttleMeasure();
|
|
345
|
+
} else {
|
|
346
|
+
// TODO: 由于iOS在onScroll滚动的过程中view的计算measureInWindow计算的值不发生变化,所以暂时在ios上加一个延时计算
|
|
347
|
+
observerTimers[key] && clearTimeout(observerTimers[key])
|
|
348
|
+
observerTimers[key] = setTimeout(() => {
|
|
349
|
+
intersectionObservers[key].throttleMeasure();
|
|
350
|
+
}, 300)
|
|
351
|
+
}
|
|
344
352
|
}
|
|
345
353
|
}
|
|
346
354
|
}
|
|
@@ -60,17 +60,17 @@ const _WebView = forwardRef<HandlerRef<WebView, WebViewProps>, WebViewProps>((pr
|
|
|
60
60
|
const canGoBack = useRef<boolean>(false)
|
|
61
61
|
|
|
62
62
|
const onAndroidBackPress = useCallback(() => {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
63
|
+
if (canGoBack.current) {
|
|
64
|
+
webViewRef.current?.goBack()
|
|
65
|
+
return true
|
|
66
|
+
}
|
|
67
|
+
return false
|
|
68
68
|
}, [canGoBack])
|
|
69
69
|
|
|
70
70
|
const beforeRemoveHandle = useCallback((e: Event) => {
|
|
71
71
|
if (canGoBack.current) {
|
|
72
|
-
|
|
73
|
-
|
|
72
|
+
webViewRef.current?.goBack()
|
|
73
|
+
e.preventDefault()
|
|
74
74
|
}
|
|
75
75
|
}, [canGoBack])
|
|
76
76
|
|
|
@@ -80,10 +80,10 @@ const _WebView = forwardRef<HandlerRef<WebView, WebViewProps>, WebViewProps>((pr
|
|
|
80
80
|
|
|
81
81
|
useEffect(() => {
|
|
82
82
|
if (__mpx_mode__ === 'android') {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
83
|
+
BackHandler.addEventListener('hardwareBackPress', onAndroidBackPress)
|
|
84
|
+
return () => {
|
|
85
|
+
BackHandler.removeEventListener('hardwareBackPress', onAndroidBackPress)
|
|
86
|
+
}
|
|
87
87
|
}
|
|
88
88
|
}, [])
|
|
89
89
|
|
|
@@ -103,7 +103,7 @@ const _WebView = forwardRef<HandlerRef<WebView, WebViewProps>, WebViewProps>((pr
|
|
|
103
103
|
src: res.nativeEvent?.url
|
|
104
104
|
}
|
|
105
105
|
}
|
|
106
|
-
bindload(result)
|
|
106
|
+
bindload?.(result)
|
|
107
107
|
}
|
|
108
108
|
const _error = function (res: WebViewErrorEvent) {
|
|
109
109
|
const result = {
|
|
@@ -113,7 +113,7 @@ const _WebView = forwardRef<HandlerRef<WebView, WebViewProps>, WebViewProps>((pr
|
|
|
113
113
|
src: ''
|
|
114
114
|
}
|
|
115
115
|
}
|
|
116
|
-
binderror(result)
|
|
116
|
+
binderror?.(result)
|
|
117
117
|
}
|
|
118
118
|
const injectedJavaScript = `
|
|
119
119
|
if (window.ReactNativeWebView && window.ReactNativeWebView.postMessage) {
|
|
@@ -141,7 +141,7 @@ const _WebView = forwardRef<HandlerRef<WebView, WebViewProps>, WebViewProps>((pr
|
|
|
141
141
|
}
|
|
142
142
|
true;
|
|
143
143
|
`
|
|
144
|
-
const sendMessage = function(params: string) {
|
|
144
|
+
const sendMessage = function (params: string) {
|
|
145
145
|
return `
|
|
146
146
|
window.mpxWebviewMessageCallback(${params})
|
|
147
147
|
true;
|
|
@@ -156,7 +156,7 @@ const _WebView = forwardRef<HandlerRef<WebView, WebViewProps>, WebViewProps>((pr
|
|
|
156
156
|
|
|
157
157
|
const _onLoadProgress = function (event: WebViewProgressEvent) {
|
|
158
158
|
if (__mpx_mode__ === 'android') {
|
|
159
|
-
|
|
159
|
+
canGoBack.current = event.nativeEvent.canGoBack
|
|
160
160
|
}
|
|
161
161
|
}
|
|
162
162
|
const _message = function (res: WebViewMessageEvent) {
|
|
@@ -540,13 +540,14 @@ export const debounce = <T extends AnyFunc> (
|
|
|
540
540
|
): ((...args: Parameters<T>) => void) & { clear: () => void } => {
|
|
541
541
|
let timer: any
|
|
542
542
|
const wrapper = (...args: ReadonlyArray<any>) => {
|
|
543
|
-
clearTimeout(timer)
|
|
543
|
+
timer && clearTimeout(timer)
|
|
544
544
|
timer = setTimeout(() => {
|
|
545
545
|
func(...args)
|
|
546
546
|
}, delay)
|
|
547
547
|
}
|
|
548
548
|
wrapper.clear = () => {
|
|
549
|
-
clearTimeout(timer)
|
|
549
|
+
timer && clearTimeout(timer)
|
|
550
|
+
timer = null
|
|
550
551
|
}
|
|
551
552
|
return wrapper
|
|
552
553
|
}
|