mirror of https://github.com/buster-so/buster.git
Add a few stable selectors
This commit is contained in:
parent
0d20155b97
commit
6af0f6e011
|
@ -26,8 +26,6 @@ export const ChatMessageBlock: React.FC<{
|
|||
select: selectIsCompleted
|
||||
});
|
||||
|
||||
console.log('chat message block', messageId, messageIndex);
|
||||
|
||||
if (!messageExists) return null;
|
||||
|
||||
return (
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react';
|
||||
import type { BusterChatMessageResponse } from '@/api/asset_interfaces';
|
||||
import React, { useCallback } from 'react';
|
||||
import type { BusterChatMessage, BusterChatMessageResponse } from '@/api/asset_interfaces/chat';
|
||||
import { useGetChatMessage } from '@/api/buster_rest/chats';
|
||||
import { ChatResponseMessage_File } from './ChatResponseMessage_File';
|
||||
import { ChatResponseMessage_Text } from './ChatResponseMessage_Text';
|
||||
|
@ -26,23 +26,29 @@ export interface ChatResponseMessageSelectorProps {
|
|||
chatId: string;
|
||||
}
|
||||
|
||||
export const ChatResponseMessageSelector: React.FC<ChatResponseMessageSelectorProps> = React.memo(
|
||||
({ responseMessageId, messageId, chatId, isStreamFinished }) => {
|
||||
const { data: messageType } = useGetChatMessage(messageId, {
|
||||
select: (x) => x?.response_messages?.[responseMessageId]?.type || 'text'
|
||||
});
|
||||
const ChatResponseMessage =
|
||||
ChatResponseMessageRecord[messageType as BusterChatMessageResponse['type']];
|
||||
export const ChatResponseMessageSelector: React.FC<ChatResponseMessageSelectorProps> = ({
|
||||
responseMessageId,
|
||||
messageId,
|
||||
chatId,
|
||||
isStreamFinished
|
||||
}) => {
|
||||
const { data: messageType } = useGetChatMessage(messageId, {
|
||||
select: useCallback(
|
||||
(x: BusterChatMessage) => x?.response_messages?.[responseMessageId]?.type || 'text',
|
||||
[responseMessageId]
|
||||
)
|
||||
});
|
||||
const ChatResponseMessage =
|
||||
ChatResponseMessageRecord[messageType as BusterChatMessageResponse['type']];
|
||||
|
||||
return (
|
||||
<ChatResponseMessage
|
||||
isStreamFinished={isStreamFinished}
|
||||
responseMessageId={responseMessageId}
|
||||
messageId={messageId}
|
||||
chatId={chatId}
|
||||
/>
|
||||
);
|
||||
}
|
||||
);
|
||||
return (
|
||||
<ChatResponseMessage
|
||||
isStreamFinished={isStreamFinished}
|
||||
responseMessageId={responseMessageId}
|
||||
messageId={messageId}
|
||||
chatId={chatId}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
ChatResponseMessageSelector.displayName = 'ChatResponseMessageSelector';
|
||||
|
|
|
@ -4,6 +4,7 @@ import { ChatMessageOptions } from '../ChatMessageOptions';
|
|||
import { MessageContainer } from '../MessageContainer';
|
||||
import { ChatResponseMessageSelector } from './ChatResponseMessageSelector';
|
||||
import { ChatResponseReasoning } from './ChatResponseReasoning';
|
||||
import type { BusterChatMessage } from '@/api/asset_interfaces/chat';
|
||||
|
||||
interface ChatResponseMessagesProps {
|
||||
isStreamFinished: boolean;
|
||||
|
@ -12,16 +13,21 @@ interface ChatResponseMessagesProps {
|
|||
messageIndex: number;
|
||||
}
|
||||
|
||||
const stableResponseMessageIdsSelector = (x: BusterChatMessage) => x?.response_message_ids || [];
|
||||
const stableLastReasoningMessageIdSelector = (x: BusterChatMessage) =>
|
||||
x?.reasoning_message_ids?.[x.reasoning_message_ids.length - 1];
|
||||
const stableFinalReasoningMessageSelector = (x: BusterChatMessage) => x?.final_reasoning_message;
|
||||
|
||||
export const ChatResponseMessages: React.FC<ChatResponseMessagesProps> = React.memo(
|
||||
({ chatId, isStreamFinished, messageId, messageIndex }) => {
|
||||
const { data: responseMessageIds } = useGetChatMessage(messageId, {
|
||||
select: (x) => x?.response_message_ids || []
|
||||
select: stableResponseMessageIdsSelector
|
||||
});
|
||||
const { data: lastReasoningMessageId } = useGetChatMessage(messageId, {
|
||||
select: (x) => x?.reasoning_message_ids?.[x.reasoning_message_ids.length - 1]
|
||||
select: stableLastReasoningMessageIdSelector
|
||||
});
|
||||
const { data: finalReasoningMessage } = useGetChatMessage(messageId, {
|
||||
select: (x) => x?.final_reasoning_message
|
||||
select: stableFinalReasoningMessageSelector
|
||||
});
|
||||
const showReasoningMessage =
|
||||
messageIndex === 0 ? !!lastReasoningMessageId || !isStreamFinished : true;
|
||||
|
|
|
@ -11,6 +11,7 @@ import { ShimmerText } from '@/components/ui/typography/ShimmerText';
|
|||
import { BusterRoutes, createBusterRoute } from '@/routes';
|
||||
import { useChatLayoutContextSelector } from '../../../ChatLayoutContext';
|
||||
import { BLACK_BOX_INITIAL_THOUGHT } from '@/layouts/ChatLayout/ChatContext/useBlackBoxMessage';
|
||||
import type { BusterChatMessage } from '@/api/asset_interfaces/chat';
|
||||
|
||||
const animations = {
|
||||
initial: { opacity: 0 },
|
||||
|
@ -19,6 +20,9 @@ const animations = {
|
|||
transition: { delay: 0, duration: 0.35 }
|
||||
};
|
||||
|
||||
const stableLastMessageTitleSelector = (x: BusterChatMessage) =>
|
||||
x?.reasoning_messages?.[x.reasoning_message_ids?.[x.reasoning_message_ids.length - 1]]?.title;
|
||||
|
||||
export const ChatResponseReasoning: React.FC<{
|
||||
reasoningMessageId: string | undefined;
|
||||
finalReasoningMessage: string | undefined | null;
|
||||
|
@ -29,7 +33,7 @@ export const ChatResponseReasoning: React.FC<{
|
|||
({ finalReasoningMessage, reasoningMessageId, isStreamFinished, messageId, chatId }) => {
|
||||
const urlMessageId = useChatLayoutContextSelector((x) => x.messageId);
|
||||
const { data: lastMessageTitle } = useGetChatMessage(messageId, {
|
||||
select: (x) => x?.reasoning_messages?.[reasoningMessageId ?? '']?.title
|
||||
select: stableLastMessageTitleSelector
|
||||
});
|
||||
const selectedFileType = useChatLayoutContextSelector((x) => x.selectedFileType);
|
||||
const isReasonginFileSelected = selectedFileType === 'reasoning' && urlMessageId === messageId;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
'use client';
|
||||
|
||||
import React, { useRef, useState } from 'react';
|
||||
import React, { useCallback, useRef, useState } from 'react';
|
||||
import type { BusterChatMessageRequest } from '@/api/asset_interfaces';
|
||||
import { Button } from '@/components/ui/buttons';
|
||||
import { Copy, PenWriting } from '@/components/ui/icons';
|
||||
|
@ -25,22 +25,25 @@ export const ChatUserMessage: React.FC<{
|
|||
|
||||
const { sender_avatar, sender_id, sender_name, request } = requestMessage;
|
||||
|
||||
const onSetIsEditing = useMemoizedFn((isEditing: boolean) => {
|
||||
const onSetIsEditing = useCallback((isEditing: boolean) => {
|
||||
setIsEditing(isEditing);
|
||||
setIsTooltipOpen(false);
|
||||
});
|
||||
}, []);
|
||||
|
||||
const handleCopy = useMemoizedFn((e?: React.ClipboardEvent) => {
|
||||
// Prevent default copy behavior
|
||||
//I do not know why this is needed, but it is...
|
||||
if (e?.clipboardData) {
|
||||
e.preventDefault();
|
||||
e.clipboardData.setData('text/plain', request || '');
|
||||
} else {
|
||||
navigator.clipboard.writeText(request || '');
|
||||
}
|
||||
openSuccessMessage('Copied to clipboard');
|
||||
});
|
||||
const handleCopy = useCallback(
|
||||
(e?: React.ClipboardEvent) => {
|
||||
// Prevent default copy behavior
|
||||
//I do not know why this is needed, but it is...
|
||||
if (e?.clipboardData) {
|
||||
e.preventDefault();
|
||||
e.clipboardData.setData('text/plain', request || '');
|
||||
} else {
|
||||
navigator.clipboard.writeText(request || '');
|
||||
}
|
||||
openSuccessMessage('Copied to clipboard');
|
||||
},
|
||||
[openSuccessMessage, request]
|
||||
);
|
||||
|
||||
return (
|
||||
<MessageContainer
|
||||
|
@ -66,7 +69,6 @@ export const ChatUserMessage: React.FC<{
|
|||
{isStreamFinished && (
|
||||
<RequestMessageTooltip
|
||||
isTooltipOpen={isTooltipOpen}
|
||||
requestMessage={requestMessage}
|
||||
setIsEditing={setIsEditing}
|
||||
onCopy={handleCopy}
|
||||
/>
|
||||
|
@ -81,12 +83,9 @@ ChatUserMessage.displayName = 'ChatUserMessage';
|
|||
|
||||
const RequestMessageTooltip: React.FC<{
|
||||
isTooltipOpen: boolean;
|
||||
requestMessage: NonNullable<BusterChatMessageRequest>;
|
||||
setIsEditing: (isEditing: boolean) => void;
|
||||
onCopy: () => void;
|
||||
}> = React.memo(({ isTooltipOpen, requestMessage, setIsEditing, onCopy }) => {
|
||||
const { openSuccessMessage } = useBusterNotifications();
|
||||
|
||||
}> = React.memo(({ isTooltipOpen, setIsEditing, onCopy }) => {
|
||||
const onEdit = useMemoizedFn(() => {
|
||||
setIsEditing(true);
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue