import { useCallback, useRef, useState } from 'react'; import { useMutation } from '@tanstack/react-query'; import { useTranslation } from 'react-i18next'; import { removeRelationship, type RelationshipUser } from '@/api/friends'; import { FramedAvatar, Nickname } from '@/components/profile/Cosmetics'; import { ErrorNotice } from '@/components/ui/ErrorNotice'; import { Menu, MenuItem, MenuSeparator } from '@/components/ui/Menu'; import { Popover } from '@/components/ui/Popover'; import { Button } from '@/components/ui/primitives'; import { DEFAULT_TIMEZONE } from '@/lib/timezones'; import { formatLastSeen, presenceDotClass } from '@/lib/presence'; import { useCurrentUser } from '@/lib/hooks'; import { useFriendsStore } from '@/stores/friends'; import { useOpenDirectChannel } from '@/components/friends/useOpenDirectChannel'; /** * Строка списка друзей: аватар с точкой статуса, имя (с подсказкой о * последнем входе) и действия — «Написать» и меню «…». * * Подсказка появляется по наведению и по фокусу: имя — кнопка, поэтому * доступна с клавиатуры, а клик по ней открывает беседу. */ export function FriendRow({ friend }: { friend: RelationshipUser }) { const { t, i18n } = useTranslation(); const currentUser = useCurrentUser(); const reload = useFriendsStore((state) => state.reload); const openDm = useOpenDirectChannel(); const [hintOpen, setHintOpen] = useState(false); const [menuOpen, setMenuOpen] = useState(false); const nameRef = useRef(null); const menuRef = useRef(null); const remove = useMutation({ mutationFn: () => removeRelationship(friend.user_id), onSuccess: () => reload(), }); const displayName = friend.display_name === '' ? friend.username : friend.display_name; const status = friend.visible_status; const statusLabel = t(`user.status.${status}`); // Время последнего входа — в часовом поясе пользователя из настроек. const time = formatLastSeen( friend.last_seen_at, currentUser.data?.timezone ?? DEFAULT_TIMEZONE, i18n.language, ); const hint = status !== 'offline' ? t('friends.lastSeen.online') : time === null ? t('friends.lastSeen.unknown') : t('friends.lastSeen.at', { time }); const closeHint = useCallback(() => setHintOpen(false), []); return (
  • {hint}

    {openDm.isError || remove.isError ? ( ) : null} setMenuOpen(false)} > { setMenuOpen(false); openDm.mutate(friend.user_id); }} > {t('friends.list.message')} { setMenuOpen(false); remove.mutate(); }} > {t('friends.list.remove')} { setMenuOpen(false); // Отдельной ручки блокировки нет: блокировка — тот же DELETE. remove.mutate(); }} > {t('friends.list.block')}
  • ); }