diff --git a/src/views/ChatPanel/MessageContainer.tsx b/src/views/ChatPanel/MessageContainer.tsx index 05ad409..c7d6bba 100644 --- a/src/views/ChatPanel/MessageContainer.tsx +++ b/src/views/ChatPanel/MessageContainer.tsx @@ -12,7 +12,8 @@ import { IconCheck, IconCopy } from "@tabler/icons-react"; import { useSelector } from 'react-redux'; import { selectGenerating, - selectResponsed + selectResponsed, + selectMessages, } from './chatSlice'; @@ -162,9 +163,9 @@ const MessageHeader = (props: any) => { }; const MessageContainer = (props: any) => { - const { messages, width, onRefillClick } = props; + const { width, onRefillClick } = props; - const generating = useSelector(selectGenerating); + const messages = useSelector(selectMessages); const messageList = messages.map((item: any, index: number) => { const { message: messageText, type: messageType, contexts } = item; @@ -193,7 +194,7 @@ const MessageContainer = (props: any) => { }}> - + {index !== messages.length - 1 && } diff --git a/src/views/ChatPanel/chatSlice.ts b/src/views/ChatPanel/chatSlice.ts index 53ca927..9b36521 100644 --- a/src/views/ChatPanel/chatSlice.ts +++ b/src/views/ChatPanel/chatSlice.ts @@ -7,6 +7,7 @@ export const chatSlice = createSlice({ responsed: false, currentMessage: '', errorMessage: '', + messages: [], }, reducers: { startGenerating: (state) => { @@ -23,6 +24,21 @@ export const chatSlice = createSlice({ state.responsed = true; state.currentMessage = action.payload; }, + newMessage: (state, action) => { + state.messages.push(action.payload); + }, + updateMessage: (state, action) => { + state.messages[action.payload.index] = action.payload.newMessage; + }, + shiftMessage: (state) => { + state.messages.splice(0, 1); + }, + popMessage: (state) => { + state.messages.pop(); + }, + clearMessages: (state) => { + state.messages.length = 0; + }, happendError: (state, action) => { state.errorMessage = action.payload; } @@ -33,12 +49,18 @@ export const selectGenerating = state => state.chat.generating; export const selectResponsed = state => state.chat.responsed; export const selectCurrentMessage = state => state.chat.currentMessage; export const selectErrorMessage = state => state.chat.errorMessage; +export const selectMessages = state => state.chat.messages; export const { startGenerating, stopGenerating, startResponsing, happendError, + newMessage, + shiftMessage, + popMessage, + clearMessages, + updateMessage, } = chatSlice.actions; export default chatSlice.reducer; \ No newline at end of file diff --git a/src/views/ChatPanel/index.tsx b/src/views/ChatPanel/index.tsx index 409d929..848fd9a 100644 --- a/src/views/ChatPanel/index.tsx +++ b/src/views/ChatPanel/index.tsx @@ -16,10 +16,15 @@ import { stopGenerating, startResponsing, happendError, + newMessage, + updateMessage, + shiftMessage, + popMessage, selectGenerating, selectResponsed, selectCurrentMessage, selectErrorMessage, + selectMessages, } from './chatSlice'; import InputMessage from './InputMessage'; @@ -78,9 +83,9 @@ const chatPanel = () => { const currentMessage = useSelector(selectCurrentMessage); const errorMessage = useSelector(selectErrorMessage); const responsed = useSelector(selectResponsed); + const messages = useSelector(selectMessages); const [chatContainerRef, chatContainerRect] = useResizeObserver(); const scrollViewport = useRef(null); - const [messages, messageHandlers] = useListState<{ type: string; message: string; contexts?: any[] }>([]); const { height, width } = useViewportSize(); const [scrollPosition, onScrollPositionChange] = useState({ x: 0, y: 0 }); const [stopScrolling, setStopScrolling] = useState(false); @@ -114,8 +119,8 @@ const chatPanel = () => { message.entries?.forEach(({ hash, user, date, request, response, context }, index) => { if (index < message.entries.length - messageCount) return; const contexts = context.map(({ content, role }) => ({ context: JSON.parse(content) })); - messageHandlers.append({ type: 'user', message: request, contexts: contexts }); - messageHandlers.append({ type: 'bot', message: response }); + dispatch(newMessage({ type: 'user', message: request, contexts: contexts })); + dispatch(newMessage({ type: 'bot', message: response })); }); }); timer.start(); @@ -138,7 +143,7 @@ const chatPanel = () => { useEffect(() => { if (generating) { // new a bot message - messageHandlers.append({ type: 'bot', message: currentMessage }); + dispatch(newMessage({ type: 'bot', message: currentMessage })); } }, [generating]); @@ -148,14 +153,18 @@ const chatPanel = () => { const lastMessage = messages[lastIndex]; if (currentMessage && lastMessage?.type === 'bot') { // update the last one bot message - messageHandlers.setItem(lastIndex, { type: 'bot', message: currentMessage }); + // messageHandlers.setItem(); + dispatch(updateMessage({ + index: lastIndex, + newMessage: { type: 'bot', message: currentMessage } + })); } timer.start(); }, [currentMessage]); useEffect(() => { if (messages.length > messageCount * 2) { - messageHandlers.remove(0, 1); + dispatch(shiftMessage()); } timer.start(); }, [messages]); @@ -190,10 +199,7 @@ const chatPanel = () => { contexts.length = 0; contextsHandlers.append(...messageContexts); }} - width={chatContainerRect.width} - generating={generating} - messages={messages} - responsed={responsed} /> + width={chatContainerRect.width} /> {errorMessage && {errorMessage} @@ -221,7 +227,7 @@ const chatPanel = () => { messageUtil.sendMessage({ command: 'regeneration' }); - messageHandlers.pop(); + dispatch(popMessage()); dispatch(startGenerating()); }} /> @@ -233,7 +239,7 @@ const chatPanel = () => { width={chatContainerRect.width} onSendClick={(input: string, contexts: any) => { // Add the user's message to the chat UI - messageHandlers.append({ type: 'user', message: input, contexts: contexts ? [...contexts].map((item) => ({ ...item })) : undefined }); + dispatch(newMessage({ type: 'user', message: input, contexts: contexts ? [...contexts].map((item) => ({ ...item })) : undefined })); // start generating dispatch(startGenerating()); }} />