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