From 661d20d176352db603471590bcd945e2aa0c12c9 Mon Sep 17 00:00:00 2001 From: Eric Bailey Date: Wed, 27 Aug 2025 19:57:40 -0500 Subject: [PATCH] Add onItemSeen and automatic insets default --- src/components/List/index.tsx | 38 ++++++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/src/components/List/index.tsx b/src/components/List/index.tsx index 0797c1a999..52333b4d64 100644 --- a/src/components/List/index.tsx +++ b/src/components/List/index.tsx @@ -1,5 +1,5 @@ -import {forwardRef} from 'react' -import {type FlatList, type FlatListProps} from 'react-native' +import {forwardRef, useMemo} from 'react' +import {type FlatList, type FlatListProps, type ViewToken} from 'react-native' import Animated, { type FlatListPropsWithLayout, useAnimatedScrollHandler, @@ -18,7 +18,9 @@ export { * * - `contentOffset` - Doesn't work, use padding on `contentContainerStyle` instead. */ -type ListProps = Omit, 'contentOffset'> +type ListProps = Omit, 'contentOffset'> & { + onItemSeen?: (item: Item) => void +} export const List = forwardRef(function List( props: ListProps, @@ -47,9 +49,39 @@ export const List = forwardRef(function List( }, }) + const [onViewableItemsChanged, viewabilityConfig] = useMemo(() => { + const onItemSeen = props.onItemSeen + if (!onItemSeen) return [undefined, undefined] + return [ + (info: { + viewableItems: Array> + changed: Array> + }) => { + for (const item of info.changed) { + if (item.isViewable) { + onItemSeen(item.item) + } + } + }, + { + itemVisiblePercentThreshold: 40, + minimumViewTime: 0.5e3, + }, + ] + }, [props.onItemSeen]) + return ( ref={ref} + viewabilityConfig={viewabilityConfig} + onViewableItemsChanged={onViewableItemsChanged} + /** + * iOS automatically adds in the safe area to the scroll indicator + * insets, even though the overwhelming majority of our ScrollViews do + * not stretch from edge to edge. + * @see https://github.com/bluesky-social/social-app/pull/7131 + */ + automaticallyAdjustsScrollIndicatorInsets={false} {...(props as FlatListPropsWithLayout)} style={[ /*