import { Message, OpenAIModel, OpenAIModelID } from '@/types'; import { IconPlayerStop, IconRepeat, IconSend } from '@tabler/icons-react'; import { FC, KeyboardEvent, MutableRefObject, useEffect, useState, } from 'react'; import { useTranslation } from 'next-i18next'; interface Props { messageIsStreaming: boolean; model: OpenAIModel; conversationIsEmpty: boolean; onSend: (message: Message) => void; onRegenerate: () => void; stopConversationRef: MutableRefObject; textareaRef: MutableRefObject; } export const ChatInput: FC = ({ messageIsStreaming, model, conversationIsEmpty, onSend, onRegenerate, stopConversationRef, textareaRef, }) => { const { t } = useTranslation('chat'); const [content, setContent] = useState(); const [isTyping, setIsTyping] = useState(false); const handleChange = (e: React.ChangeEvent) => { const value = e.target.value; const maxLength = model.id === OpenAIModelID.GPT_3_5 ? 12000 : 24000; if (value.length > maxLength) { alert( t( `Message limit is {{maxLength}} characters. You have entered {{valueLength}} characters.`, { maxLength, valueLength: value.length }, ), ); return; } setContent(value); }; const handleSend = () => { if (messageIsStreaming) { return; } if (!content) { alert(t('Please enter a message')); return; } onSend({ role: 'user', content }); setContent(''); if (window.innerWidth < 640 && textareaRef && textareaRef.current) { textareaRef.current.blur(); } }; const isMobile = () => { const userAgent = typeof window.navigator === 'undefined' ? '' : navigator.userAgent; const mobileRegex = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini|Mobile|mobile|CriOS/i; return mobileRegex.test(userAgent); }; const handleKeyDown = (e: KeyboardEvent) => { if (!isTyping) { if (e.key === 'Enter' && !e.shiftKey && !isMobile()) { e.preventDefault(); handleSend(); } } }; useEffect(() => { if (textareaRef && textareaRef.current) { textareaRef.current.style.height = 'inherit'; textareaRef.current.style.height = `${textareaRef.current?.scrollHeight}px`; textareaRef.current.style.overflow = `${ textareaRef?.current?.scrollHeight > 400 ? 'auto' : 'hidden' }`; } }, [content]); function handleStopConversation() { stopConversationRef.current = true; setTimeout(() => { stopConversationRef.current = false; }, 1000); } return (
{messageIsStreaming && ( )} {!messageIsStreaming && !conversationIsEmpty && ( )}