Refactor ChatPanel to use Redux for message handling
- Replace messageHandlers with Redux actions and selectors. - Add newMessage, updateMessage, shiftMessage, and popMessage actions to chatSlice. - Update MessageContainer to use useSelector for messages.
This commit is contained in:
parent
6a0744515b
commit
1771e87028
@ -12,7 +12,8 @@ import { IconCheck, IconCopy } from "@tabler/icons-react";
|
|||||||
import { useSelector } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
import {
|
import {
|
||||||
selectGenerating,
|
selectGenerating,
|
||||||
selectResponsed
|
selectResponsed,
|
||||||
|
selectMessages,
|
||||||
} from './chatSlice';
|
} from './chatSlice';
|
||||||
|
|
||||||
|
|
||||||
@ -162,9 +163,9 @@ const MessageHeader = (props: any) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const MessageContainer = (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 messageList = messages.map((item: any, index: number) => {
|
||||||
const { message: messageText, type: messageType, contexts } = item;
|
const { message: messageText, type: messageType, contexts } = item;
|
||||||
@ -193,7 +194,7 @@ const MessageContainer = (props: any) => {
|
|||||||
}}>
|
}}>
|
||||||
<MessageContext contexts={contexts} />
|
<MessageContext contexts={contexts} />
|
||||||
<CodeBlock messageText={messageText} />
|
<CodeBlock messageText={messageText} />
|
||||||
<MessageBlink generating={generating} messageType={messageType} lastMessage={index === messages.length - 1} />
|
<MessageBlink messageType={messageType} lastMessage={index === messages.length - 1} />
|
||||||
</Container >
|
</Container >
|
||||||
</Stack >
|
</Stack >
|
||||||
{index !== messages.length - 1 && <Divider my={3} />}
|
{index !== messages.length - 1 && <Divider my={3} />}
|
||||||
|
@ -7,6 +7,7 @@ export const chatSlice = createSlice({
|
|||||||
responsed: false,
|
responsed: false,
|
||||||
currentMessage: '',
|
currentMessage: '',
|
||||||
errorMessage: '',
|
errorMessage: '',
|
||||||
|
messages: <any>[],
|
||||||
},
|
},
|
||||||
reducers: {
|
reducers: {
|
||||||
startGenerating: (state) => {
|
startGenerating: (state) => {
|
||||||
@ -23,6 +24,21 @@ export const chatSlice = createSlice({
|
|||||||
state.responsed = true;
|
state.responsed = true;
|
||||||
state.currentMessage = action.payload;
|
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) => {
|
happendError: (state, action) => {
|
||||||
state.errorMessage = action.payload;
|
state.errorMessage = action.payload;
|
||||||
}
|
}
|
||||||
@ -33,12 +49,18 @@ export const selectGenerating = state => state.chat.generating;
|
|||||||
export const selectResponsed = state => state.chat.responsed;
|
export const selectResponsed = state => state.chat.responsed;
|
||||||
export const selectCurrentMessage = state => state.chat.currentMessage;
|
export const selectCurrentMessage = state => state.chat.currentMessage;
|
||||||
export const selectErrorMessage = state => state.chat.errorMessage;
|
export const selectErrorMessage = state => state.chat.errorMessage;
|
||||||
|
export const selectMessages = state => state.chat.messages;
|
||||||
|
|
||||||
export const {
|
export const {
|
||||||
startGenerating,
|
startGenerating,
|
||||||
stopGenerating,
|
stopGenerating,
|
||||||
startResponsing,
|
startResponsing,
|
||||||
happendError,
|
happendError,
|
||||||
|
newMessage,
|
||||||
|
shiftMessage,
|
||||||
|
popMessage,
|
||||||
|
clearMessages,
|
||||||
|
updateMessage,
|
||||||
} = chatSlice.actions;
|
} = chatSlice.actions;
|
||||||
|
|
||||||
export default chatSlice.reducer;
|
export default chatSlice.reducer;
|
@ -16,10 +16,15 @@ import {
|
|||||||
stopGenerating,
|
stopGenerating,
|
||||||
startResponsing,
|
startResponsing,
|
||||||
happendError,
|
happendError,
|
||||||
|
newMessage,
|
||||||
|
updateMessage,
|
||||||
|
shiftMessage,
|
||||||
|
popMessage,
|
||||||
selectGenerating,
|
selectGenerating,
|
||||||
selectResponsed,
|
selectResponsed,
|
||||||
selectCurrentMessage,
|
selectCurrentMessage,
|
||||||
selectErrorMessage,
|
selectErrorMessage,
|
||||||
|
selectMessages,
|
||||||
} from './chatSlice';
|
} from './chatSlice';
|
||||||
|
|
||||||
import InputMessage from './InputMessage';
|
import InputMessage from './InputMessage';
|
||||||
@ -78,9 +83,9 @@ const chatPanel = () => {
|
|||||||
const currentMessage = useSelector(selectCurrentMessage);
|
const currentMessage = useSelector(selectCurrentMessage);
|
||||||
const errorMessage = useSelector(selectErrorMessage);
|
const errorMessage = useSelector(selectErrorMessage);
|
||||||
const responsed = useSelector(selectResponsed);
|
const responsed = useSelector(selectResponsed);
|
||||||
|
const messages = useSelector(selectMessages);
|
||||||
const [chatContainerRef, chatContainerRect] = useResizeObserver();
|
const [chatContainerRef, chatContainerRect] = useResizeObserver();
|
||||||
const scrollViewport = useRef<HTMLDivElement>(null);
|
const scrollViewport = useRef<HTMLDivElement>(null);
|
||||||
const [messages, messageHandlers] = useListState<{ type: string; message: string; contexts?: any[] }>([]);
|
|
||||||
const { height, width } = useViewportSize();
|
const { height, width } = useViewportSize();
|
||||||
const [scrollPosition, onScrollPositionChange] = useState({ x: 0, y: 0 });
|
const [scrollPosition, onScrollPositionChange] = useState({ x: 0, y: 0 });
|
||||||
const [stopScrolling, setStopScrolling] = useState(false);
|
const [stopScrolling, setStopScrolling] = useState(false);
|
||||||
@ -114,8 +119,8 @@ const chatPanel = () => {
|
|||||||
message.entries?.forEach(({ hash, user, date, request, response, context }, index) => {
|
message.entries?.forEach(({ hash, user, date, request, response, context }, index) => {
|
||||||
if (index < message.entries.length - messageCount) return;
|
if (index < message.entries.length - messageCount) return;
|
||||||
const contexts = context.map(({ content, role }) => ({ context: JSON.parse(content) }));
|
const contexts = context.map(({ content, role }) => ({ context: JSON.parse(content) }));
|
||||||
messageHandlers.append({ type: 'user', message: request, contexts: contexts });
|
dispatch(newMessage({ type: 'user', message: request, contexts: contexts }));
|
||||||
messageHandlers.append({ type: 'bot', message: response });
|
dispatch(newMessage({ type: 'bot', message: response }));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
timer.start();
|
timer.start();
|
||||||
@ -138,7 +143,7 @@ const chatPanel = () => {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (generating) {
|
if (generating) {
|
||||||
// new a bot message
|
// new a bot message
|
||||||
messageHandlers.append({ type: 'bot', message: currentMessage });
|
dispatch(newMessage({ type: 'bot', message: currentMessage }));
|
||||||
}
|
}
|
||||||
}, [generating]);
|
}, [generating]);
|
||||||
|
|
||||||
@ -148,14 +153,18 @@ const chatPanel = () => {
|
|||||||
const lastMessage = messages[lastIndex];
|
const lastMessage = messages[lastIndex];
|
||||||
if (currentMessage && lastMessage?.type === 'bot') {
|
if (currentMessage && lastMessage?.type === 'bot') {
|
||||||
// update the last one bot message
|
// 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();
|
timer.start();
|
||||||
}, [currentMessage]);
|
}, [currentMessage]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (messages.length > messageCount * 2) {
|
if (messages.length > messageCount * 2) {
|
||||||
messageHandlers.remove(0, 1);
|
dispatch(shiftMessage());
|
||||||
}
|
}
|
||||||
timer.start();
|
timer.start();
|
||||||
}, [messages]);
|
}, [messages]);
|
||||||
@ -190,10 +199,7 @@ const chatPanel = () => {
|
|||||||
contexts.length = 0;
|
contexts.length = 0;
|
||||||
contextsHandlers.append(...messageContexts);
|
contextsHandlers.append(...messageContexts);
|
||||||
}}
|
}}
|
||||||
width={chatContainerRect.width}
|
width={chatContainerRect.width} />
|
||||||
generating={generating}
|
|
||||||
messages={messages}
|
|
||||||
responsed={responsed} />
|
|
||||||
{errorMessage &&
|
{errorMessage &&
|
||||||
<Alert styles={{ message: { fontSize: 'var(--vscode-editor-font-size)' } }} w={chatContainerRect.width} mb={20} color="gray" variant="filled">
|
<Alert styles={{ message: { fontSize: 'var(--vscode-editor-font-size)' } }} w={chatContainerRect.width} mb={20} color="gray" variant="filled">
|
||||||
{errorMessage}
|
{errorMessage}
|
||||||
@ -221,7 +227,7 @@ const chatPanel = () => {
|
|||||||
messageUtil.sendMessage({
|
messageUtil.sendMessage({
|
||||||
command: 'regeneration'
|
command: 'regeneration'
|
||||||
});
|
});
|
||||||
messageHandlers.pop();
|
dispatch(popMessage());
|
||||||
dispatch(startGenerating());
|
dispatch(startGenerating());
|
||||||
}} />
|
}} />
|
||||||
</Center>
|
</Center>
|
||||||
@ -233,7 +239,7 @@ const chatPanel = () => {
|
|||||||
width={chatContainerRect.width}
|
width={chatContainerRect.width}
|
||||||
onSendClick={(input: string, contexts: any) => {
|
onSendClick={(input: string, contexts: any) => {
|
||||||
// Add the user's message to the chat UI
|
// 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
|
// start generating
|
||||||
dispatch(startGenerating());
|
dispatch(startGenerating());
|
||||||
}} />
|
}} />
|
||||||
|
Loading…
x
Reference in New Issue
Block a user