Hey is a decentralized and permissionless social media app built with Lens Protocol 馃尶
at main 108 lines 2.9 kB view raw
1import { HeartIcon } from "@heroicons/react/24/outline"; 2import { 3 PageSize, 4 type PostReactionsRequest, 5 usePostReactionsQuery 6} from "@hey/indexer"; 7import { motion } from "motion/react"; 8import { useCallback } from "react"; 9import { Virtualizer } from "virtua"; 10import SingleAccount from "@/components/Shared/Account/SingleAccount"; 11import AccountListShimmer from "@/components/Shared/Shimmer/AccountListShimmer"; 12import { EmptyState, ErrorMessage } from "@/components/Shared/UI"; 13import cn from "@/helpers/cn"; 14import useLoadMoreOnIntersect from "@/hooks/useLoadMoreOnIntersect"; 15import { useAccountStore } from "@/store/persisted/useAccountStore"; 16import { accountsList } from "@/variants"; 17 18interface LikesProps { 19 postId: string; 20} 21 22const Likes = ({ postId }: LikesProps) => { 23 const { currentAccount } = useAccountStore(); 24 25 const request: PostReactionsRequest = { 26 pageSize: PageSize.Fifty, 27 post: postId 28 }; 29 30 const { data, error, fetchMore, loading } = usePostReactionsQuery({ 31 skip: !postId, 32 variables: { request } 33 }); 34 35 const accounts = data?.postReactions?.items; 36 const pageInfo = data?.postReactions?.pageInfo; 37 const hasMore = pageInfo?.next; 38 39 const handleEndReached = useCallback(async () => { 40 if (hasMore) { 41 await fetchMore({ 42 variables: { request: { ...request, cursor: pageInfo?.next } } 43 }); 44 } 45 }, [fetchMore, hasMore, pageInfo?.next, request]); 46 47 const loadMoreRef = useLoadMoreOnIntersect(handleEndReached); 48 49 if (loading) { 50 return <AccountListShimmer />; 51 } 52 53 if (!accounts?.length) { 54 return ( 55 <div className="p-5"> 56 <EmptyState 57 hideCard 58 icon={<HeartIcon className="size-8" />} 59 message="No likes." 60 /> 61 </div> 62 ); 63 } 64 65 if (error) { 66 return ( 67 <ErrorMessage 68 className="m-5" 69 error={error} 70 title="Failed to load likes" 71 /> 72 ); 73 } 74 75 return ( 76 <div className="max-h-[80vh] overflow-y-auto"> 77 <Virtualizer> 78 {accounts.map((like, index) => ( 79 <motion.div 80 animate="visible" 81 className={cn( 82 "divider p-5", 83 index === accounts.length - 1 && "border-b-0" 84 )} 85 initial="hidden" 86 key={like.account.address} 87 variants={accountsList} 88 > 89 <SingleAccount 90 account={like.account} 91 hideFollowButton={ 92 currentAccount?.address === like.account.address 93 } 94 hideUnfollowButton={ 95 currentAccount?.address === like.account.address 96 } 97 showBio 98 showUserPreview={false} 99 /> 100 </motion.div> 101 ))} 102 {hasMore && <span ref={loadMoreRef} />} 103 </Virtualizer> 104 </div> 105 ); 106}; 107 108export default Likes;