import React, { useEffect, useRef, useState } from 'react'; import { useRecoilValue, useRecoilState } from 'recoil'; import SubmitButton from './SubmitButton'; import OpenAIOptions from './OpenAIOptions'; import PluginsOptions from './PluginsOptions'; import ChatGPTOptions from './ChatGPTOptions'; import BingAIOptions from './BingAIOptions'; import GoogleOptions from './GoogleOptions'; import AnthropicOptions from './AnthropicOptions'; import NewConversationMenu from './NewConversationMenu'; import AdjustToneButton from './AdjustToneButton'; import Footer from './Footer'; import TextareaAutosize from 'react-textarea-autosize'; import { useMessageHandler } from '~/utils/handleSubmit'; import store from '~/store'; export default function TextChat({ isSearchView = false }) { const inputRef = useRef(null); const isComposing = useRef(false); const conversation = useRecoilValue(store.conversation); const latestMessage = useRecoilValue(store.latestMessage); const [text, setText] = useRecoilState(store.text); const endpointsConfig = useRecoilValue(store.endpointsConfig); const isSubmitting = useRecoilValue(store.isSubmitting); // TODO: do we need this? const disabled = false; const { ask, stopGenerating } = useMessageHandler(); const [showBingToneSetting, setShowBingToneSetting] = useState(false); const isNotAppendable = latestMessage?.unfinished & !isSubmitting || latestMessage?.error; const { conversationId, jailbreak } = conversation || {}; // auto focus to input, when enter a conversation. useEffect(() => { if (!conversationId) { return; } // Prevents Settings from not showing on new conversation, also prevents showing toneStyle change without jailbreak if (conversationId === 'new' || !jailbreak) { setShowBingToneSetting(false); } if (conversationId !== 'search') { inputRef.current?.focus(); } }, [conversationId, jailbreak]); useEffect(() => { const timeoutId = setTimeout(() => { inputRef.current?.focus(); }, 100); return () => clearTimeout(timeoutId); }, [isSubmitting]); const submitMessage = () => { ask({ text }); setText(''); }; const handleStopGenerating = (e) => { e.preventDefault(); stopGenerating(); }; const handleKeyDown = (e) => { if (e.key === 'Enter' && isSubmitting) { return; } if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); } if (e.key === 'Enter' && !e.shiftKey && !isComposing?.current) { submitMessage(); } }; const handleKeyUp = (e) => { if (e.keyCode === 8 && e.target.value.trim() === '') { setText(e.target.value); } if (e.key === 'Enter' && e.shiftKey) { return console.log('Enter + Shift'); } if (isSubmitting) { return; } }; const handleCompositionStart = () => { isComposing.current = true; }; const handleCompositionEnd = () => { isComposing.current = false; }; const changeHandler = (e) => { const { value } = e.target; setText(value); }; const getPlaceholderText = () => { if (isSearchView) { return 'Click a message title to open its conversation.'; } if (disabled) { return 'Choose another model or customize GPT again'; } if (isNotAppendable) { return 'Edit your message or Regenerate.'; } return ''; }; const handleBingToneSetting = () => { setShowBingToneSetting((show) => !show); }; if (isSearchView) { return <>; } return ( <>
{latestMessage && conversation?.jailbreak && conversation.endpoint === 'bingAI' ? ( ) : null}
); }