Fix broken pagination for lists tab on profile page (#6221)

* set onEndReachedThreshold to 2 for ProfileLists

* Add a footer for ProfileLists component for consistency

* Remove logs

* Revert onEndReachedThreshold change on Feed component

* Fix threshold defaults to match native

* Align lists and feedgens

---------

Co-authored-by: Dan Abramov <dan.abramov@gmail.com>
This commit is contained in:
Khuddite
2024-11-23 14:52:36 -05:00
committed by GitHub
parent 30af267bb4
commit f802f81fa6
3 changed files with 36 additions and 4 deletions
+17 -1
View File
@@ -1,8 +1,10 @@
import React from 'react' import React from 'react'
import { import {
ActivityIndicator,
findNodeHandle, findNodeHandle,
ListRenderItemInfo, ListRenderItemInfo,
StyleProp, StyleProp,
StyleSheet,
View, View,
ViewStyle, ViewStyle,
} from 'react-native' } from 'react-native'
@@ -10,6 +12,7 @@ import {msg} from '@lingui/macro'
import {useLingui} from '@lingui/react' import {useLingui} from '@lingui/react'
import {useQueryClient} from '@tanstack/react-query' import {useQueryClient} from '@tanstack/react-query'
import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries'
import {cleanError} from '#/lib/strings/errors' import {cleanError} from '#/lib/strings/errors'
import {logger} from '#/logger' import {logger} from '#/logger'
import {isNative, isWeb} from '#/platform/detection' import {isNative, isWeb} from '#/platform/detection'
@@ -57,6 +60,7 @@ export const ProfileFeedgens = React.forwardRef<
data, data,
isFetching, isFetching,
isFetched, isFetched,
isFetchingNextPage,
hasNextPage, hasNextPage,
fetchNextPage, fetchNextPage,
isError, isError,
@@ -65,6 +69,7 @@ export const ProfileFeedgens = React.forwardRef<
} = useProfileFeedgensQuery(did, opts) } = useProfileFeedgensQuery(did, opts)
const isEmpty = !isFetching && !data?.pages[0]?.feeds.length const isEmpty = !isFetching && !data?.pages[0]?.feeds.length
const {data: preferences} = usePreferencesQuery() const {data: preferences} = usePreferencesQuery()
const {isMobile} = useWebMediaQueries()
const items = React.useMemo(() => { const items = React.useMemo(() => {
let items: any[] = [] let items: any[] = []
@@ -180,6 +185,12 @@ export const ProfileFeedgens = React.forwardRef<
} }
}, [enabled, scrollElRef, setScrollViewTag]) }, [enabled, scrollElRef, setScrollViewTag])
const ProfileFeedgensFooter = React.useCallback(() => {
return isFetchingNextPage ? (
<ActivityIndicator style={[styles.footer]} />
) : null
}, [isFetchingNextPage])
return ( return (
<View testID={testID} style={style}> <View testID={testID} style={style}>
<List <List
@@ -188,11 +199,12 @@ export const ProfileFeedgens = React.forwardRef<
data={items} data={items}
keyExtractor={(item: any) => item._reactKey || item.uri} keyExtractor={(item: any) => item._reactKey || item.uri}
renderItem={renderItem} renderItem={renderItem}
ListFooterComponent={ProfileFeedgensFooter}
refreshing={isPTRing} refreshing={isPTRing}
onRefresh={onRefresh} onRefresh={onRefresh}
headerOffset={headerOffset} headerOffset={headerOffset}
progressViewOffset={ios(0)} progressViewOffset={ios(0)}
contentContainerStyle={isNative && {paddingBottom: headerOffset + 100}} contentContainerStyle={isMobile && {paddingBottom: headerOffset + 100}}
indicatorStyle={t.name === 'light' ? 'black' : 'white'} indicatorStyle={t.name === 'light' ? 'black' : 'white'}
removeClippedSubviews={true} removeClippedSubviews={true}
// @ts-ignore our .web version only -prf // @ts-ignore our .web version only -prf
@@ -202,3 +214,7 @@ export const ProfileFeedgens = React.forwardRef<
</View> </View>
) )
}) })
const styles = StyleSheet.create({
footer: {paddingTop: 20},
})
+17 -1
View File
@@ -1,8 +1,10 @@
import React from 'react' import React from 'react'
import { import {
ActivityIndicator,
findNodeHandle, findNodeHandle,
ListRenderItemInfo, ListRenderItemInfo,
StyleProp, StyleProp,
StyleSheet,
View, View,
ViewStyle, ViewStyle,
} from 'react-native' } from 'react-native'
@@ -10,6 +12,7 @@ import {msg} from '@lingui/macro'
import {useLingui} from '@lingui/react' import {useLingui} from '@lingui/react'
import {useQueryClient} from '@tanstack/react-query' import {useQueryClient} from '@tanstack/react-query'
import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries'
import {cleanError} from '#/lib/strings/errors' import {cleanError} from '#/lib/strings/errors'
import {logger} from '#/logger' import {logger} from '#/logger'
import {isNative, isWeb} from '#/platform/detection' import {isNative, isWeb} from '#/platform/detection'
@@ -56,10 +59,12 @@ export const ProfileLists = React.forwardRef<SectionRef, ProfileListsProps>(
isFetched, isFetched,
hasNextPage, hasNextPage,
fetchNextPage, fetchNextPage,
isFetchingNextPage,
isError, isError,
error, error,
refetch, refetch,
} = useProfileListsQuery(did, opts) } = useProfileListsQuery(did, opts)
const {isMobile} = useWebMediaQueries()
const isEmpty = !isFetching && !data?.pages[0]?.lists.length const isEmpty = !isFetching && !data?.pages[0]?.lists.length
const items = React.useMemo(() => { const items = React.useMemo(() => {
@@ -176,6 +181,12 @@ export const ProfileLists = React.forwardRef<SectionRef, ProfileListsProps>(
} }
}, [enabled, scrollElRef, setScrollViewTag]) }, [enabled, scrollElRef, setScrollViewTag])
const ProfileListsFooter = React.useCallback(() => {
return isFetchingNextPage ? (
<ActivityIndicator style={[styles.footer]} />
) : null
}, [isFetchingNextPage])
return ( return (
<View testID={testID} style={style}> <View testID={testID} style={style}>
<List <List
@@ -184,12 +195,13 @@ export const ProfileLists = React.forwardRef<SectionRef, ProfileListsProps>(
data={items} data={items}
keyExtractor={(item: any) => item._reactKey || item.uri} keyExtractor={(item: any) => item._reactKey || item.uri}
renderItem={renderItemInner} renderItem={renderItemInner}
ListFooterComponent={ProfileListsFooter}
refreshing={isPTRing} refreshing={isPTRing}
onRefresh={onRefresh} onRefresh={onRefresh}
headerOffset={headerOffset} headerOffset={headerOffset}
progressViewOffset={ios(0)} progressViewOffset={ios(0)}
contentContainerStyle={ contentContainerStyle={
isNative && {paddingBottom: headerOffset + 100} isMobile && {paddingBottom: headerOffset + 100}
} }
indicatorStyle={t.name === 'light' ? 'black' : 'white'} indicatorStyle={t.name === 'light' ? 'black' : 'white'}
removeClippedSubviews={true} removeClippedSubviews={true}
@@ -201,3 +213,7 @@ export const ProfileLists = React.forwardRef<SectionRef, ProfileListsProps>(
) )
}, },
) )
const styles = StyleSheet.create({
footer: {paddingTop: 20},
})
+2 -2
View File
@@ -46,9 +46,9 @@ function ListImpl<ItemT>(
keyExtractor, keyExtractor,
refreshing: _unsupportedRefreshing, refreshing: _unsupportedRefreshing,
onStartReached, onStartReached,
onStartReachedThreshold = 0, onStartReachedThreshold = 2,
onEndReached, onEndReached,
onEndReachedThreshold = 0, onEndReachedThreshold = 2,
onRefresh: _unsupportedOnRefresh, onRefresh: _unsupportedOnRefresh,
onScrolledDownChange, onScrolledDownChange,
onContentSizeChange, onContentSizeChange,