Skip to content

Commit 8cc2c03

Browse files
cleanup and pull-to-refresh action (experimental)
1 parent 4527cc2 commit 8cc2c03

File tree

1 file changed

+61
-80
lines changed

1 file changed

+61
-80
lines changed

src/BidirectionalFlatList.tsx

Lines changed: 61 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ const styles = StyleSheet.create({
3737
const waiter = () => new Promise((resolve) => setTimeout(resolve, 500));
3838
const dampingFactor = 5;
3939
const pullToRefreshReleaseThreshold = 100;
40-
40+
const EmptyFunction = () => null;
4141
/**
4242
* Note:
4343
* - `onEndReached` and `onStartReached` must return a promise.
@@ -76,6 +76,7 @@ export const BidirectionalFlatList = (React.forwardRef(
7676
onScroll,
7777
onStartReached,
7878
onStartReachedThreshold = 300,
79+
refreshing,
7980
renderItem,
8081
showDefaultLoadingIndicators = true,
8182
} = props;
@@ -101,13 +102,24 @@ export const BidirectionalFlatList = (React.forwardRef(
101102
const lastYValue = useRef(0);
102103
const panResponderActive = useRef(false);
103104
const onRefreshRef = useRef(onRefresh);
104-
const simulateRefreshAction = useRef(async () => {
105+
const stopRefreshAction = useRef(() => {
106+
fadeAnimation.setValue(0);
107+
Animated.spring(pan, {
108+
toValue: { x: 0, y: 0 },
109+
useNativeDriver: true,
110+
}).start();
111+
});
112+
const startRefreshAction = useRef(async () => {
105113
if (!scrollerRef.current) return;
114+
fadeAnimation.setValue(1);
115+
Animated.spring(pan, {
116+
toValue: { x: 0, y: 30 },
117+
useNativeDriver: true,
118+
}).start();
106119

107120
prependingItems.current = true;
108121
await waiter();
109122
await onRefreshRef.current?.();
110-
scrollerRef.current.style.overflow = 'auto';
111123

112124
Animated.spring(pan, {
113125
toValue: { x: 0, y: 0 },
@@ -118,9 +130,6 @@ export const BidirectionalFlatList = (React.forwardRef(
118130
});
119131

120132
const resetPanHandlerAndScroller = () => {
121-
if (scrollerRef.current) {
122-
scrollerRef.current.style.overflow = 'auto';
123-
}
124133
panResponderActive.current = false;
125134
};
126135

@@ -200,7 +209,6 @@ export const BidirectionalFlatList = (React.forwardRef(
200209
}
201210

202211
panResponderActive.current = true;
203-
// scrollerRef.current.style.overflow = 'hidden';
204212
pan.setValue({
205213
x: 0,
206214
y: lastYValue.current + gestureState.dy / dampingFactor,
@@ -227,19 +235,9 @@ export const BidirectionalFlatList = (React.forwardRef(
227235
pullToRefreshReleaseThreshold &&
228236
offsetFromTop.current <= 0
229237
) {
230-
fadeAnimation.setValue(1);
231-
Animated.spring(pan, {
232-
toValue: { x: 0, y: 30 },
233-
useNativeDriver: true,
234-
}).start();
235-
236-
simulateRefreshAction.current?.();
238+
startRefreshAction.current();
237239
} else {
238-
fadeAnimation.setValue(0);
239-
Animated.spring(pan, {
240-
toValue: { x: 0, y: 0 },
241-
useNativeDriver: true,
242-
}).start();
240+
stopRefreshAction.current();
243241
}
244242
},
245243
})
@@ -314,9 +312,9 @@ export const BidirectionalFlatList = (React.forwardRef(
314312
index,
315313
item: vData[indexInData],
316314
separators: {
317-
highlight: () => null,
318-
unhighlight: () => null,
319-
updateProps: () => null,
315+
highlight: EmptyFunction,
316+
unhighlight: EmptyFunction,
317+
updateProps: EmptyFunction,
320318
},
321319
})}
322320
{indexInData !== vData.length && !!ItemSeparatorComponent && (
@@ -363,30 +361,30 @@ export const BidirectionalFlatList = (React.forwardRef(
363361
updateVirtuoso();
364362
}, [enableAutoscrollToTop, autoscrollToTopThreshold, data, setVDate]);
365363

364+
useEffect(() => {
365+
if (refreshing) {
366+
startRefreshAction.current();
367+
}
368+
}, [refreshing]);
369+
366370
useImperativeHandle(
367371
ref,
368372
// @ts-ignore
369373
() => ({
370-
flashScrollIndicators: () => null,
371-
getNativeScrollRef: () => null,
372-
getScrollableNode: () => null,
373-
getScrollResponder: () => null,
374-
recordInteraction: () => null,
374+
flashScrollIndicators: EmptyFunction,
375+
getNativeScrollRef: EmptyFunction,
376+
getScrollableNode: EmptyFunction,
377+
getScrollResponder: EmptyFunction,
378+
recordInteraction: EmptyFunction,
375379
scrollToEnd: (params = { animated: true }) => {
376380
const { animated } = params;
377381
if (!vData?.length) return;
378382

379-
if (inverted) {
380-
virtuosoRef.current?.scrollToIndex({
381-
behavior: animated ? 'smooth' : 'auto',
382-
index: 0,
383-
});
384-
} else {
385-
virtuosoRef.current?.scrollToIndex({
386-
behavior: animated ? 'smooth' : 'auto',
387-
index: vData.length - 1,
388-
});
389-
}
383+
const index = inverted ? 0 : vData.length - 1;
384+
virtuosoRef.current?.scrollToIndex({
385+
behavior: animated ? 'smooth' : 'auto',
386+
index: index,
387+
});
390388
},
391389
scrollToIndex: ({
392390
animated,
@@ -428,8 +426,8 @@ export const BidirectionalFlatList = (React.forwardRef(
428426
index,
429427
});
430428
},
431-
scrollToOffset: () => null,
432-
setNativeProps: () => null,
429+
scrollToOffset: EmptyFunction,
430+
setNativeProps: EmptyFunction,
433431
}),
434432
[virtuosoRef, inverted, vData]
435433
);
@@ -439,31 +437,31 @@ export const BidirectionalFlatList = (React.forwardRef(
439437
}, [onRefresh]);
440438

441439
if (!vData?.length || vData?.length === 0) {
442-
return <ListEmptyComponent />;
440+
return ListEmptyComponent ? <ListEmptyComponent /> : null;
443441
}
444442

443+
const VirtuosoNode = (
444+
<Virtuoso<T>
445+
components={{
446+
Footer,
447+
Header,
448+
}}
449+
firstItemIndex={firstItemIndex.current}
450+
initialTopMostItemIndex={
451+
inverted ? vData.length - 1 - initialScrollIndex : initialScrollIndex
452+
}
453+
itemContent={itemContent}
454+
onScroll={handleScroll}
455+
overscan={300}
456+
ref={virtuosoRef}
457+
// @ts-ignore
458+
scrollerRef={(ref) => (scrollerRef.current = ref as HTMLElement)}
459+
totalCount={vData.length}
460+
/>
461+
);
462+
445463
if (!onRefresh) {
446-
return (
447-
<Virtuoso<T>
448-
components={{
449-
Footer,
450-
Header,
451-
}}
452-
firstItemIndex={firstItemIndex.current}
453-
initialTopMostItemIndex={
454-
inverted
455-
? vData.length - 1 - initialScrollIndex
456-
: initialScrollIndex
457-
}
458-
itemContent={itemContent}
459-
onScroll={handleScroll}
460-
overscan={300}
461-
ref={virtuosoRef}
462-
// @ts-ignore
463-
scrollerRef={(ref) => (scrollerRef.current = ref)}
464-
totalCount={vData.length}
465-
/>
466-
);
464+
return VirtuosoNode;
467465
}
468466

469467
return (
@@ -487,24 +485,7 @@ export const BidirectionalFlatList = (React.forwardRef(
487485
<ActivityIndicator />
488486
</Animated.View>
489487

490-
<Virtuoso<T>
491-
components={{
492-
Footer,
493-
Header,
494-
}}
495-
firstItemIndex={firstItemIndex.current}
496-
initialTopMostItemIndex={
497-
inverted
498-
? vData.length - 1 - initialScrollIndex
499-
: initialScrollIndex
500-
}
501-
itemContent={itemContent}
502-
onScroll={handleScroll}
503-
overscan={300}
504-
ref={virtuosoRef}
505-
scrollerRef={(ref) => (scrollerRef.current = ref as HTMLElement)}
506-
totalCount={vData.length}
507-
/>
488+
{VirtuosoNode}
508489
</Animated.View>
509490
</>
510491
);

0 commit comments

Comments
 (0)