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 AccountSchema } from 'soapbox/schemas'; interface IInstanceFavicon { account: AccountSchema; 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'); } }; if (!account.pleroma?.favicon) { return null; } 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: AccountSchema; 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; emojiUrl?: 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, emojiUrl, 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'; const linkProps = withLinkToProfile ? { to: `/@${account.acct}`, title: account.acct, onClick: (event: React.MouseEvent) => event.stopPropagation(), } : {}; return (
{children}} > {emoji && ( )}
{children}} > {account.verified && } {account.bot && } @{username} {account.pleroma?.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;