import React, { useEffect, useRef, useState } from 'react'; import { useRecoilValue, useRecoilState } from 'recoil'; import SubmitButton from './SubmitButton'; import AdjustToneButton from './AdjustToneButton'; import BingStyles from './BingStyles'; import ModelMenu from './Models/ModelMenu'; import Footer from './Footer'; import TextareaAutosize from 'react-textarea-autosize'; import createPayload from '~/utils/createPayload'; import RegenerateIcon from '../svg/RegenerateIcon'; import StopGeneratingIcon from '../svg/StopGeneratingIcon'; import { useMessageHandler } from '../../utils/handleSubmit'; import store from '~/store'; export default function TextChat() { const inputRef = useRef(null); const isComposing = useRef(false); const conversation = useRecoilValue(store.conversation); const latestMessage = useRecoilValue(store.latestMessage); const messages = useRecoilValue(store.messages); const isSubmitting = useRecoilValue(store.isSubmitting); // TODO: do we need this? const disabled = false; const [text, setText] = useState(''); const { ask, regenerate, stopGenerating } = useMessageHandler(); const bingStylesRef = useRef(null); const [showBingToneSetting, setShowBingToneSetting] = useState(false); const isNotAppendable = latestMessage?.cancelled || latestMessage?.error; // auto focus to input, when enter a conversation. useEffect(() => { inputRef.current?.focus(); setText(''); }, [conversation?.conversationId]); // controls the height of Bing tone style tabs useEffect(() => { if (!inputRef.current) { return; // wait for the ref to be available } const resizeObserver = new ResizeObserver(() => { const newHeight = inputRef.current.clientHeight; if (newHeight >= 24) { // 24 is the default height of the input bingStylesRef.current.style.bottom = 15 + newHeight + 'px'; } }); resizeObserver.observe(inputRef.current); return () => resizeObserver.disconnect(); }, [inputRef]); const submitMessage = () => { ask({ text }); setText(''); }; const handleRegenerate = () => { if (latestMessage && !latestMessage?.isCreatedByUser) regenerate(latestMessage); }; const handleStopGenerating = () => { stopGenerating(); }; const handleKeyDown = e => { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); } if (e.key === 'Enter' && !e.shiftKey) { if (!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 isSearchView = messages?.[0]?.searchResult === true; 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 ( <>
{isSubmitting ? ( ) : latestMessage && !latestMessage?.isCreatedByUser ? ( ) : null}
{messages?.length && conversation?.model === 'sydney' ? ( ) : null}
); }