Bluesky app fork with some witchin' additions 馃挮 witchsky.app
bluesky fork client
at main 117 lines 3.2 kB view raw
1import {useCallback, useMemo, useState} 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 PostLikedBy({uri}: {uri: string}) { 30 const {_} = useLingui() 31 const initialNumToRender = useInitialNumToRender() 32 33 const [isPTRing, setIsPTRing] = useState(false) 34 35 const { 36 data: resolvedUri, 37 error: resolveError, 38 isLoading: isLoadingUri, 39 } = useResolveUriQuery(uri) 40 const { 41 data, 42 isLoading: isLoadingLikes, 43 isFetchingNextPage, 44 hasNextPage, 45 fetchNextPage, 46 error, 47 refetch, 48 } = useLikedByQuery(resolvedUri?.uri) 49 50 const isError = Boolean(resolveError || error) 51 52 const likes = useMemo(() => { 53 if (data?.pages) { 54 return data.pages.flatMap(page => page.likes) 55 } 56 return [] 57 }, [data]) 58 59 const onRefresh = 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 = 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={isLoadingUri || isLoadingLikes} 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 sideBorders={false} 90 topBorder={false} 91 /> 92 ) 93 } 94 95 return ( 96 <List 97 data={likes} 98 renderItem={renderItem} 99 keyExtractor={keyExtractor} 100 refreshing={isPTRing} 101 onRefresh={onRefresh} 102 onEndReached={onEndReached} 103 onEndReachedThreshold={4} 104 ListFooterComponent={ 105 <ListFooter 106 isFetchingNextPage={isFetchingNextPage} 107 error={cleanError(error)} 108 onRetry={fetchNextPage} 109 /> 110 } 111 desktopFixedHeight 112 initialNumToRender={initialNumToRender} 113 windowSize={11} 114 sideBorders={false} 115 /> 116 ) 117}