Hey is a decentralized and permissionless social media app built with Lens Protocol 馃尶
1import { UserGroupIcon } from "@heroicons/react/24/outline";
2import { GroupsFeedType } from "@hey/data/enums";
3import {
4 GroupsOrderBy,
5 type GroupsRequest,
6 PageSize,
7 useGroupsQuery
8} from "@hey/indexer";
9import { useCallback } from "react";
10import { WindowVirtualizer } from "virtua";
11import SingleGroup from "@/components/Shared/Group/SingleGroup";
12import GroupListShimmer from "@/components/Shared/Shimmer/GroupListShimmer";
13import { EmptyState, ErrorMessage } from "@/components/Shared/UI";
14import useLoadMoreOnIntersect from "@/hooks/useLoadMoreOnIntersect";
15import { useAccountStore } from "@/store/persisted/useAccountStore";
16
17interface ListProps {
18 feedType: GroupsFeedType;
19}
20
21const List = ({ feedType }: ListProps) => {
22 const { currentAccount } = useAccountStore();
23
24 const request: GroupsRequest = {
25 filter: {
26 ...(feedType === GroupsFeedType.Member && {
27 member: currentAccount?.address
28 }),
29 ...(feedType === GroupsFeedType.Managed && {
30 managedBy: { address: currentAccount?.address }
31 })
32 },
33 orderBy: GroupsOrderBy.LatestFirst,
34 pageSize: PageSize.Fifty
35 };
36
37 const { data, error, fetchMore, loading } = useGroupsQuery({
38 variables: { request }
39 });
40
41 const groups = data?.groups?.items;
42 const pageInfo = data?.groups?.pageInfo;
43 const hasMore = pageInfo?.next;
44
45 const handleEndReached = useCallback(async () => {
46 if (hasMore) {
47 await fetchMore({
48 variables: { request: { ...request, cursor: pageInfo?.next } }
49 });
50 }
51 }, [fetchMore, hasMore, pageInfo?.next, request]);
52
53 const loadMoreRef = useLoadMoreOnIntersect(handleEndReached);
54
55 if (loading) {
56 return <GroupListShimmer />;
57 }
58
59 if (!groups?.length) {
60 return (
61 <EmptyState
62 hideCard
63 icon={<UserGroupIcon className="size-8" />}
64 message="No groups."
65 />
66 );
67 }
68
69 if (error) {
70 return (
71 <ErrorMessage
72 className="m-5"
73 error={error}
74 title="Failed to load groups"
75 />
76 );
77 }
78
79 return (
80 <div className="virtual-divider-list-window">
81 <WindowVirtualizer>
82 {groups.map((group) => (
83 <div className="p-5" key={group.address}>
84 <SingleGroup group={group} isBig showDescription />
85 </div>
86 ))}
87 {hasMore && <span ref={loadMoreRef} />}
88 </WindowVirtualizer>
89 </div>
90 );
91};
92
93export default List;