import { useCallback, useEffect } from 'react'; import { createPortal } from 'react-dom'; import { useVoiceSession } from '../hooks/useVoiceSession'; import { isVoiceInputAvailable } from '../voice/capabilities'; import { VoiceWaveform } from './VoiceWaveform'; export function VoiceInputDialog({ open, disabled = false, onClose, onSend, onError, }: { open: boolean; disabled?: boolean; onClose: () => void; onSend: (text: string) => void; onError?: (message: string) => void; }) { const { phase, text, analyser, liveRecognition, stopListening, finishFallbackRecording, resetSession } = useVoiceSession({ active: open && !disabled, onError, }); const handleClose = useCallback(() => { stopListening(); resetSession(); onClose(); }, [onClose, resetSession, stopListening]); useEffect(() => { if (!open) return undefined; const previousOverflow = document.body.style.overflow; document.body.style.overflow = 'hidden'; const onKeyDown = (event: KeyboardEvent) => { if (event.key === 'Escape') handleClose(); }; window.addEventListener('keydown', onKeyDown); return () => { document.body.style.overflow = previousOverflow; window.removeEventListener('keydown', onKeyDown); }; }, [open, handleClose]); if (!open) return null; const listening = phase === 'listening'; const transcribing = phase === 'transcribing'; const busy = phase === 'requesting' || transcribing; const canSend = Boolean(text.trim()) && !busy && !disabled; const handleSend = () => { const value = text.trim(); if (!value || disabled) return; stopListening(); resetSession(); onSend(value); onClose(); }; const statusText = phase === 'requesting' ? '正在准备麦克风…' : listening ? liveRecognition ? '正在聆听,文字会实时显示' : '正在录音,完成后点击「完成识别」' : transcribing ? '正在识别…' : '可编辑识别结果后发送'; const supported = isVoiceInputAvailable(); if (!supported) { return createPortal(
e.stopPropagation()}>

当前浏览器不支持语音输入,请改用文字发送。

, document.body, ); } return createPortal(
event.stopPropagation()} >

语音输入

说出你想发送的内容

{transcribing ?