diff --git a/.gitignore b/.gitignore index fa70c3c4c..e20197487 100644 --- a/.gitignore +++ b/.gitignore @@ -47,7 +47,6 @@ bower_components/ .env cache.json api/data/ -.eslintrc.js owner.yml archive .vscode/settings.json diff --git a/client/src/App.jsx b/client/src/App.jsx index 9bab1f593..5f1446fd0 100644 --- a/client/src/App.jsx +++ b/client/src/App.jsx @@ -8,7 +8,7 @@ import useDocumentTitle from '~/hooks/useDocumentTitle'; import { useSelector } from 'react-redux'; const App = () => { - const { messages } = useSelector((state) => state.messages); + const { messages, messageTree } = useSelector((state) => state.messages); const { title } = useSelector((state) => state.convo); const { conversationId } = useSelector((state) => state.convo); const [ navVisible, setNavVisible ]= useState(false) @@ -25,6 +25,7 @@ const App = () => { ) : ( )} diff --git a/client/src/components/Main/TextChat.jsx b/client/src/components/Main/TextChat.jsx index 3671833ef..e0363cd8b 100644 --- a/client/src/components/Main/TextChat.jsx +++ b/client/src/components/Main/TextChat.jsx @@ -157,15 +157,17 @@ export default function TextChat({ messages }) { const message = text.trim(); const sender = model === 'chatgptCustom' ? chatGptLabel : model; let parentMessageId = convo.parentMessageId || '00000000-0000-0000-0000-000000000000'; - if (resetConvo(messages, sender)) { + let currentMessages = messages; + if (resetConvo(currentMessages, sender)) { parentMessageId = '00000000-0000-0000-0000-000000000000'; dispatch(setNewConvo()); + currentMessages = []; } const currentMsg = { sender: 'User', text: message, current: true, isCreatedByUser: true, parentMessageId , messageId: fakeMessageId }; const initialResponse = { sender, text: '', parentMessageId: fakeMessageId, submitting: true }; dispatch(setSubmitState(true)); - dispatch(setMessages([...messages, currentMsg, initialResponse])); + dispatch(setMessages([...currentMessages, currentMsg, initialResponse])); dispatch(setText('')); const submission = { @@ -177,7 +179,7 @@ export default function TextChat({ messages }) { chatGptLabel, promptPrefix, }, - messages, + messages: currentMessages, currentMsg, initialResponse, sender, diff --git a/client/src/components/Messages/Message.jsx b/client/src/components/Messages/Message.jsx index cfda8e524..af60fc1a9 100644 --- a/client/src/components/Messages/Message.jsx +++ b/client/src/components/Messages/Message.jsx @@ -1,5 +1,6 @@ import React, { useState, useEffect, useRef } from 'react'; import TextWrapper from './TextWrapper'; +import MultiMessage from './MultiMessage'; import { useSelector, useDispatch } from 'react-redux'; import HoverButtons from './HoverButtons'; import SiblingSwitch from './SiblingSwitch'; @@ -11,42 +12,6 @@ import { setText } from '~/store/textSlice'; import { setConversation } from '../../store/convoSlice'; import { getIconOfModel } from '../../utils'; -const MultiMessage = ({ - messageList, - messages, - scrollToBottom, - currentEditId, - setCurrentEditId -}) => { - const [siblingIdx, setSiblingIdx] = useState(0) - - const setSiblingIdxRev = (value) => { - setSiblingIdx(messageList?.length - value - 1) - } - - if (!messageList?.length) return null; - - if (siblingIdx >= messageList?.length) { - setSiblingIdx(0) - return null - } - - return -} - -export { MultiMessage }; - export default function Message({ message, messages, @@ -84,9 +49,9 @@ export default function Message({ dispatch(setConversation({parentMessageId: message?.messageId})) }, [last, ]) - if (sender === '') { - return ; - } + // if (sender === '') { + // return ; + // } const enterEdit = (cancel) => setCurrentEditId(cancel?-1:message.messageId) @@ -167,7 +132,7 @@ export default function Message({ >
-
+
{typeof icon === 'string' && icon.match(/[^\u0000-\u007F]+/) ? ( {icon} ) : ( diff --git a/client/src/components/Messages/MultiMessage.jsx b/client/src/components/Messages/MultiMessage.jsx new file mode 100644 index 000000000..24ab761eb --- /dev/null +++ b/client/src/components/Messages/MultiMessage.jsx @@ -0,0 +1,40 @@ +import React, { useState } from 'react'; +import Message from './Message'; + +export default function MultiMessage({ + messageList, + messages, + scrollToBottom, + currentEditId, + setCurrentEditId +}) { + const [siblingIdx, setSiblingIdx] = useState(0); + + const setSiblingIdxRev = (value) => { + setSiblingIdx(messageList?.length - value - 1); + }; + + // if (!messageList?.length) return null; + if (!(messageList && messageList.length)) { + return null; + } + + if (siblingIdx >= messageList?.length) { + setSiblingIdx(0); + return null; + } + + return ( + + ); +} diff --git a/client/src/components/Messages/index.jsx b/client/src/components/Messages/index.jsx index 85c671d69..eaf0a0cb6 100644 --- a/client/src/components/Messages/index.jsx +++ b/client/src/components/Messages/index.jsx @@ -1,12 +1,13 @@ import React, { useEffect, useState, useRef, useMemo } from 'react'; +import Spinner from '../svg/Spinner'; import { CSSTransition } from 'react-transition-group'; import ScrollToBottom from './ScrollToBottom'; -import { MultiMessage } from './Message'; -import Conversation from '../Conversations/Conversation'; +import MultiMessage from './MultiMessage'; +import buildTree from '~/utils/buildTree'; import { useSelector } from 'react-redux'; -const Messages = ({ messages }) => { - const [currentEditId, setCurrentEditId] = useState(-1) +const Messages = ({ messages, messageTree }) => { + const [currentEditId, setCurrentEditId] = useState(-1); const { conversationId } = useSelector((state) => state.convo); const [showScrollButton, setShowScrollButton] = useState(false); const scrollableRef = useRef(null); @@ -23,26 +24,6 @@ const Messages = ({ messages }) => { clearTimeout(timeoutId); }; }, [messages]); - - const messageTree = useMemo(() => buildTree(messages), [messages, ]); - - function buildTree(messages) { - let messageMap = {}; - let rootMessages = []; - - // Traverse the messages array and store each element in messageMap. - messages.forEach(message => { - messageMap[message.messageId] = {...message, children: []}; - - const parentMessage = messageMap[message.parentMessageId]; - if (parentMessage) - parentMessage.children.push(messageMap[message.messageId]); - else - rootMessages.push(messageMap[message.messageId]); - }); - - return rootMessages; - } const scrollToBottom = () => { messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' }); @@ -79,28 +60,33 @@ const Messages = ({ messages }) => { onScroll={debouncedHandleScroll} > {/*
*/} -
-
- - - {() => showScrollButton && } - - +
+
+ {messageTree.length === 0 ? ( + + ) : ( + <> + + + {() => showScrollButton && } + + + )}
diff --git a/client/src/store/messageSlice.js b/client/src/store/messageSlice.js index 137c32982..955d0c98f 100644 --- a/client/src/store/messageSlice.js +++ b/client/src/store/messageSlice.js @@ -1,7 +1,9 @@ import { createSlice } from '@reduxjs/toolkit'; +import buildTree from '~/utils/buildTree'; const initialState = { messages: [], + messageTree: [] }; const currentSlice = createSlice({ @@ -10,6 +12,7 @@ const currentSlice = createSlice({ reducers: { setMessages: (state, action) => { state.messages = action.payload; + state.messageTree = buildTree(action.payload); }, setEmptyMessage: (state) => { state.messages = [ diff --git a/client/src/utils/buildTree.js b/client/src/utils/buildTree.js new file mode 100644 index 000000000..a030509bc --- /dev/null +++ b/client/src/utils/buildTree.js @@ -0,0 +1,17 @@ +export default function buildTree(messages) { + let messageMap = {}; + let rootMessages = []; + + // Traverse the messages array and store each element in messageMap. + messages.forEach(message => { + messageMap[message.messageId] = {...message, children: []}; + + const parentMessage = messageMap[message.parentMessageId]; + if (parentMessage) + parentMessage.children.push(messageMap[message.messageId]); + else + rootMessages.push(messageMap[message.messageId]); + }); + + return rootMessages; +} \ No newline at end of file