From b07b74ba54fb2180cf27871fae55c3f1de6b1628 Mon Sep 17 00:00:00 2001 From: Daniel Avila Date: Sat, 25 Mar 2023 09:34:00 -0400 Subject: [PATCH] feat: complete bing styles (view) --- client/src/components/Main/BingStyles.jsx | 9 +- client/src/components/Main/TextChat.jsx | 169 ++++++++++-------- .../Messages/Content/TextWrapper.jsx | 4 +- client/src/style.css | 2 +- 4 files changed, 102 insertions(+), 82 deletions(-) diff --git a/client/src/components/Main/BingStyles.jsx b/client/src/components/Main/BingStyles.jsx index 512b8d0926..a54134e34d 100644 --- a/client/src/components/Main/BingStyles.jsx +++ b/client/src/components/Main/BingStyles.jsx @@ -1,16 +1,16 @@ -import React, { useState, useEffect } from 'react'; +import React, { useState, useEffect, forwardRef } from 'react'; import { Tabs, TabsList, TabsTrigger } from '../ui/Tabs.tsx'; import { useDispatch, useSelector } from 'react-redux'; import { setConversation } from '~/store/convoSlice'; -export default function BingStyles() { +function BingStyles(props, ref) { const dispatch = useDispatch(); const [value, setValue] = useState('fast'); const { model } = useSelector((state) => state.submit); const { conversationId } = useSelector((state) => state.convo); const { messages } = useSelector((state) => state.messages); + const isBing = model === 'bingai' || model === 'sydney'; - useEffect(() => { if (isBing && !conversationId) { dispatch(setConversation({ toneStyle: value })); @@ -32,6 +32,7 @@ export default function BingStyles() { defaultValue={value} className={`shadow-md mb-1 bing-styles ${show ? 'show' : ''}`} onValueChange={changeHandler} + ref={ref} > ); } + +export default forwardRef(BingStyles); diff --git a/client/src/components/Main/TextChat.jsx b/client/src/components/Main/TextChat.jsx index a955e627ef..c2c37796ac 100644 --- a/client/src/components/Main/TextChat.jsx +++ b/client/src/components/Main/TextChat.jsx @@ -10,11 +10,7 @@ import TextareaAutosize from 'react-textarea-autosize'; import createPayload from '~/utils/createPayload'; import RegenerateIcon from '../svg/RegenerateIcon'; import StopGeneratingIcon from '../svg/StopGeneratingIcon'; -import { - setConversation, - setError, - refreshConversation -} from '~/store/convoSlice'; +import { setConversation, setError, refreshConversation } from '~/store/convoSlice'; import { setMessages } from '~/store/messageSlice'; import { setSubmitState, toggleCursor } from '~/store/submitSlice'; import { setText } from '~/store/textSlice'; @@ -22,12 +18,12 @@ import { useMessageHandler } from '../../utils/handleSubmit'; export default function TextChat({ messages }) { const inputRef = useRef(null); + const bingStylesRef = useRef(null); const isComposing = useRef(false); const dispatch = useDispatch(); - const convo = useSelector((state) => state.convo); - const { isSubmitting, stopStream, submission, disabled } = - useSelector((state) => state.submit); - const { text } = useSelector((state) => state.text); + const convo = useSelector(state => state.convo); + const { isSubmitting, stopStream, submission, disabled } = useSelector(state => state.submit); + const { text } = useSelector(state => state.text); const { latestMessage } = convo; const { ask, regenerate, stopGenerating } = useMessageHandler(); @@ -38,6 +34,22 @@ export default function TextChat({ messages }) { inputRef.current?.focus(); }, [convo?.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 messageHandler = (data, currentState, currentMsg) => { const { messages, message, sender, isRegenerate } = currentState; @@ -114,8 +126,7 @@ export default function TextChat({ messages }) { const convoHandler = (data, currentState) => { const { requestMessage, responseMessage } = data; - const { messages, message, isCustomModel, isRegenerate } = - currentState; + const { messages, message, isCustomModel, isRegenerate } = currentState; const { model, chatGptLabel, promptPrefix } = message; if (isRegenerate) dispatch(setMessages([...messages, responseMessage])); else dispatch(setMessages([...messages, requestMessage, responseMessage])); @@ -194,7 +205,7 @@ export default function TextChat({ messages }) { }; const errorHandler = (data, currentState, currentMsg) => { - const {messages, message } = currentState; + const { messages, message } = currentState; console.log('Error:', data); const errorResponse = { ...data, @@ -223,7 +234,7 @@ export default function TextChat({ messages }) { let latestResponseText = ''; const { server, payload } = createPayload(submission); - const onMessage = (e) => { + const onMessage = e => { if (stopStream) { return; } @@ -298,7 +309,7 @@ export default function TextChat({ messages }) { stopGenerating(); }; - const handleKeyDown = (e) => { + const handleKeyDown = e => { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); } @@ -308,7 +319,11 @@ export default function TextChat({ messages }) { } }; - const handleKeyUp = (e) => { + const handleKeyUp = e => { + if (e.keyCode === 8 && e.target.value.trim() === '') { + dispatch(setText(e.target.value)); + } + if (e.key === 'Enter' && e.shiftKey) { return console.log('Enter + Shift'); } @@ -326,7 +341,7 @@ export default function TextChat({ messages }) { isComposing.current = false; }; - const changeHandler = (e) => { + const changeHandler = e => { const { value } = e.target; // if (isSubmitting && (value === '' || value === '\n')) { @@ -343,80 +358,80 @@ export default function TextChat({ messages }) { const isSearchView = messages?.[0]?.searchResult === true; const getPlaceholderText = () => { if (isSearchView) { - return 'Click a message title to open its conversation.' + 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 'Edit your message or Regenerate.'; } - + return ''; }; return ( <> -
-
-
- - - {isSubmitting && !isSearchView ? ( - - ) : latestMessage && !latestMessage?.isCreatedByUser && !isSearchView ? ( - - ) : null} - -
- - - +
+ +
+ + + {isSubmitting && !isSearchView ? ( + + ) : latestMessage && !latestMessage?.isCreatedByUser && !isSearchView ? ( + + ) : null} + +
+ + + +
-
- -
-
+ +
); } diff --git a/client/src/components/Messages/Content/TextWrapper.jsx b/client/src/components/Messages/Content/TextWrapper.jsx index 3cfd0a1b37..b8a242cf1e 100644 --- a/client/src/components/Messages/Content/TextWrapper.jsx +++ b/client/src/components/Messages/Content/TextWrapper.jsx @@ -46,7 +46,7 @@ const inLineWrap = (parts) => { }); }; -export default function TextWrapper({ text, generateCursor }) { +function TextWrapper({ text, generateCursor }) { let embedTest = false; let result = null; @@ -158,3 +158,5 @@ export default function TextWrapper({ text, generateCursor }) { ); } + +export default React.memo(TextWrapper); \ No newline at end of file diff --git a/client/src/style.css b/client/src/style.css index 04f2a899db..01d837a863 100644 --- a/client/src/style.css +++ b/client/src/style.css @@ -33,7 +33,7 @@ position: absolute; left: 0; right: 0; opacity: 0; -bottom: 35px; +bottom: 39px; z-index: 995; margin-left: auto; margin-right: auto;