This commit is contained in:
Dan Abramov
2023-12-15 06:07:43 +00:00
parent c01243620a
commit 534427d234
+27 -16
View File
@@ -1,5 +1,5 @@
import React, {memo, useRef, startTransition} from 'react'
import {FlatListProps, StyleSheet, View} from 'react-native'
import {FlatListProps, StyleSheet, View, ViewProps} from 'react-native'
import {addStyle} from 'lib/styles'
import {usePalette} from 'lib/hooks/usePalette'
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
@@ -114,8 +114,8 @@ function ListImpl<ItemT>(
}, [isVisible])
const isScrolledDown = useRef(false)
function handleScrolledDownDetectorVisibleChange(isMarkerVisible: boolean) {
const didScrollDown = !isMarkerVisible
function handleAboveTheFoldVisibleChange(isAboveTheFold: boolean) {
const didScrollDown = !isAboveTheFold
if (isScrolledDown.current !== didScrollDown) {
isScrolledDown.current = didScrollDown
startTransition(() => {
@@ -125,8 +125,11 @@ function ListImpl<ItemT>(
}
return (
<View style={{paddingTop: 0}}>
<View {...props} style={style} ref={nativeRef}>
<Visibility
onVisibleChange={setIsVisible}
style={styles.parentTreeVisibilityDetector}
/>
<View
style={[
styles.contentContainer,
@@ -134,14 +137,10 @@ function ListImpl<ItemT>(
desktopFixedHeight ? styles.minHeightViewport : null,
pal.border,
]}>
<View style={styles.visibilityDetector}>
<Visibility onVisibleChange={setIsVisible} />
</View>
<View style={[styles.scrolledDownDetector, {height: headerOffset}]}>
<Visibility
onVisibleChange={handleScrolledDownDetectorVisibleChange}
onVisibleChange={handleAboveTheFoldVisibleChange}
style={[styles.aboveTheFoldDetector, {height: headerOffset}]}
/>
</View>
{header}
{(data as Array<ItemT>).map((item, index) => (
<Row<ItemT>
@@ -167,7 +166,6 @@ function ListImpl<ItemT>(
{footer}
</View>
</View>
</View>
)
}
@@ -199,9 +197,11 @@ Row = React.memo(Row)
let Visibility = ({
topMargin = '0px',
onVisibleChange,
style,
}: {
topMargin?: string
onVisibleChange: (isVisible: boolean) => void
style?: ViewProps['style']
}): React.ReactNode => {
const tailRef = React.useRef(null)
const isIntersecting = React.useRef(false)
@@ -230,7 +230,9 @@ let Visibility = ({
}
}, [handleIntersection, topMargin])
return <View ref={tailRef} />
return (
<View ref={tailRef} style={addStyle(styles.visibilityDetector, style)} />
)
}
Visibility = React.memo(Visibility)
@@ -257,14 +259,23 @@ const styles = StyleSheet.create({
// @ts-ignore web only
minHeight: '100vh',
},
visibilityDetector: {
parentTreeVisibilityDetector: {
// @ts-ignore web only
position: 'fixed',
},
scrolledDownDetector: {
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
},
aboveTheFoldDetector: {
position: 'absolute',
top: 0,
left: 0,
right: 0,
// Bottom is dynamic.
},
visibilityDetector: {
pointerEvents: 'none',
zIndex: -1,
},
})