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