Hey is a decentralized and permissionless social media app built with Lens Protocol 🌿
1import { NoSymbolIcon } from "@heroicons/react/24/outline";
2import { STATIC_IMAGES_URL } from "@hey/data/constants";
3import { AccountFeedType } from "@hey/data/enums";
4import getAccount from "@hey/helpers/getAccount";
5import isAccountDeleted from "@hey/helpers/isAccountDeleted";
6import { useAccountQuery } from "@hey/indexer";
7import { useState } from "react";
8import { useParams } from "react-router";
9import NewPost from "@/components/Composer/NewPost";
10import Custom404 from "@/components/Shared/404";
11import Custom500 from "@/components/Shared/500";
12import Cover from "@/components/Shared/Cover";
13import PageLayout from "@/components/Shared/PageLayout";
14import { EmptyState } from "@/components/Shared/UI";
15import {
16 getBlockedByMeMessage,
17 getBlockedMeMessage
18} from "@/helpers/getBlockedMessage";
19import { useAccountLinkStore } from "@/store/non-persisted/navigation/useAccountLinkStore";
20import { useAccountStore } from "@/store/persisted/useAccountStore";
21import AccountFeed from "./AccountFeed";
22import DeletedDetails from "./DeletedDetails";
23import Details from "./Details";
24import FeedType from "./FeedType";
25import AccountPageShimmer from "./Shimmer";
26
27const ViewAccount = () => {
28 const { address, username } = useParams<{
29 address: string;
30 username: string;
31 }>();
32 const [feedType, setFeedType] = useState<AccountFeedType>(
33 AccountFeedType.Feed
34 );
35
36 const { currentAccount } = useAccountStore();
37 const { cachedAccount, setCachedAccount } = useAccountLinkStore();
38
39 const { data, error, loading } = useAccountQuery({
40 onCompleted: (data) => {
41 if (data?.account) {
42 setCachedAccount(null);
43 }
44 },
45 skip: address ? !address : !username,
46 variables: {
47 request: {
48 ...(address
49 ? { address }
50 : { username: { localName: username as string } })
51 }
52 }
53 });
54
55 const account = data?.account ?? cachedAccount;
56
57 if ((!username && !address) || (loading && !cachedAccount)) {
58 return <AccountPageShimmer />;
59 }
60
61 if (!account) {
62 return <Custom404 />;
63 }
64
65 if (error) {
66 return <Custom500 />;
67 }
68
69 const isDeleted = isAccountDeleted(account);
70 const isBlockedByMe = account?.operations?.isBlockedByMe;
71 const hasBlockedMe = account?.operations?.hasBlockedMe;
72
73 const accountInfo = getAccount(account);
74
75 const renderAccountDetails = () => {
76 if (isDeleted) return <DeletedDetails account={account} />;
77
78 return (
79 <Details
80 account={account}
81 hasBlockedMe={account?.operations?.hasBlockedMe || false}
82 isBlockedByMe={account?.operations?.isBlockedByMe || false}
83 />
84 );
85 };
86
87 const renderEmptyState = () => {
88 const message = isDeleted
89 ? "Account Deleted"
90 : isBlockedByMe
91 ? getBlockedByMeMessage(account)
92 : hasBlockedMe
93 ? getBlockedMeMessage(account)
94 : null;
95
96 return (
97 <EmptyState
98 icon={<NoSymbolIcon className="size-8" />}
99 message={message}
100 />
101 );
102 };
103
104 return (
105 <PageLayout
106 title={`${accountInfo.name} (${accountInfo.username}) • Hey`}
107 zeroTopMargin
108 >
109 <Cover
110 cover={
111 account?.metadata?.coverPicture ||
112 `${STATIC_IMAGES_URL}/patterns/2.svg`
113 }
114 />
115 {renderAccountDetails()}
116 {isDeleted || isBlockedByMe || hasBlockedMe ? (
117 renderEmptyState()
118 ) : (
119 <>
120 <FeedType feedType={feedType} setFeedType={setFeedType} />
121 {currentAccount?.address === account?.address && <NewPost />}
122 {(feedType === AccountFeedType.Feed ||
123 feedType === AccountFeedType.Replies ||
124 feedType === AccountFeedType.Media ||
125 feedType === AccountFeedType.Collects) && (
126 <AccountFeed
127 address={account.address}
128 type={feedType}
129 username={accountInfo.username}
130 />
131 )}
132 </>
133 )}
134 </PageLayout>
135 );
136};
137
138export default ViewAccount;