diff options
Diffstat (limited to 'src/view/com/profile/ProfileFollows.tsx')
-rw-r--r-- | src/view/com/profile/ProfileFollows.tsx | 104 |
1 files changed, 67 insertions, 37 deletions
diff --git a/src/view/com/profile/ProfileFollows.tsx b/src/view/com/profile/ProfileFollows.tsx index abc35398a..77ae72da4 100644 --- a/src/view/com/profile/ProfileFollows.tsx +++ b/src/view/com/profile/ProfileFollows.tsx @@ -1,42 +1,73 @@ -import React, {useEffect} from 'react' -import {observer} from 'mobx-react-lite' +import React from 'react' import {ActivityIndicator, RefreshControl, StyleSheet, View} from 'react-native' +import {AppBskyActorDefs as ActorDefs} from '@atproto/api' import {CenteredView, FlatList} from '../util/Views' -import {UserFollowsModel, FollowItem} from 'state/models/lists/user-follows' import {ErrorMessage} from '../util/error/ErrorMessage' import {ProfileCardWithFollowBtn} from './ProfileCard' -import {useStores} from 'state/index' import {usePalette} from 'lib/hooks/usePalette' +import {useProfileFollowsQuery} from '#/state/queries/profile-follows' +import {useResolveDidQuery} from '#/state/queries/resolve-uri' import {logger} from '#/logger' +import {cleanError} from '#/lib/strings/errors' -export const ProfileFollows = observer(function ProfileFollows({ - name, -}: { - name: string -}) { +export function ProfileFollows({name}: {name: string}) { const pal = usePalette('default') - const store = useStores() - const view = React.useMemo( - () => new UserFollowsModel(store, {actor: name}), - [store, name], - ) + const [isPTRing, setIsPTRing] = React.useState(false) + const { + data: resolvedDid, + error: resolveError, + isFetching: isFetchingDid, + } = useResolveDidQuery(name) + const { + data, + dataUpdatedAt, + isFetching, + isFetched, + isFetchingNextPage, + hasNextPage, + fetchNextPage, + isError, + error, + refetch, + } = useProfileFollowsQuery(resolvedDid?.did) - useEffect(() => { - view - .loadMore() - .catch(err => logger.error('Failed to fetch user follows', err)) - }, [view]) + const follows = React.useMemo(() => { + if (data?.pages) { + return data.pages.flatMap(page => page.follows) + } + }, [data]) - const onRefresh = () => { - view.refresh() - } - const onEndReached = () => { - view - .loadMore() - .catch(err => logger.error('Failed to load more follows', err)) + const onRefresh = React.useCallback(async () => { + setIsPTRing(true) + try { + await refetch() + } catch (err) { + logger.error('Failed to refresh follows', {error: err}) + } + setIsPTRing(false) + }, [refetch, setIsPTRing]) + + const onEndReached = async () => { + if (isFetching || !hasNextPage || isError) return + try { + await fetchNextPage() + } catch (err) { + logger.error('Failed to load more follows', {error: err}) + } } - if (!view.hasLoaded) { + const renderItem = React.useCallback( + ({item}: {item: ActorDefs.ProfileViewBasic}) => ( + <ProfileCardWithFollowBtn + key={item.did} + profile={item} + dataUpdatedAt={dataUpdatedAt} + /> + ), + [dataUpdatedAt], + ) + + if (isFetchingDid || !isFetched) { return ( <CenteredView> <ActivityIndicator /> @@ -46,26 +77,26 @@ export const ProfileFollows = observer(function ProfileFollows({ // error // = - if (view.hasError) { + if (resolveError || isError) { return ( <CenteredView> - <ErrorMessage message={view.error} onPressTryAgain={onRefresh} /> + <ErrorMessage + message={cleanError(resolveError || error)} + onPressTryAgain={onRefresh} + /> </CenteredView> ) } // loaded // = - const renderItem = ({item}: {item: FollowItem}) => ( - <ProfileCardWithFollowBtn key={item.did} profile={item} /> - ) return ( <FlatList - data={view.follows} + data={follows} keyExtractor={item => item.did} refreshControl={ <RefreshControl - refreshing={view.isRefreshing} + refreshing={isPTRing} onRefresh={onRefresh} tintColor={pal.colors.text} titleColor={pal.colors.text} @@ -78,15 +109,14 @@ export const ProfileFollows = observer(function ProfileFollows({ // eslint-disable-next-line react/no-unstable-nested-components ListFooterComponent={() => ( <View style={styles.footer}> - {view.isLoading && <ActivityIndicator />} + {(isFetching || isFetchingNextPage) && <ActivityIndicator />} </View> )} - extraData={view.isLoading} // @ts-ignore our .web version only -prf desktopFixedHeight /> ) -}) +} const styles = StyleSheet.create({ footer: { |