import { useEffect, useRef, useState, type ChangeEvent, type KeyboardEvent } from 'react' import { AlertCircle, Send, X } from 'lucide-react' import type { ChatConnectionStatus, ChatMessageOut } from '@/hooks/useChat' import { formatLocalTime } from '@/lib/localTime' interface ChatPanelProps { messages: ChatMessageOut[] status: ChatConnectionStatus statusMessage: string | null onSend: (text: string) => void onClose: () => void } /** * Панель чата комнаты конференции (см. design/mockups/room.html, блок * `.chat-panel`). Всегда в развёрнутом виде рендерится только пока сама * панель открыта — сворачивание/разворачивание и счётчик непрочитанных * управляются на уровне RoomPage (WS-соединение живёт независимо от того, * открыта ли панель, — иначе при сворачивании терялась бы история). * * Textarea, а не `` из макета — сознательное отступление ради * Enter/Shift+Enter (перенос строки), стили сохранены визуально идентичными * пилюле-полю из макета. */ export function ChatPanel({ messages, status, statusMessage, onSend, onClose }: ChatPanelProps) { const [draft, setDraft] = useState('') const listRef = useRef(null) const textareaRef = useRef(null) // Автоскролл к последнему сообщению — только если пользователь и так был // внизу списка, чтобы не мешать чтению прокрученной вверх истории. useEffect(() => { const el = listRef.current if (!el) return const distanceFromBottom = el.scrollHeight - el.scrollTop - el.clientHeight if (distanceFromBottom < 120) { el.scrollTop = el.scrollHeight } }, [messages]) function handleSend() { const text = draft.trim() if (!text || status !== 'open') return onSend(text) setDraft('') if (textareaRef.current) textareaRef.current.style.height = 'auto' } function handleKeyDown(event: KeyboardEvent) { if (event.key === 'Enter' && !event.shiftKey) { event.preventDefault() handleSend() } } function handleDraftChange(event: ChangeEvent) { setDraft(event.target.value) // Авторасширение textarea до 4 строк, дальше — внутренний скролл. const el = event.target el.style.height = 'auto' el.style.height = `${Math.min(el.scrollHeight, 96)}px` } return (