import { Logout, NotificationsOutlined, Tag, WarningAmberRounded, } from '@mui/icons-material' import clsx from 'clsx' import { useCallback, useMemo, useState } from 'react' import toast from 'react-hot-toast' import { useTranslation } from 'react-i18next' import { DaoPageMode, EntityType, NavWalletConnectedProps, PopupTriggerCustomComponent, } from '@dao-dao/types' import { abbreviateAddress, getDisplayNameForChainId, getImageUrlForChainId, } from '@dao-dao/utils' import { IconButton } from '../icon_buttons' import { useAppContextIfAvailable } from '../layout/AppContext' import { Notifications } from '../Notifications' import { ButtonPopup, FilterableItem, FilterableItemPopup, Popup, } from '../popup' import { ProfileImage } from '../profile' import { Tooltip } from '../tooltip' import { WalletLogo } from './WalletLogo' export const NavWalletConnected = ({ wallet, profile, entity, mergeProfileType, onMergeProfiles, disconnect, className, mode, ButtonLink, ...notificationsProps }: NavWalletConnectedProps) => { const { t } = useTranslation() // SDA error pages are not wrapped in app context, so we aren't guaranteed to // be in it. const { mode: appMode, inbox } = useAppContextIfAvailable() ?? {} const [addressPopupVisible, setAddressPopupVisible] = useState(false) const imageUrl = entity.loading ? profile.loading ? undefined : profile.data.imageUrl : entity.data.imageUrl const loading = entity.loading || profile.loading const ProfileImagePopup: PopupTriggerCustomComponent = useCallback( ({ onClick }) => (
), [mode, t, wallet, imageUrl, loading] ) const profileChainAddresses = useMemo( (): (FilterableItem & { chainId: string; address: string })[] => entity.loading || profile.loading ? [] : (entity.data.type === EntityType.Dao ? entity.data.daoInfo.accounts.map( ({ type, chainId, address }) => ({ key: chainId + ':' + address, label: getDisplayNameForChainId(chainId), iconUrl: getImageUrlForChainId(chainId), description: t(`accountTypeLabel.${type}`), rightNode: (

{abbreviateAddress(address, 6)}

), iconClassName: '!h-8 !w-8', contentContainerClassName: '!gap-4', chainId, address, }) ) : Object.entries(profile.data.chains).map( ([chainId, { address }]) => ({ key: chainId, label: getDisplayNameForChainId(chainId), iconUrl: getImageUrlForChainId(chainId), rightNode: (

{abbreviateAddress(address, 6)}

), iconClassName: '!h-8 !w-8', contentContainerClassName: '!gap-4', chainId, address, }) ) ).sort((a, b) => a.label.localeCompare(b.label)), [t, entity, profile] ) return (
{/* Notification popup */} {mode !== 'dock' && appMode === DaoPageMode.Dapp && inbox && notificationsProps.inbox && ( 0 ? t('title.notificationsWithCount', { count: inbox.items.length, }) : t('title.notifications'), props: { Icon: NotificationsOutlined, className: 'relative', variant: 'highlight', size: 'sm', // Show badge when notifications exist. children: !inbox.loading && inbox.items.length > 0 && (
), }, }} >

{t('title.notifications')}

{notificationsProps.inbox.buttons.refresh} {notificationsProps.inbox.buttons.clear} {notificationsProps.inbox.buttons.settings}
)} {mode !== 'dock' && !entity.loading && entity.data.type !== EntityType.Dao && !profile.loading && !!profile.data.uuid && mergeProfileType && ( )} {/* Icon overflows a bit on the bottom, so add extra room with pb-1. */}
{/* Image */} setAddressPopupVisible(true), }, { label: t('button.logOut'), Icon: Logout, onClick: disconnect, }, ], }, ]} topOffset={8} trigger={{ type: 'custom', Renderer: ProfileImagePopup, }} />
{ navigator.clipboard.writeText(address) toast.success( t('info.copiedChainAddress', { chain: getDisplayNameForChainId(chainId), }) ) }} searchPlaceholder={t('info.searchForChain')} trigger={{ type: 'manual', open: addressPopupVisible, setOpen: setAddressPopupVisible, }} />
) } const FILTERABLE_KEYS = ['label', 'chainId', 'address']