UserDisplay.tsx
1 import { Box } from '@mui/material'; 2 import { blo } from 'blo'; 3 import { useMemo } from 'react'; 4 import useGetEns from 'src/libs/hooks/use-get-ens'; 5 import { useWeb3Context } from 'src/libs/hooks/useWeb3Context'; 6 import { useRootStore } from 'src/store/root'; 7 import { useShallow } from 'zustand/shallow'; 8 9 import { Avatar, AvatarProps } from './Avatar'; 10 import { BadgeSize, ExclamationBadge } from './badges/ExclamationBadge'; 11 import { UserNameText, UserNameTextProps } from './UserNameText'; 12 13 type UserDisplayProps = { 14 oneLiner?: boolean; 15 avatarProps?: AvatarProps; 16 titleProps?: Omit<UserNameTextProps, 'address' | 'domainName'>; 17 subtitleProps?: Omit<UserNameTextProps, 'address' | 'domainName'>; 18 withLink?: boolean; 19 funnel?: string; 20 }; 21 22 export const UserDisplay: React.FC<UserDisplayProps> = ({ 23 oneLiner = false, 24 avatarProps, 25 titleProps, 26 subtitleProps, 27 withLink, 28 funnel, 29 }) => { 30 const [account, defaultDomain, domainsLoading] = useRootStore( 31 useShallow((state) => [state.account, state.defaultDomain, state.domainsLoading]) 32 ); 33 const { readOnlyMode } = useWeb3Context(); 34 35 const fallbackImage = useMemo( 36 () => (account ? blo(account as `0x${string}`) : undefined), 37 [account] 38 ); 39 const loading = domainsLoading; 40 41 return ( 42 <Box sx={{ display: 'flex', alignItems: 'center', gap: 2 }}> 43 <Avatar 44 fallbackImage={fallbackImage} 45 image={defaultDomain?.avatar} 46 loading={loading} 47 badge={<ExclamationBadge size={BadgeSize.SM} />} 48 invisibleBadge={!readOnlyMode} 49 {...avatarProps} 50 /> 51 <Box sx={{ display: 'flex', flexDirection: 'column' }}> 52 {!oneLiner && defaultDomain?.name ? ( 53 <> 54 <UserNameText 55 address={account} 56 loading={loading} 57 domainName={defaultDomain.name} 58 variant="h4" 59 link={withLink ? `https://etherscan.io/address/${account}` : undefined} 60 funnel={funnel} 61 {...titleProps} 62 /> 63 <UserNameText 64 address={account} 65 loading={loading} 66 variant="caption" 67 {...subtitleProps} 68 /> 69 </> 70 ) : ( 71 <UserNameText 72 address={account} 73 domainName={defaultDomain?.name} 74 loading={loading} 75 variant="h4" 76 link={withLink ? `https://etherscan.io/address/${account}` : undefined} 77 funnel={funnel} 78 {...titleProps} 79 /> 80 )} 81 </Box> 82 </Box> 83 ); 84 }; 85 86 interface ExternalUserDisplayProps { 87 avatarProps?: AvatarProps; 88 titleProps?: Omit<UserNameTextProps, 'address'>; 89 address: string; 90 } 91 92 export const ExternalUserDisplay: React.FC<ExternalUserDisplayProps> = ({ 93 avatarProps, 94 titleProps, 95 address, 96 }) => { 97 const { name, avatar } = useGetEns(address); 98 99 const fallbackImage = useMemo( 100 () => (address ? blo(address as `0x${string}`) : undefined), 101 [address] 102 ); 103 return ( 104 <Box sx={{ display: 'flex', alignItems: 'center', gap: 2 }}> 105 <Avatar image={avatar} fallbackImage={fallbackImage} {...avatarProps} /> 106 <UserNameText 107 variant="h4" 108 address={address} 109 domainName={name} 110 link={`https://etherscan.io/address/${address}`} 111 iconSize={14} 112 {...titleProps} 113 funnel={'Delegation power panel: Governance'} 114 /> 115 </Box> 116 ); 117 };