import { useEffect, useRef, useState, type KeyboardEvent } from 'react'; import { Button } from '@/ui/Button'; import { ChatMessage } from './ChatMessage'; import styles from './ChatPane.module.css'; interface Props { threadName: string; ids: string[]; enabled: boolean; onSend: (text: string) => Promise; onDelete: (id: string) => void; onOpenFile: (id: string) => void; onFiles?: (files: File[]) => void } export function ChatPane({ threadName, ids, enabled, onSend, onDelete, onOpenFile, onFiles }: Props) { const [text, setText] = useState(''); const [busy, setBusy] = useState(false); const [error, setError] = useState(''); const messages = useRef(null); const fileInput = useRef(null); const chronological = ids.slice().reverse(); useEffect(() => { messages.current?.scrollTo({ top: messages.current.scrollHeight }); }, [chronological.length]); async function submit() { const value = text.trim(); if (!value || busy || !enabled) return; setBusy(true); setError(''); try { await onSend(value); setText(''); } catch (cause) { setError(cause instanceof Error ? cause.message : '发送失败'); } finally { setBusy(false); } } function keyDown(event: KeyboardEvent) { if (event.key === 'Enter' && !event.shiftKey) { event.preventDefault(); void submit(); } } return (
{threadName}频道聊天
{chronological.length === 0 ?

在这里发送消息或文件,成员可以看到你的名称和头像。

: null} {chronological.map((id) => )}
{ event.preventDefault(); void submit(); }}> {onFiles ? <> { if (event.target.files?.length) onFiles([...event.target.files]); event.target.value = ''; }} />