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