mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
1import React, {useCallback, useMemo, useState} from 'react'
2import {ActivityIndicator, RefreshControl, StyleSheet, View} from 'react-native'
3import {AppBskyFeedGetLikes as GetLikes} from '@atproto/api'
4import {CenteredView, FlatList} from '../util/Views'
5import {ErrorMessage} from '../util/error/ErrorMessage'
6import {ProfileCardWithFollowBtn} from '../profile/ProfileCard'
7import {usePalette} from 'lib/hooks/usePalette'
8import {logger} from '#/logger'
9import {useResolveUriQuery} from '#/state/queries/resolve-uri'
10import {usePostLikedByQuery} from '#/state/queries/post-liked-by'
11import {cleanError} from '#/lib/strings/errors'
12
13export function PostLikedBy({uri}: {uri: string}) {
14 const pal = usePalette('default')
15 const [isPTRing, setIsPTRing] = useState(false)
16 const {
17 data: resolvedUri,
18 error: resolveError,
19 isFetching: isFetchingResolvedUri,
20 } = useResolveUriQuery(uri)
21 const {
22 data,
23 isFetching,
24 isFetched,
25 isFetchingNextPage,
26 hasNextPage,
27 fetchNextPage,
28 isError,
29 error,
30 refetch,
31 } = usePostLikedByQuery(resolvedUri?.uri)
32 const likes = useMemo(() => {
33 if (data?.pages) {
34 return data.pages.flatMap(page => page.likes)
35 }
36 }, [data])
37
38 const onRefresh = useCallback(async () => {
39 setIsPTRing(true)
40 try {
41 await refetch()
42 } catch (err) {
43 logger.error('Failed to refresh likes', {error: err})
44 }
45 setIsPTRing(false)
46 }, [refetch, setIsPTRing])
47
48 const onEndReached = useCallback(async () => {
49 if (isFetching || !hasNextPage || isError) return
50 try {
51 await fetchNextPage()
52 } catch (err) {
53 logger.error('Failed to load more likes', {error: err})
54 }
55 }, [isFetching, hasNextPage, isError, fetchNextPage])
56
57 const renderItem = useCallback(({item}: {item: GetLikes.Like}) => {
58 return (
59 <ProfileCardWithFollowBtn key={item.actor.did} profile={item.actor} />
60 )
61 }, [])
62
63 if (isFetchingResolvedUri || !isFetched) {
64 return (
65 <CenteredView>
66 <ActivityIndicator />
67 </CenteredView>
68 )
69 }
70
71 // error
72 // =
73 if (resolveError || isError) {
74 return (
75 <CenteredView>
76 <ErrorMessage
77 message={cleanError(resolveError || error)}
78 onPressTryAgain={onRefresh}
79 />
80 </CenteredView>
81 )
82 }
83
84 // loaded
85 // =
86 return (
87 <FlatList
88 data={likes}
89 keyExtractor={item => item.actor.did}
90 refreshControl={
91 <RefreshControl
92 refreshing={isPTRing}
93 onRefresh={onRefresh}
94 tintColor={pal.colors.text}
95 titleColor={pal.colors.text}
96 />
97 }
98 onEndReached={onEndReached}
99 renderItem={renderItem}
100 initialNumToRender={15}
101 // FIXME(dan)
102 // eslint-disable-next-line react/no-unstable-nested-components
103 ListFooterComponent={() => (
104 <View style={styles.footer}>
105 {(isFetching || isFetchingNextPage) && <ActivityIndicator />}
106 </View>
107 )}
108 // @ts-ignore our .web version only -prf
109 desktopFixedHeight
110 />
111 )
112}
113
114const styles = StyleSheet.create({
115 footer: {
116 height: 200,
117 paddingTop: 20,
118 },
119})