Only intercept scroll handler on iOS

The ScrollProvider wrapping and animatedProps for scroll indicator
insets are iOS-only. On other platforms, let the List use the scroll
handler from context directly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Samuel Newman
2026-02-17 12:11:09 +02:00
parent 8485ac65df
commit 58629959e8
5 changed files with 186 additions and 149 deletions
@@ -201,40 +201,48 @@ export function ProfileStarterPacks({
[isTabletOrDesktop, t.atoms.border_contrast_low],
)
const list = (
<List
testID={testID ? `${testID}-flatlist` : undefined}
ref={scrollElRef}
data={items}
renderItem={renderItem}
keyExtractor={keyExtractor}
refreshing={isPTRing}
headerOffset={headerOffset}
progressViewOffset={ios(0)}
contentContainerStyle={{
minHeight: height + headerOffset,
paddingBottom: bottomBarOffset,
}}
removeClippedSubviews={true}
desktopFixedHeight
onEndReached={onEndReached}
onRefresh={onRefresh}
ListEmptyComponent={
data ? (isMe ? EmptyComponent : undefined) : FeedLoadingPlaceholder
}
ListFooterComponent={
!!data && items?.length !== 0 && isMe ? CreateAnother : undefined
}
animatedProps={IS_IOS ? animatedProps : undefined}
/>
)
return (
<View testID={testID} style={style}>
<ScrollProvider
onScroll={onScrollWorklet}
onBeginDrag={onBeginDragFromContext}
onEndDrag={onEndDragFromContext}
onMomentumBegin={onMomentumEndFromContext}
onMomentumEnd={onMomentumEndFromContext}>
<List
testID={testID ? `${testID}-flatlist` : undefined}
ref={scrollElRef}
data={items}
renderItem={renderItem}
keyExtractor={keyExtractor}
refreshing={isPTRing}
headerOffset={headerOffset}
progressViewOffset={ios(0)}
contentContainerStyle={{
minHeight: height + headerOffset,
paddingBottom: bottomBarOffset,
}}
removeClippedSubviews={true}
desktopFixedHeight
onEndReached={onEndReached}
onRefresh={onRefresh}
ListEmptyComponent={
data ? (isMe ? EmptyComponent : undefined) : FeedLoadingPlaceholder
}
ListFooterComponent={
!!data && items?.length !== 0 && isMe ? CreateAnother : undefined
}
animatedProps={animatedProps}
/>
</ScrollProvider>
{IS_IOS ? (
<ScrollProvider
onScroll={onScrollWorklet}
onBeginDrag={onBeginDragFromContext}
onEndDrag={onEndDragFromContext}
onMomentumBegin={onMomentumEndFromContext}
onMomentumEnd={onMomentumEndFromContext}>
{list}
</ScrollProvider>
) : (
list
)}
</View>
)
}
+37 -32
View File
@@ -159,40 +159,45 @@ export function ProfileLabelsSection({
[labelerInfo, isSubscribed, numItems, t],
)
const list = (
<List
ref={scrollElRef}
data={labelValues}
renderItem={renderItem}
keyExtractor={keyExtractor}
contentContainerStyle={a.px_xl}
headerOffset={headerHeight}
progressViewOffset={ios(0)}
ListHeaderComponent={
<LabelerListHeader
isLabelerLoading={isLabelerLoading}
labelerInfo={labelerInfo}
labelerError={labelerError}
hasValues={labelValues.length !== 0}
isSubscribed={isSubscribed}
/>
}
ListFooterComponent={
<ListFooter height={headerHeight + 180} style={a.border_transparent} />
}
animatedProps={IS_IOS ? animatedProps : undefined}
/>
)
return (
<View>
<ScrollProvider
onScroll={onScrollWorklet}
onBeginDrag={onBeginDragFromContext}
onEndDrag={onEndDragFromContext}
onMomentumBegin={onMomentumEndFromContext}
onMomentumEnd={onMomentumEndFromContext}>
<List
ref={scrollElRef}
data={labelValues}
renderItem={renderItem}
keyExtractor={keyExtractor}
contentContainerStyle={a.px_xl}
headerOffset={headerHeight}
progressViewOffset={ios(0)}
ListHeaderComponent={
<LabelerListHeader
isLabelerLoading={isLabelerLoading}
labelerInfo={labelerInfo}
labelerError={labelerError}
hasValues={labelValues.length !== 0}
isSubscribed={isSubscribed}
/>
}
ListFooterComponent={
<ListFooter
height={headerHeight + 180}
style={a.border_transparent}
/>
}
animatedProps={animatedProps}
/>
</ScrollProvider>
{IS_IOS ? (
<ScrollProvider
onScroll={onScrollWorklet}
onBeginDrag={onBeginDragFromContext}
onEndDrag={onEndDragFromContext}
onMomentumBegin={onMomentumEndFromContext}
onMomentumEnd={onMomentumEndFromContext}>
{list}
</ScrollProvider>
) : (
list
)}
</View>
)
}
+32 -24
View File
@@ -286,32 +286,40 @@ export function ProfileFeedgens({
isEmpty,
])
const list = (
<List
testID={testID ? `${testID}-flatlist` : undefined}
ref={scrollElRef}
data={items}
keyExtractor={keyExtractor}
renderItem={renderItem}
ListFooterComponent={ProfileFeedgensFooter}
refreshing={isPTRing}
onRefresh={onRefresh}
headerOffset={headerOffset}
progressViewOffset={ios(0)}
removeClippedSubviews={true}
desktopFixedHeight
onEndReached={onEndReached}
contentContainerStyle={{minHeight: height + headerOffset}}
animatedProps={IS_IOS ? animatedProps : undefined}
/>
)
return (
<View testID={testID} style={style}>
<ScrollProvider
onScroll={onScrollWorklet}
onBeginDrag={onBeginDragFromContext}
onEndDrag={onEndDragFromContext}
onMomentumBegin={onMomentumEndFromContext}
onMomentumEnd={onMomentumEndFromContext}>
<List
testID={testID ? `${testID}-flatlist` : undefined}
ref={scrollElRef}
data={items}
keyExtractor={keyExtractor}
renderItem={renderItem}
ListFooterComponent={ProfileFeedgensFooter}
refreshing={isPTRing}
onRefresh={onRefresh}
headerOffset={headerOffset}
progressViewOffset={ios(0)}
removeClippedSubviews={true}
desktopFixedHeight
onEndReached={onEndReached}
contentContainerStyle={{minHeight: height + headerOffset}}
animatedProps={animatedProps}
/>
</ScrollProvider>
{IS_IOS ? (
<ScrollProvider
onScroll={onScrollWorklet}
onBeginDrag={onBeginDragFromContext}
onEndDrag={onEndDragFromContext}
onMomentumBegin={onMomentumEndFromContext}
onMomentumEnd={onMomentumEndFromContext}>
{list}
</ScrollProvider>
) : (
list
)}
</View>
)
}
+32 -24
View File
@@ -285,32 +285,40 @@ export function ProfileLists({
isEmpty,
])
const list = (
<List
testID={testID ? `${testID}-flatlist` : undefined}
ref={scrollElRef}
data={items}
keyExtractor={keyExtractor}
renderItem={renderItem}
ListFooterComponent={ProfileListsFooter}
refreshing={isPTRing}
onRefresh={onRefresh}
headerOffset={headerOffset}
progressViewOffset={ios(0)}
removeClippedSubviews={true}
desktopFixedHeight
onEndReached={onEndReached}
contentContainerStyle={{minHeight: height + headerOffset}}
animatedProps={IS_IOS ? animatedProps : undefined}
/>
)
return (
<View testID={testID} style={style}>
<ScrollProvider
onScroll={onScrollWorklet}
onBeginDrag={onBeginDragFromContext}
onEndDrag={onEndDragFromContext}
onMomentumBegin={onMomentumEndFromContext}
onMomentumEnd={onMomentumEndFromContext}>
<List
testID={testID ? `${testID}-flatlist` : undefined}
ref={scrollElRef}
data={items}
keyExtractor={keyExtractor}
renderItem={renderItem}
ListFooterComponent={ProfileListsFooter}
refreshing={isPTRing}
onRefresh={onRefresh}
headerOffset={headerOffset}
progressViewOffset={ios(0)}
removeClippedSubviews={true}
desktopFixedHeight
onEndReached={onEndReached}
contentContainerStyle={{minHeight: height + headerOffset}}
animatedProps={animatedProps}
/>
</ScrollProvider>
{IS_IOS ? (
<ScrollProvider
onScroll={onScrollWorklet}
onBeginDrag={onBeginDragFromContext}
onEndDrag={onEndDragFromContext}
onMomentumBegin={onMomentumEndFromContext}
onMomentumEnd={onMomentumEndFromContext}>
{list}
</ScrollProvider>
) : (
list
)}
</View>
)
}
+45 -37
View File
@@ -1045,45 +1045,53 @@ let PostFeed = ({
return {}
})
const list = (
<List
testID={testID ? `${testID}-flatlist` : undefined}
ref={scrollElRef}
data={feedItems}
keyExtractor={(item: FeedRow) => item.key}
renderItem={renderItem}
ListFooterComponent={FeedFooter}
ListHeaderComponent={ListHeaderComponent}
refreshing={isPTRing}
onRefresh={() => void onRefresh()}
headerOffset={headerOffset}
progressViewOffset={progressViewOffset}
contentContainerStyle={{
minHeight: Dimensions.get('window').height * 1.5,
}}
onScrolledDownChange={handleScrolledDownChange}
onEndReached={() => void onEndReached()}
onEndReachedThreshold={2} // number of posts left to trigger load more
removeClippedSubviews={true}
extraData={extraData}
desktopFixedHeight={
desktopFixedHeightOffset ? desktopFixedHeightOffset : true
}
initialNumToRender={initialNumToRenderOverride ?? initialNumToRender}
windowSize={9}
maxToRenderPerBatch={IS_IOS ? 5 : 1}
updateCellsBatchingPeriod={40}
onItemSeen={onItemSeen}
animatedProps={IS_IOS ? animatedProps : undefined}
/>
)
return (
<View testID={testID} style={style}>
<ScrollProvider
onScroll={onScrollWorklet}
onBeginDrag={onBeginDragFromContext}
onEndDrag={onEndDragFromContext}
onMomentumBegin={onMomentumEndFromContext}
onMomentumEnd={onMomentumEndFromContext}>
<List
testID={testID ? `${testID}-flatlist` : undefined}
ref={scrollElRef}
data={feedItems}
keyExtractor={(item: FeedRow) => item.key}
renderItem={renderItem}
ListFooterComponent={FeedFooter}
ListHeaderComponent={ListHeaderComponent}
refreshing={isPTRing}
onRefresh={() => void onRefresh()}
headerOffset={headerOffset}
progressViewOffset={progressViewOffset}
contentContainerStyle={{
minHeight: Dimensions.get('window').height * 1.5,
}}
onScrolledDownChange={handleScrolledDownChange}
onEndReached={() => void onEndReached()}
onEndReachedThreshold={2} // number of posts left to trigger load more
removeClippedSubviews={true}
extraData={extraData}
desktopFixedHeight={
desktopFixedHeightOffset ? desktopFixedHeightOffset : true
}
initialNumToRender={initialNumToRenderOverride ?? initialNumToRender}
windowSize={9}
maxToRenderPerBatch={IS_IOS ? 5 : 1}
updateCellsBatchingPeriod={40}
onItemSeen={onItemSeen}
animatedProps={animatedProps}
/>
</ScrollProvider>
{IS_IOS ? (
<ScrollProvider
onScroll={onScrollWorklet}
onBeginDrag={onBeginDragFromContext}
onEndDrag={onEndDragFromContext}
onMomentumBegin={onMomentumEndFromContext}
onMomentumEnd={onMomentumEndFromContext}>
{list}
</ScrollProvider>
) : (
list
)}
</View>
)
}