Hey is a decentralized and permissionless social media app built with Lens Protocol 馃尶
1import { CheckBadgeIcon } from "@heroicons/react/24/solid";
2import getAccount from "@hey/helpers/getAccount";
3import getAvatar from "@hey/helpers/getAvatar";
4import type { AccountFragment } from "@hey/indexer";
5import { memo } from "react";
6import Markup from "@/components/Shared/Markup";
7import Slug from "@/components/Shared/Slug";
8import { Image } from "@/components/Shared/UI";
9import cn from "@/helpers/cn";
10import getMentions from "@/helpers/getMentions";
11import AccountLink from "./AccountLink";
12import AccountPreview from "./AccountPreview";
13import FollowUnfollowButton from "./FollowUnfollowButton";
14
15interface SingleAccountProps {
16 hideFollowButton?: boolean;
17 hideUnfollowButton?: boolean;
18 isBig?: boolean;
19 isVerified?: boolean;
20 linkToAccount?: boolean;
21 account: AccountFragment;
22 showBio?: boolean;
23 showUserPreview?: boolean;
24}
25
26const SingleAccount = ({
27 hideFollowButton = false,
28 hideUnfollowButton = false,
29 isBig = false,
30 isVerified = false,
31 linkToAccount = true,
32 account,
33 showBio = false,
34 showUserPreview = true
35}: SingleAccountProps) => {
36 const UserAvatar = () => (
37 <Image
38 alt={account.address}
39 className={cn(
40 isBig ? "size-14" : "size-11",
41 "rounded-full border border-gray-200 bg-gray-200 dark:border-gray-700"
42 )}
43 height={isBig ? 56 : 44}
44 loading="lazy"
45 src={getAvatar(account)}
46 width={isBig ? 56 : 44}
47 />
48 );
49
50 const UserName = () => (
51 <div>
52 <div
53 className={cn(
54 { "font-bold": isBig },
55 "flex max-w-sm items-center gap-x-1.5"
56 )}
57 >
58 <div className="truncate font-semibold">{getAccount(account).name}</div>
59 {(isVerified || account.hasSubscribed) && (
60 <CheckBadgeIcon className="size-4 text-brand-500" />
61 )}
62 {account.heyEns?.localName && (
63 <Image
64 className="size-4"
65 src="https://ens.domains/assets/brand/mark/ens-mark-Blue.svg"
66 />
67 )}
68 </div>
69 <Slug className="text-sm" slug={getAccount(account).username} />
70 </div>
71 );
72
73 const AccountInfo = () => (
74 <AccountPreview
75 address={account.address}
76 showUserPreview={showUserPreview}
77 username={account.username?.localName}
78 >
79 <div className="mr-8 flex items-center gap-x-3">
80 <UserAvatar />
81 <UserName />
82 </div>
83 </AccountPreview>
84 );
85
86 return (
87 <div className="flex flex-col gap-y-2">
88 <div className="flex items-center justify-between">
89 {linkToAccount && account.address ? (
90 <AccountLink account={account}>
91 <AccountInfo />
92 </AccountLink>
93 ) : (
94 <AccountInfo />
95 )}
96 <FollowUnfollowButton
97 account={account}
98 hideFollowButton={hideFollowButton}
99 hideUnfollowButton={hideUnfollowButton}
100 small
101 />
102 </div>
103 {showBio && account?.metadata?.bio && (
104 <div
105 className={cn(
106 isBig ? "text-base" : "text-sm",
107 "mt-2",
108 "linkify leading-6"
109 )}
110 style={{ wordBreak: "break-word" }}
111 >
112 <Markup mentions={getMentions(account.metadata.bio)}>
113 {account?.metadata.bio}
114 </Markup>
115 </div>
116 )}
117 </div>
118 );
119};
120
121export default memo(SingleAccount);