mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
1import React from 'react'
2import {AppBskyActorDefs} from '@atproto/api'
3import {msg} from '@lingui/macro'
4import {useLingui} from '@lingui/react'
5import {useFocusEffect} from '@react-navigation/native'
6
7import {useInitialNumToRender} from '#/lib/hooks/useInitialNumToRender'
8import {CommonNavigatorParams, NativeStackScreenProps} from '#/lib/routes/types'
9import {cleanError} from '#/lib/strings/errors'
10import {logger} from '#/logger'
11import {useProfileKnownFollowersQuery} from '#/state/queries/known-followers'
12import {useResolveDidQuery} from '#/state/queries/resolve-uri'
13import {useSetMinimalShellMode} from '#/state/shell'
14import {ProfileCardWithFollowBtn} from '#/view/com/profile/ProfileCard'
15import {List} from '#/view/com/util/List'
16import {ViewHeader} from '#/view/com/util/ViewHeader'
17import * as Layout from '#/components/Layout'
18import {ListFooter, ListMaybePlaceholder} from '#/components/Lists'
19
20function renderItem({
21 item,
22 index,
23}: {
24 item: AppBskyActorDefs.ProfileView
25 index: number
26}) {
27 return (
28 <ProfileCardWithFollowBtn
29 key={item.did}
30 profile={item}
31 noBorder={index === 0}
32 />
33 )
34}
35
36function keyExtractor(item: AppBskyActorDefs.ProfileViewBasic) {
37 return item.did
38}
39
40type Props = NativeStackScreenProps<
41 CommonNavigatorParams,
42 'ProfileKnownFollowers'
43>
44export const ProfileKnownFollowersScreen = ({route}: Props) => {
45 const {_} = useLingui()
46 const setMinimalShellMode = useSetMinimalShellMode()
47 const initialNumToRender = useInitialNumToRender()
48
49 const {name} = route.params
50
51 const [isPTRing, setIsPTRing] = React.useState(false)
52 const {
53 data: resolvedDid,
54 isLoading: isDidLoading,
55 error: resolveError,
56 } = useResolveDidQuery(route.params.name)
57 const {
58 data,
59 isLoading: isFollowersLoading,
60 isFetchingNextPage,
61 hasNextPage,
62 fetchNextPage,
63 error,
64 refetch,
65 } = useProfileKnownFollowersQuery(resolvedDid)
66
67 const onRefresh = React.useCallback(async () => {
68 setIsPTRing(true)
69 try {
70 await refetch()
71 } catch (err) {
72 logger.error('Failed to refresh followers', {message: err})
73 }
74 setIsPTRing(false)
75 }, [refetch, setIsPTRing])
76
77 const onEndReached = React.useCallback(async () => {
78 if (isFetchingNextPage || !hasNextPage || !!error) return
79 try {
80 await fetchNextPage()
81 } catch (err) {
82 logger.error('Failed to load more followers', {message: err})
83 }
84 }, [isFetchingNextPage, hasNextPage, error, fetchNextPage])
85
86 const followers = React.useMemo(() => {
87 if (data?.pages) {
88 return data.pages.flatMap(page => page.followers)
89 }
90 return []
91 }, [data])
92
93 const isError = Boolean(resolveError || error)
94
95 useFocusEffect(
96 React.useCallback(() => {
97 setMinimalShellMode(false)
98 }, [setMinimalShellMode]),
99 )
100
101 if (followers.length < 1) {
102 return (
103 <Layout.Screen>
104 <ViewHeader title={_(msg`Followers you know`)} />
105 <ListMaybePlaceholder
106 isLoading={isDidLoading || isFollowersLoading}
107 isError={isError}
108 emptyType="results"
109 emptyMessage={_(msg`You don't follow any users who follow @${name}.`)}
110 errorMessage={cleanError(resolveError || error)}
111 onRetry={isError ? refetch : undefined}
112 topBorder={false}
113 sideBorders={false}
114 />
115 </Layout.Screen>
116 )
117 }
118
119 return (
120 <Layout.Screen>
121 <ViewHeader title={_(msg`Followers you know`)} />
122 <List
123 data={followers}
124 renderItem={renderItem}
125 keyExtractor={keyExtractor}
126 refreshing={isPTRing}
127 onRefresh={onRefresh}
128 onEndReached={onEndReached}
129 onEndReachedThreshold={4}
130 ListFooterComponent={
131 <ListFooter
132 isFetchingNextPage={isFetchingNextPage}
133 error={cleanError(error)}
134 onRetry={fetchNextPage}
135 />
136 }
137 // @ts-ignore our .web version only -prf
138 desktopFixedHeight
139 initialNumToRender={initialNumToRender}
140 windowSize={11}
141 sideBorders={false}
142 />
143 </Layout.Screen>
144 )
145}