import { useCallback, useRef, useState, type ReactNode, type RefObject } from 'react'; import { useMutation, useQueryClient } from '@tanstack/react-query'; import { useTranslation } from 'react-i18next'; import { useNavigate } from 'react-router'; import { logout } from '@/api/auth'; import { currentUserQueryKey, updateProfile } from '@/api/users'; import { userStatuses, type UserStatus } from '@/api/types'; import { Avatar } from '@/components/ui/Avatar'; import { Menu, MenuGroupLabel, MenuItem, MenuSeparator } from '@/components/ui/Menu'; import { Popover } from '@/components/ui/Popover'; import { VolumeSlider, VoiceDeviceList } from '@/components/voice/VoiceControls'; import { useCurrentUser } from '@/lib/hooks'; import { useApiErrorMessage } from '@/lib/useApiErrorMessage'; import { useDeviceChoice } from '@/lib/useMediaDevices'; import { useGatewayStore } from '@/stores/gateway'; import { useMessagesStore } from '@/stores/messages'; import { useSessionStore } from '@/stores/session'; import { useUiStore } from '@/stores/ui'; import { useVoiceStore } from '@/stores/voice'; import { SettingsModal } from '@/pages/settings/SettingsModal'; /** Статусы, которые можно выставить из мини-профиля: «не в сети» сервер выводит сам. */ const selectableStatuses = userStatuses.filter((value) => value !== 'offline'); /** Цвет точки статуса — тот же, что в списках участников. */ const statusDotClass: Record = { online: 'bg-success', idle: 'bg-warning', dnd: 'bg-danger', invisible: 'bg-fg-muted', offline: 'bg-fg-muted', }; /** Иконка с перечёркиванием для выключенного состояния (как в мессенджерах). */ function PanelIcon({ glyph, off }: { glyph: string; off: boolean }) { return (