mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-17 00:40:14 +01:00
feat: loading state for messages
This commit is contained in:
parent
afae13eec6
commit
79f050bac7
6 changed files with 43 additions and 8 deletions
|
|
@ -3,8 +3,8 @@ import RenameButton from './RenameButton';
|
||||||
import DeleteButton from './DeleteButton';
|
import DeleteButton from './DeleteButton';
|
||||||
import { useSelector, useDispatch } from 'react-redux';
|
import { useSelector, useDispatch } from 'react-redux';
|
||||||
import { setConversation } from '~/store/convoSlice';
|
import { setConversation } from '~/store/convoSlice';
|
||||||
import { setCustomGpt, setModel, setCustomModel } from '~/store/submitSlice';
|
import { setStopStream, setCustomGpt, setModel, setCustomModel } from '~/store/submitSlice';
|
||||||
import { setMessages } from '~/store/messageSlice';
|
import { setMessages, setEmptyMessage } from '~/store/messageSlice';
|
||||||
import { setText } from '~/store/textSlice';
|
import { setText } from '~/store/textSlice';
|
||||||
import manualSWR from '~/utils/fetchers';
|
import manualSWR from '~/utils/fetchers';
|
||||||
import ConvoIcon from '../svg/ConvoIcon';
|
import ConvoIcon from '../svg/ConvoIcon';
|
||||||
|
|
@ -23,7 +23,7 @@ export default function Conversation({
|
||||||
const { modelMap } = useSelector((state) => state.models);
|
const { modelMap } = useSelector((state) => state.models);
|
||||||
const inputRef = useRef(null);
|
const inputRef = useRef(null);
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const { trigger } = manualSWR(`/api/messages/${id}`, 'get');
|
const { trigger, isMutating } = manualSWR(`/api/messages/${id}`, 'get');
|
||||||
const rename = manualSWR(`/api/convos/update`, 'post');
|
const rename = manualSWR(`/api/convos/update`, 'post');
|
||||||
|
|
||||||
const clickHandler = async () => {
|
const clickHandler = async () => {
|
||||||
|
|
@ -31,6 +31,9 @@ export default function Conversation({
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dispatch(setStopStream(true));
|
||||||
|
dispatch(setEmptyMessage());
|
||||||
|
|
||||||
const convo = { title, error: false, conversationId: id, chatGptLabel, promptPrefix };
|
const convo = { title, error: false, conversationId: id, chatGptLabel, promptPrefix };
|
||||||
|
|
||||||
if (bingData) {
|
if (bingData) {
|
||||||
|
|
@ -64,6 +67,12 @@ export default function Conversation({
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
const data = await trigger();
|
const data = await trigger();
|
||||||
|
// while (isMutating) {
|
||||||
|
// await new Promise((resolve) => setTimeout(() => {
|
||||||
|
// dispatch(setMessages([]));
|
||||||
|
// resolve();
|
||||||
|
// }, 50));
|
||||||
|
// }
|
||||||
|
|
||||||
if (chatGptLabel) {
|
if (chatGptLabel) {
|
||||||
dispatch(setModel('chatgptCustom'));
|
dispatch(setModel('chatgptCustom'));
|
||||||
|
|
@ -81,6 +90,7 @@ export default function Conversation({
|
||||||
dispatch(setMessages(data));
|
dispatch(setMessages(data));
|
||||||
dispatch(setCustomGpt(convo));
|
dispatch(setCustomGpt(convo));
|
||||||
dispatch(setText(''));
|
dispatch(setText(''));
|
||||||
|
dispatch(setStopStream(false));
|
||||||
};
|
};
|
||||||
|
|
||||||
const renameHandler = (e) => {
|
const renameHandler = (e) => {
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ export default function TextChat({ messages }) {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const convo = useSelector((state) => state.convo);
|
const convo = useSelector((state) => state.convo);
|
||||||
const { initial } = useSelector((state) => state.models);
|
const { initial } = useSelector((state) => state.models);
|
||||||
const { isSubmitting, disabled, model, chatGptLabel, promptPrefix } = useSelector(
|
const { isSubmitting, stopStream, disabled, model, chatGptLabel, promptPrefix } = useSelector(
|
||||||
(state) => state.submit
|
(state) => state.submit
|
||||||
);
|
);
|
||||||
const { text } = useSelector((state) => state.text);
|
const { text } = useSelector((state) => state.text);
|
||||||
|
|
@ -38,7 +38,12 @@ export default function TextChat({ messages }) {
|
||||||
const initialResponse = { sender, text: '' };
|
const initialResponse = { sender, text: '' };
|
||||||
dispatch(setMessages([...messages, currentMsg, initialResponse]));
|
dispatch(setMessages([...messages, currentMsg, initialResponse]));
|
||||||
dispatch(setText(''));
|
dispatch(setText(''));
|
||||||
const messageHandler = (data) => {
|
const messageHandler = (data, events) => {
|
||||||
|
if (stopStream) {
|
||||||
|
console.log('Stopping stream');
|
||||||
|
events.close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
dispatch(setMessages([...messages, currentMsg, { sender, text: data }]));
|
dispatch(setMessages([...messages, currentMsg, { sender, text: data }]));
|
||||||
};
|
};
|
||||||
const convoHandler = (data) => {
|
const convoHandler = (data) => {
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import { useSelector } from 'react-redux';
|
||||||
import GPTIcon from '../svg/GPTIcon';
|
import GPTIcon from '../svg/GPTIcon';
|
||||||
import BingIcon from '../svg/BingIcon';
|
import BingIcon from '../svg/BingIcon';
|
||||||
import HoverButtons from './HoverButtons';
|
import HoverButtons from './HoverButtons';
|
||||||
|
import Spinner from '../svg/Spinner';
|
||||||
|
|
||||||
export default function Message({
|
export default function Message({
|
||||||
sender,
|
sender,
|
||||||
|
|
@ -22,6 +23,10 @@ export default function Message({
|
||||||
scrollToBottom();
|
scrollToBottom();
|
||||||
}
|
}
|
||||||
}, [isSubmitting, text, blinker, scrollToBottom, abortScroll]);
|
}, [isSubmitting, text, blinker, scrollToBottom, abortScroll]);
|
||||||
|
|
||||||
|
if (sender === '') {
|
||||||
|
return <Spinner />;
|
||||||
|
}
|
||||||
|
|
||||||
const handleWheel = () => {
|
const handleWheel = () => {
|
||||||
if (blinker) {
|
if (blinker) {
|
||||||
|
|
|
||||||
|
|
@ -11,9 +11,20 @@ const currentSlice = createSlice({
|
||||||
setMessages: (state, action) => {
|
setMessages: (state, action) => {
|
||||||
state.messages = action.payload;
|
state.messages = action.payload;
|
||||||
},
|
},
|
||||||
|
setEmptyMessage: (state) => {
|
||||||
|
state.messages = [
|
||||||
|
{
|
||||||
|
id: '1',
|
||||||
|
conversationId: '1',
|
||||||
|
parentMessageId: '1',
|
||||||
|
sender: '',
|
||||||
|
text: ''
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
export const { setMessages, setSubmitState } = currentSlice.actions;
|
export const { setMessages, setEmptyMessage } = currentSlice.actions;
|
||||||
|
|
||||||
export default currentSlice.reducer;
|
export default currentSlice.reducer;
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import { createSlice } from '@reduxjs/toolkit';
|
||||||
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
isSubmitting: false,
|
isSubmitting: false,
|
||||||
|
stopStream: false,
|
||||||
disabled: false,
|
disabled: false,
|
||||||
model: 'chatgpt',
|
model: 'chatgpt',
|
||||||
promptPrefix: '',
|
promptPrefix: '',
|
||||||
|
|
@ -16,6 +17,9 @@ const currentSlice = createSlice({
|
||||||
setSubmitState: (state, action) => {
|
setSubmitState: (state, action) => {
|
||||||
state.isSubmitting = action.payload;
|
state.isSubmitting = action.payload;
|
||||||
},
|
},
|
||||||
|
setStopStream: (state, action) => {
|
||||||
|
state.stopStream = action.payload;
|
||||||
|
},
|
||||||
setDisabled: (state, action) => {
|
setDisabled: (state, action) => {
|
||||||
state.disabled = action.payload;
|
state.disabled = action.payload;
|
||||||
},
|
},
|
||||||
|
|
@ -32,7 +36,7 @@ const currentSlice = createSlice({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
export const { setSubmitState, setDisabled, setModel, setCustomGpt, setCustomModel } =
|
export const { setSubmitState, setStopStream, setDisabled, setModel, setCustomGpt, setCustomModel } =
|
||||||
currentSlice.actions;
|
currentSlice.actions;
|
||||||
|
|
||||||
export default currentSlice.reducer;
|
export default currentSlice.reducer;
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ export default function handleSubmit({
|
||||||
const data = JSON.parse(e.data);
|
const data = JSON.parse(e.data);
|
||||||
let text = data.text || data.response;
|
let text = data.text || data.response;
|
||||||
if (data.message) {
|
if (data.message) {
|
||||||
messageHandler(text);
|
messageHandler(text, events);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.final) {
|
if (data.final) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue