mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
1import React from 'react'
2import {AppBskyActorDefs as ActorDefs} from '@atproto/api'
3import {msg} from '@lingui/macro'
4import {useLingui} from '@lingui/react'
5
6import {cleanError} from '#/lib/strings/errors'
7import {logger} from '#/logger'
8import {useProfileFollowersQuery} from '#/state/queries/profile-followers'
9import {useResolveDidQuery} from '#/state/queries/resolve-uri'
10import {useInitialNumToRender} from 'lib/hooks/useInitialNumToRender'
11import {isWeb} from 'platform/detection'
12import {useSession} from 'state/session'
13import {ListFooter, ListMaybePlaceholder} from '#/components/Lists'
14import {List} from '../util/List'
15import {ProfileCardWithFollowBtn} from './ProfileCard'
16
17function renderItem({
18 item,
19 index,
20}: {
21 item: ActorDefs.ProfileViewBasic
22 index: number
23}) {
24 return (
25 <ProfileCardWithFollowBtn
26 key={item.did}
27 profile={item}
28 noBorder={index === 0 && !isWeb}
29 />
30 )
31}
32
33function keyExtractor(item: ActorDefs.ProfileViewBasic) {
34 return item.did
35}
36
37export function ProfileFollowers({name}: {name: string}) {
38 const {_} = useLingui()
39 const initialNumToRender = useInitialNumToRender()
40 const {currentAccount} = useSession()
41
42 const [isPTRing, setIsPTRing] = React.useState(false)
43 const {
44 data: resolvedDid,
45 isLoading: isDidLoading,
46 error: resolveError,
47 } = useResolveDidQuery(name)
48 const {
49 data,
50 isLoading: isFollowersLoading,
51 isFetchingNextPage,
52 hasNextPage,
53 fetchNextPage,
54 error,
55 refetch,
56 } = useProfileFollowersQuery(resolvedDid)
57
58 const isError = !!resolveError || !!error
59 const isMe = resolvedDid === currentAccount?.did
60
61 const followers = React.useMemo(() => {
62 if (data?.pages) {
63 return data.pages.flatMap(page => page.followers)
64 }
65 return []
66 }, [data])
67
68 const onRefresh = React.useCallback(async () => {
69 setIsPTRing(true)
70 try {
71 await refetch()
72 } catch (err) {
73 logger.error('Failed to refresh followers', {message: err})
74 }
75 setIsPTRing(false)
76 }, [refetch, setIsPTRing])
77
78 const onEndReached = React.useCallback(async () => {
79 if (isFetchingNextPage || !hasNextPage || !!error) return
80 try {
81 await fetchNextPage()
82 } catch (err) {
83 logger.error('Failed to load more followers', {message: err})
84 }
85 }, [isFetchingNextPage, hasNextPage, error, fetchNextPage])
86
87 if (followers.length < 1) {
88 return (
89 <ListMaybePlaceholder
90 isLoading={isDidLoading || isFollowersLoading}
91 isError={isError}
92 emptyType="results"
93 emptyMessage={
94 isMe
95 ? _(msg`You do not have any followers.`)
96 : _(msg`This user doesn't have any followers.`)
97 }
98 errorMessage={cleanError(resolveError || error)}
99 onRetry={isError ? refetch : undefined}
100 sideBorders={false}
101 />
102 )
103 }
104
105 return (
106 <List
107 data={followers}
108 renderItem={renderItem}
109 keyExtractor={keyExtractor}
110 refreshing={isPTRing}
111 onRefresh={onRefresh}
112 onEndReached={onEndReached}
113 onEndReachedThreshold={4}
114 ListFooterComponent={
115 <ListFooter
116 isFetchingNextPage={isFetchingNextPage}
117 error={cleanError(error)}
118 onRetry={fetchNextPage}
119 />
120 }
121 // @ts-ignore our .web version only -prf
122 desktopFixedHeight
123 initialNumToRender={initialNumToRender}
124 windowSize={11}
125 sideBorders={false}
126 />
127 )
128}