Hey is a decentralized and permissionless social media app built with Lens Protocol 馃尶
1import { UsersIcon } from "@heroicons/react/24/outline";
2import {
3 type FollowersYouKnowRequest,
4 useFollowersYouKnowQuery
5} from "@hey/indexer";
6import { motion } from "motion/react";
7import { useCallback } from "react";
8import { Virtualizer } from "virtua";
9import SingleAccount from "@/components/Shared/Account/SingleAccount";
10import AccountListShimmer from "@/components/Shared/Shimmer/AccountListShimmer";
11import { EmptyState, ErrorMessage } from "@/components/Shared/UI";
12import cn from "@/helpers/cn";
13import useLoadMoreOnIntersect from "@/hooks/useLoadMoreOnIntersect";
14import { useAccountStore } from "@/store/persisted/useAccountStore";
15import { accountsList } from "@/variants";
16
17interface FollowersYouKnowProps {
18 username: string;
19 address: string;
20}
21
22const FollowersYouKnow = ({ username, address }: FollowersYouKnowProps) => {
23 const { currentAccount } = useAccountStore();
24
25 const request: FollowersYouKnowRequest = {
26 observer: currentAccount?.address,
27 target: address
28 };
29
30 const { data, error, fetchMore, loading } = useFollowersYouKnowQuery({
31 skip: !address,
32 variables: { request }
33 });
34
35 const followersYouKnow = data?.followersYouKnow?.items;
36 const pageInfo = data?.followersYouKnow?.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 (!followersYouKnow?.length) {
54 return (
55 <EmptyState
56 hideCard
57 icon={<UsersIcon className="size-8" />}
58 message={
59 <div>
60 <span className="mr-1 font-bold">{username}</span>
61 <span>doesn't have any mutual followers.</span>
62 </div>
63 }
64 />
65 );
66 }
67
68 if (error) {
69 return (
70 <ErrorMessage
71 className="m-5"
72 error={error}
73 title="Failed to load mutual followers"
74 />
75 );
76 }
77
78 return (
79 <div className="max-h-[80vh] overflow-y-auto">
80 <Virtualizer>
81 {followersYouKnow.map((follower, index) => (
82 <motion.div
83 animate="visible"
84 className={cn(
85 "divider p-5",
86 index === followersYouKnow.length - 1 && "border-b-0"
87 )}
88 initial="hidden"
89 key={follower.follower.address}
90 variants={accountsList}
91 >
92 <SingleAccount
93 account={follower.follower}
94 hideFollowButton={
95 currentAccount?.address === follower.follower.address
96 }
97 hideUnfollowButton={
98 currentAccount?.address === follower.follower.address
99 }
100 showBio
101 showUserPreview={false}
102 />
103 </motion.div>
104 ))}
105 {hasMore && <span ref={loadMoreRef} />}
106 </Virtualizer>
107 </div>
108 );
109};
110
111export default FollowersYouKnow;