diff --git a/src/view/com/util/List.tsx b/src/view/com/util/List.tsx index a84dacaef2..0ba499f09f 100644 --- a/src/view/com/util/List.tsx +++ b/src/view/com/util/List.tsx @@ -39,9 +39,7 @@ function ListImpl( const pal = usePalette('default') function handleScrolledDownChange(didScrollDown: boolean) { - startTransition(() => { - onScrolledDownChange?.(didScrollDown) - }) + onScrolledDownChange?.(didScrollDown) } const scrollHandler = useAnimatedScrollHandler({ diff --git a/src/view/com/util/List.web.tsx b/src/view/com/util/List.web.tsx index 478556b6e8..b18bdfaf77 100644 --- a/src/view/com/util/List.web.tsx +++ b/src/view/com/util/List.web.tsx @@ -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 {addStyle} from 'lib/styles' import {usePalette} from 'lib/hooks/usePalette' import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback' +import {batchedUpdates} from '#/lib/batchedUpdates' export type ListMethods = FlatList_INTERNAL export type ListProps = Omit< @@ -30,7 +31,7 @@ function ListImpl( keyExtractor, refreshing: _unsupportedRefreshing, onEndReached, - onEndReachedThreshold, + onEndReachedThreshold = 0, onRefresh: _unsupportedOnRefresh, onScrolledDownChange, // TODO renderItem, @@ -101,18 +102,28 @@ function ListImpl( ) const [isVisible, setIsVisible] = React.useState(false) - React.useEffect(() => { if (!isVisible) { return } function handleScroll() { - console.log(window.scrollY) + // console.log(window.scrollY) } window.addEventListener('scroll', handleScroll) return () => window.removeEventListener('scroll', handleScroll) }, [isVisible]) + const isScrolledDown = useRef(false) + function handleScrolledDownDetectorVisibleChange(isMarkerVisible: boolean) { + const didScrollDown = !isMarkerVisible + if (isScrolledDown.current !== didScrollDown) { + isScrolledDown.current = didScrollDown + startTransition(() => { + onScrolledDownChange?.(didScrollDown) + }) + } + } + return ( @@ -125,9 +136,13 @@ function ListImpl( ]}> { - setIsVisible(newIsVisible) - }} + topMargin={(headerOffset ?? 0) + 'px'} + onVisibleChange={setIsVisible} + /> + + + {header} @@ -142,7 +157,7 @@ function ListImpl( ))} {onEndReached && ( { if (isVisible) { onEndReached?.({ @@ -185,10 +200,10 @@ let Row = function RowImpl({ Row = React.memo(Row) let Visibility = ({ - threshold = 0, + topMargin = '0px', onVisibleChange, }: { - threshold?: number | null | undefined + topMargin?: string onVisibleChange: (isVisible: boolean) => void }): React.ReactNode => { const tailRef = React.useRef(null) @@ -196,25 +211,27 @@ let Visibility = ({ const handleIntersection = useNonReactiveCallback( (entries: IntersectionObserverEntry[]) => { - entries.forEach(entry => { - if (entry.isIntersecting !== isIntersecting.current) { - isIntersecting.current = entry.isIntersecting - onVisibleChange(entry.isIntersecting) - } + batchedUpdates(() => { + entries.forEach(entry => { + if (entry.isIntersecting !== isIntersecting.current) { + isIntersecting.current = entry.isIntersecting + onVisibleChange(entry.isIntersecting) + } + }) }) }, ) React.useEffect(() => { const observer = new IntersectionObserver(handleIntersection, { - rootMargin: (threshold || 0) * 100 + '%', + rootMargin: `${topMargin} 0px 0px 0px`, }) const tail: Element | null = tailRef.current! observer.observe(tail) return () => { observer.unobserve(tail) } - }, [handleIntersection, threshold]) + }, [handleIntersection, topMargin]) return } @@ -247,4 +264,10 @@ const styles = StyleSheet.create({ // @ts-ignore web only position: 'fixed', }, + scrolledDownDetector: { + position: 'absolute', + left: 0, + right: 0, + pointerEvents: 'none', + }, })