Make isScrolledDown work
This commit is contained in:
@@ -39,9 +39,7 @@ function ListImpl<ItemT>(
|
|||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
|
|
||||||
function handleScrolledDownChange(didScrollDown: boolean) {
|
function handleScrolledDownChange(didScrollDown: boolean) {
|
||||||
startTransition(() => {
|
|
||||||
onScrolledDownChange?.(didScrollDown)
|
onScrolledDownChange?.(didScrollDown)
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const scrollHandler = useAnimatedScrollHandler({
|
const scrollHandler = useAnimatedScrollHandler({
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
import React, {memo, startTransition} from 'react'
|
import React, {memo, useRef, startTransition} from 'react'
|
||||||
import {FlatListProps, StyleSheet, View} from 'react-native'
|
import {FlatListProps, StyleSheet, View} 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'
|
||||||
import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback'
|
import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback'
|
||||||
|
import {batchedUpdates} from '#/lib/batchedUpdates'
|
||||||
|
|
||||||
export type ListMethods = FlatList_INTERNAL
|
export type ListMethods = FlatList_INTERNAL
|
||||||
export type ListProps<ItemT> = Omit<
|
export type ListProps<ItemT> = Omit<
|
||||||
@@ -30,7 +31,7 @@ function ListImpl<ItemT>(
|
|||||||
keyExtractor,
|
keyExtractor,
|
||||||
refreshing: _unsupportedRefreshing,
|
refreshing: _unsupportedRefreshing,
|
||||||
onEndReached,
|
onEndReached,
|
||||||
onEndReachedThreshold,
|
onEndReachedThreshold = 0,
|
||||||
onRefresh: _unsupportedOnRefresh,
|
onRefresh: _unsupportedOnRefresh,
|
||||||
onScrolledDownChange, // TODO
|
onScrolledDownChange, // TODO
|
||||||
renderItem,
|
renderItem,
|
||||||
@@ -101,18 +102,28 @@ function ListImpl<ItemT>(
|
|||||||
)
|
)
|
||||||
|
|
||||||
const [isVisible, setIsVisible] = React.useState(false)
|
const [isVisible, setIsVisible] = React.useState(false)
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (!isVisible) {
|
if (!isVisible) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
function handleScroll() {
|
function handleScroll() {
|
||||||
console.log(window.scrollY)
|
// console.log(window.scrollY)
|
||||||
}
|
}
|
||||||
window.addEventListener('scroll', handleScroll)
|
window.addEventListener('scroll', handleScroll)
|
||||||
return () => window.removeEventListener('scroll', handleScroll)
|
return () => window.removeEventListener('scroll', handleScroll)
|
||||||
}, [isVisible])
|
}, [isVisible])
|
||||||
|
|
||||||
|
const isScrolledDown = useRef(false)
|
||||||
|
function handleScrolledDownDetectorVisibleChange(isMarkerVisible: boolean) {
|
||||||
|
const didScrollDown = !isMarkerVisible
|
||||||
|
if (isScrolledDown.current !== didScrollDown) {
|
||||||
|
isScrolledDown.current = didScrollDown
|
||||||
|
startTransition(() => {
|
||||||
|
onScrolledDownChange?.(didScrollDown)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={{paddingTop: 0}}>
|
<View style={{paddingTop: 0}}>
|
||||||
<View {...props} style={style} ref={nativeRef}>
|
<View {...props} style={style} ref={nativeRef}>
|
||||||
@@ -125,9 +136,13 @@ function ListImpl<ItemT>(
|
|||||||
]}>
|
]}>
|
||||||
<View style={styles.visibilityDetector}>
|
<View style={styles.visibilityDetector}>
|
||||||
<Visibility
|
<Visibility
|
||||||
onVisibleChange={newIsVisible => {
|
topMargin={(headerOffset ?? 0) + 'px'}
|
||||||
setIsVisible(newIsVisible)
|
onVisibleChange={setIsVisible}
|
||||||
}}
|
/>
|
||||||
|
</View>
|
||||||
|
<View style={[styles.scrolledDownDetector, {height: headerOffset}]}>
|
||||||
|
<Visibility
|
||||||
|
onVisibleChange={handleScrolledDownDetectorVisibleChange}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
{header}
|
{header}
|
||||||
@@ -142,7 +157,7 @@ function ListImpl<ItemT>(
|
|||||||
))}
|
))}
|
||||||
{onEndReached && (
|
{onEndReached && (
|
||||||
<Visibility
|
<Visibility
|
||||||
threshold={onEndReachedThreshold}
|
topMargin={(onEndReachedThreshold ?? 0) * 100 + '%'}
|
||||||
onVisibleChange={isVisible => {
|
onVisibleChange={isVisible => {
|
||||||
if (isVisible) {
|
if (isVisible) {
|
||||||
onEndReached?.({
|
onEndReached?.({
|
||||||
@@ -185,10 +200,10 @@ let Row = function RowImpl<ItemT>({
|
|||||||
Row = React.memo(Row)
|
Row = React.memo(Row)
|
||||||
|
|
||||||
let Visibility = ({
|
let Visibility = ({
|
||||||
threshold = 0,
|
topMargin = '0px',
|
||||||
onVisibleChange,
|
onVisibleChange,
|
||||||
}: {
|
}: {
|
||||||
threshold?: number | null | undefined
|
topMargin?: string
|
||||||
onVisibleChange: (isVisible: boolean) => void
|
onVisibleChange: (isVisible: boolean) => void
|
||||||
}): React.ReactNode => {
|
}): React.ReactNode => {
|
||||||
const tailRef = React.useRef(null)
|
const tailRef = React.useRef(null)
|
||||||
@@ -196,25 +211,27 @@ let Visibility = ({
|
|||||||
|
|
||||||
const handleIntersection = useNonReactiveCallback(
|
const handleIntersection = useNonReactiveCallback(
|
||||||
(entries: IntersectionObserverEntry[]) => {
|
(entries: IntersectionObserverEntry[]) => {
|
||||||
|
batchedUpdates(() => {
|
||||||
entries.forEach(entry => {
|
entries.forEach(entry => {
|
||||||
if (entry.isIntersecting !== isIntersecting.current) {
|
if (entry.isIntersecting !== isIntersecting.current) {
|
||||||
isIntersecting.current = entry.isIntersecting
|
isIntersecting.current = entry.isIntersecting
|
||||||
onVisibleChange(entry.isIntersecting)
|
onVisibleChange(entry.isIntersecting)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
})
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
const observer = new IntersectionObserver(handleIntersection, {
|
const observer = new IntersectionObserver(handleIntersection, {
|
||||||
rootMargin: (threshold || 0) * 100 + '%',
|
rootMargin: `${topMargin} 0px 0px 0px`,
|
||||||
})
|
})
|
||||||
const tail: Element | null = tailRef.current!
|
const tail: Element | null = tailRef.current!
|
||||||
observer.observe(tail)
|
observer.observe(tail)
|
||||||
return () => {
|
return () => {
|
||||||
observer.unobserve(tail)
|
observer.unobserve(tail)
|
||||||
}
|
}
|
||||||
}, [handleIntersection, threshold])
|
}, [handleIntersection, topMargin])
|
||||||
|
|
||||||
return <View ref={tailRef} />
|
return <View ref={tailRef} />
|
||||||
}
|
}
|
||||||
@@ -247,4 +264,10 @@ const styles = StyleSheet.create({
|
|||||||
// @ts-ignore web only
|
// @ts-ignore web only
|
||||||
position: 'fixed',
|
position: 'fixed',
|
||||||
},
|
},
|
||||||
|
scrolledDownDetector: {
|
||||||
|
position: 'absolute',
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
pointerEvents: 'none',
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user