diff --git a/client/src/components/Messages/Message.jsx b/client/src/components/Messages/Message.jsx index af60fc1a9a..622b907454 100644 --- a/client/src/components/Messages/Message.jsx +++ b/client/src/components/Messages/Message.jsx @@ -1,10 +1,9 @@ -import React, { useState, useEffect, useRef } from 'react'; +import React, { useState, useEffect, useRef, useCallback } from 'react'; import TextWrapper from './TextWrapper'; import MultiMessage from './MultiMessage'; import { useSelector, useDispatch } from 'react-redux'; import HoverButtons from './HoverButtons'; import SiblingSwitch from './SiblingSwitch'; -import Spinner from '../svg/Spinner'; import { setError } from '~/store/convoSlice'; import { setMessages } from '~/store/messageSlice'; import { setSubmitState, setSubmission } from '~/store/submitSlice'; @@ -22,21 +21,28 @@ export default function Message({ siblingCount, setSiblingIdx }) { - const { isSubmitting, model, chatGptLabel, promptPrefix } = useSelector((state) => state.submit); + const { isSubmitting, model, chatGptLabel, promptPrefix } = useSelector( + (state) => state.submit + ); const [abortScroll, setAbort] = useState(false); - const { sender, text, isCreatedByUser, error, submitting } = message - const textEditor = useRef(null) + const { sender, text, isCreatedByUser, error, submitting } = message; + const textEditor = useRef(null); const convo = useSelector((state) => state.convo); const { initial } = useSelector((state) => state.models); const { error: convoError } = convo; - const last = !message?.children?.length - + const last = !message?.children?.length; const edit = message.messageId == currentEditId; - const dispatch = useDispatch(); // const notUser = !isCreatedByUser; // sender.toLowerCase() !== 'user'; const blinker = submitting && isSubmitting && last && !isCreatedByUser; + const generateCursor = useCallback(() => { + if (!blinker) { + return ''; + } + + return ; + }, [blinker]); useEffect(() => { if (blinker && !abortScroll) { @@ -45,15 +51,10 @@ export default function Message({ }, [isSubmitting, text, blinker, scrollToBottom, abortScroll]); useEffect(() => { - if (last) - dispatch(setConversation({parentMessageId: message?.messageId})) - }, [last, ]) + if (last) dispatch(setConversation({ parentMessageId: message?.messageId })); + }, [last]); - // if (sender === '') { - // return ; - // } - - const enterEdit = (cancel) => setCurrentEditId(cancel?-1:message.messageId) + const enterEdit = (cancel) => setCurrentEditId(cancel ? -1 : message.messageId); const handleWheel = () => { if (blinker) { @@ -67,17 +68,24 @@ export default function Message({ className: 'w-full border-b border-black/10 dark:border-gray-900/50 text-gray-800 bg-white dark:text-gray-100 group dark:bg-gray-800' }; - - const icon = getIconOfModel({ sender, isCreatedByUser, model, chatGptLabel, promptPrefix, error }); - + + const icon = getIconOfModel({ + sender, + isCreatedByUser, + model, + chatGptLabel, + promptPrefix, + error + }); + if (!isCreatedByUser) props.className = 'w-full border-b border-black/10 bg-gray-50 dark:border-gray-900/50 text-gray-800 dark:text-gray-100 group bg-gray-100 dark:bg-[#444654]'; - const wrapText = (text) => ; + // const wrapText = (text) => ; const resubmitMessage = () => { - const text = textEditor.current.innerText + const text = textEditor.current.innerText; if (convoError) { dispatch(setError(false)); @@ -90,14 +98,23 @@ export default function Message({ // this is not a real messageId, it is used as placeholder before real messageId returned const fakeMessageId = crypto.randomUUID(); const isCustomModel = model === 'chatgptCustom' || !initial[model]; - const currentMsg = { - sender: 'User', text: text.trim(), current: true, isCreatedByUser: true, - parentMessageId: message?.parentMessageId, - conversationId: message?.conversationId, - messageId: fakeMessageId }; + const currentMsg = { + sender: 'User', + text: text.trim(), + current: true, + isCreatedByUser: true, + parentMessageId: message?.parentMessageId, + conversationId: message?.conversationId, + messageId: fakeMessageId + }; const sender = model === 'chatgptCustom' ? chatGptLabel : model; - const initialResponse = { sender, text: '', parentMessageId: fakeMessageId, submitting: true }; + const initialResponse = { + sender, + text: '', + parentMessageId: fakeMessageId, + submitting: true + }; dispatch(setSubmitState(true)); dispatch(setMessages([...messages, currentMsg, initialResponse])); @@ -105,22 +122,22 @@ export default function Message({ const submission = { isCustomModel, - message: { - ...currentMsg, + message: { + ...currentMsg, model, chatGptLabel, - promptPrefix, + promptPrefix }, messages: messages, currentMsg, initialResponse, - sender, + sender }; console.log('User Input:', currentMsg?.text); // handleSubmit(submission); dispatch(setSubmission(submission)); - setSiblingIdx(siblingCount - 1) + setSiblingIdx(siblingCount - 1); enterEdit(true); }; @@ -131,68 +148,84 @@ export default function Message({ onWheel={handleWheel} >
-
{typeof icon === 'string' && icon.match(/[^\u0000-\u007F]+/) ? ( {icon} ) : ( icon )} - +
{error ? ( -
+
{`An error occurred. Please try again in a few moments.\n\nError message: ${text}`}
- ) : - edit ? ( -
- {/*
*/} - -
- {text} -
-
- - -
+ ) : edit ? ( +
+ {/*
*/} + +
+ {text}
- ) : ( -
- {/*
*/} -
- {!isCreatedByUser ? wrapText(text) : text} - {blinker && } -
+
+ +
- )} +
+ ) : ( +
+ {/*
*/} +
+ {!isCreatedByUser ? ( + + ) : ( + text + )} +
+
+ )}
- enterEdit()}/> + enterEdit()} + />
); diff --git a/client/src/components/Messages/TextWrapper.jsx b/client/src/components/Messages/TextWrapper.jsx index 5719ee876b..75766bca0c 100644 --- a/client/src/components/Messages/TextWrapper.jsx +++ b/client/src/components/Messages/TextWrapper.jsx @@ -46,8 +46,9 @@ const inLineWrap = (parts) => { }); }; -export default function TextWrapper({ text }) { +export default function TextWrapper({ text, generateCursor }) { let embedTest = false; + let result = null; // to match unenclosed code blocks if (text.match(/```/g)?.length === 1) { @@ -137,13 +138,23 @@ export default function TextWrapper({ text }) { } }); - return <>{codeParts}; // return the wrapped text + // return <>{codeParts}; // return the wrapped text + result = <>{codeParts}; } else if (text.match(markupRegex)) { // map over the parts and wrap any text between tildes with tags const parts = text.split(markupRegex); const codeParts = inLineWrap(parts); - return {codeParts}; // return the wrapped text + // return <>{codeParts}; // return the wrapped text + result = <>{codeParts}; } else { - return {text}; + // return {text}; + result = {text}; } + + return ( + <> + {result} + {(<>{generateCursor()})} + + ); } diff --git a/client/src/style.css b/client/src/style.css index c4a03408b7..30fae19b40 100644 --- a/client/src/style.css +++ b/client/src/style.css @@ -1251,7 +1251,6 @@ html { vertical-align: baseline; } - /* .result-streaming>:not(ol):not(ul):not(pre):last-child:after, .result-streaming>ol:last-child li:last-child:after, .result-streaming>pre:last-child code:after,