Bluesky app fork with some witchin' additions 馃挮 witchsky.app
bluesky fork client
at main 117 lines 3.2 kB view raw
1import React from 'react' 2import {type AppBskyFeedGetLikes as GetLikes} from '@atproto/api' 3import {msg} from '@lingui/core/macro' 4import {useLingui} from '@lingui/react' 5 6import {useInitialNumToRender} from '#/lib/hooks/useInitialNumToRender' 7import {cleanError} from '#/lib/strings/errors' 8import {logger} from '#/logger' 9import {useLikedByQuery} from '#/state/queries/post-liked-by' 10import {useResolveUriQuery} from '#/state/queries/resolve-uri' 11import {ProfileCardWithFollowBtn} from '#/view/com/profile/ProfileCard' 12import {List} from '#/view/com/util/List' 13import {ListFooter, ListMaybePlaceholder} from '#/components/Lists' 14 15function renderItem({item, index}: {item: GetLikes.Like; index: number}) { 16 return ( 17 <ProfileCardWithFollowBtn 18 key={item.actor.did} 19 profile={item.actor} 20 noBorder={index === 0} 21 /> 22 ) 23} 24 25function keyExtractor(item: GetLikes.Like) { 26 return item.actor.did 27} 28 29export function LikedByList({uri}: {uri: string}) { 30 const {_} = useLingui() 31 const initialNumToRender = useInitialNumToRender() 32 const [isPTRing, setIsPTRing] = React.useState(false) 33 34 const { 35 data: resolvedUri, 36 error: resolveError, 37 isLoading: isUriLoading, 38 } = useResolveUriQuery(uri) 39 const { 40 data, 41 isLoading: isLikedByLoading, 42 isFetchingNextPage, 43 hasNextPage, 44 fetchNextPage, 45 error: likedByError, 46 refetch, 47 } = useLikedByQuery(resolvedUri?.uri) 48 49 const error = resolveError || likedByError 50 const isError = !!resolveError || !!likedByError 51 52 const likes = React.useMemo(() => { 53 if (data?.pages) { 54 return data.pages.flatMap(page => page.likes) 55 } 56 return [] 57 }, [data]) 58 59 const onRefresh = React.useCallback(async () => { 60 setIsPTRing(true) 61 try { 62 await refetch() 63 } catch (err) { 64 logger.error('Failed to refresh likes', {message: err}) 65 } 66 setIsPTRing(false) 67 }, [refetch, setIsPTRing]) 68 69 const onEndReached = React.useCallback(async () => { 70 if (isFetchingNextPage || !hasNextPage || isError) return 71 try { 72 await fetchNextPage() 73 } catch (err) { 74 logger.error('Failed to load more likes', {message: err}) 75 } 76 }, [isFetchingNextPage, hasNextPage, isError, fetchNextPage]) 77 78 if (likes.length < 1) { 79 return ( 80 <ListMaybePlaceholder 81 isLoading={isUriLoading || isLikedByLoading} 82 isError={isError} 83 emptyType="results" 84 emptyTitle={_(msg`No likes yet`)} 85 emptyMessage={_( 86 msg`Nobody has liked this yet. Maybe you should be the first!`, 87 )} 88 errorMessage={cleanError(resolveError || error)} 89 onRetry={isError ? refetch : undefined} 90 topBorder={false} 91 sideBorders={false} 92 /> 93 ) 94 } 95 96 return ( 97 <List 98 data={likes} 99 renderItem={renderItem} 100 keyExtractor={keyExtractor} 101 refreshing={isPTRing} 102 onRefresh={onRefresh} 103 onEndReached={onEndReached} 104 ListFooterComponent={ 105 <ListFooter 106 isFetchingNextPage={isFetchingNextPage} 107 error={cleanError(error)} 108 onRetry={fetchNextPage} 109 /> 110 } 111 onEndReachedThreshold={3} 112 initialNumToRender={initialNumToRender} 113 windowSize={11} 114 sideBorders={false} 115 /> 116 ) 117}