import React, { useRef } from 'react'; import { defineMessages, useIntl, FormattedMessage } from 'react-intl'; import { Link, useHistory } from 'react-router-dom'; import HoverRefWrapper from 'soapbox/components/hover-ref-wrapper'; import VerificationBadge from 'soapbox/components/verification-badge'; import ActionButton from 'soapbox/features/ui/components/action-button'; import { useAppSelector } from 'soapbox/hooks'; import { getAcct } from 'soapbox/utils/accounts'; import { displayFqn } from 'soapbox/utils/state'; import Badge from './badge'; import RelativeTimestamp from './relative-timestamp'; import { Avatar, Emoji, HStack, Icon, IconButton, Stack, Text } from './ui'; import type { StatusApprovalStatus } from 'soapbox/normalizers/status'; import type { Account as AccountEntity } from 'soapbox/types/entities'; interface IInstanceFavicon { account: AccountEntity disabled?: boolean } const messages = defineMessages({ bot: { id: 'account.badges.bot', defaultMessage: 'Bot' }, }); const InstanceFavicon: React.FC = ({ account, disabled }) => { const history = useHistory(); const handleClick: React.MouseEventHandler = (e) => { e.stopPropagation(); if (disabled) return; const timelineUrl = `/timeline/${account.domain}`; if (!(e.ctrlKey || e.metaKey)) { history.push(timelineUrl); } else { window.open(timelineUrl, '_blank'); } }; return ( ); }; interface IProfilePopper { condition: boolean wrapper: (children: React.ReactNode) => React.ReactNode children: React.ReactNode } const ProfilePopper: React.FC = ({ condition, wrapper, children }) => { return ( <> {condition ? wrapper(children) : children} ); }; export interface IAccount { account: AccountEntity action?: React.ReactElement actionAlignment?: 'center' | 'top' actionIcon?: string actionTitle?: string /** Override other actions for specificity like mute/unmute. */ actionType?: 'muting' | 'blocking' | 'follow_request' avatarSize?: number hidden?: boolean hideActions?: boolean id?: string onActionClick?: (account: any) => void showProfileHoverCard?: boolean timestamp?: string timestampUrl?: string futureTimestamp?: boolean withAccountNote?: boolean withDate?: boolean withLinkToProfile?: boolean withRelationship?: boolean showEdit?: boolean approvalStatus?: StatusApprovalStatus emoji?: string note?: string } const Account = ({ account, actionType, action, actionIcon, actionTitle, actionAlignment = 'center', avatarSize = 42, hidden = false, hideActions = false, onActionClick, showProfileHoverCard = true, timestamp, timestampUrl, futureTimestamp = false, withAccountNote = false, withDate = false, withLinkToProfile = true, withRelationship = true, showEdit = false, approvalStatus, emoji, note, }: IAccount) => { const overflowRef = useRef(null); const actionRef = useRef(null); const me = useAppSelector((state) => state.me); const username = useAppSelector((state) => account ? getAcct(account, displayFqn(state)) : null); const handleAction = () => { onActionClick!(account); }; const renderAction = () => { if (action) { return action; } if (hideActions) { return null; } if (onActionClick && actionIcon) { return ( ); } if (account.id !== me) { return ; } return null; }; const intl = useIntl(); if (!account) { return null; } if (hidden) { return ( <> {account.display_name} {account.username} ); } if (withDate) timestamp = account.created_at; const LinkEl: any = withLinkToProfile ? Link : 'div'; return (
{children}} > event.stopPropagation()} > {emoji && ( )}
{children}} > event.stopPropagation()} > {account.verified && } {account.bot && } @{username} {account.favicon && ( )} {(timestamp) ? ( <> · {timestampUrl ? ( event.stopPropagation()}> ) : ( )} ) : null} {approvalStatus && ['pending', 'rejected'].includes(approvalStatus) && ( <> · {approvalStatus === 'pending' ? : } )} {showEdit ? ( <> · ) : null} {actionType === 'muting' && account.mute_expires_at ? ( <> · ) : null} {note ? ( {note} ) : withAccountNote && ( )}
{withRelationship ? renderAction() : null}
); }; export default Account;