mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-17 08:50:15 +01:00
🖱️ fix: Message Scrolling UX; refactor: Frontend UX/DX Optimizations (#3733)
* refactor(DropdownPopup): set MenuButton `as` prop to `div` to prevent React warning: validateDOMNesting(...): <button> cannot appear as a descendant of <button> * refactor: memoize ChatGroupItem and ControlCombobox components * refactor(OpenAIClient): await stream process finish before finalCompletion event handling * refactor: update useSSE.ts typing to handle null and undefined values in data properties * refactor: set abort scroll to false on SSE connection open * refactor: improve logger functionality with filter support * refactor: update handleScroll typing in MessageContainer component * refactor: update logger.dir call in useChatFunctions to log 'message_stream' tag format instead of the entire submission object as first arg * refactor: fix null check for message object in Message component * refactor: throttle handleScroll to help prevent auto-scrolling issues on new message requests; fix type issues within useMessageProcess * refactor: add abortScrollByIndex logging effect * refactor: update MessageIcon and Icon components to use React.memo for performance optimization * refactor: memoize ConvoIconURL component for performance optimization * chore: type issues * chore: update package version to 0.7.414
This commit is contained in:
parent
ba9c351435
commit
98b437edd5
20 changed files with 282 additions and 176 deletions
|
|
@ -9,7 +9,7 @@ import {
|
|||
isAssistantsEndpoint,
|
||||
} from 'librechat-data-provider';
|
||||
import { useGetUserBalance, useGetStartupConfig } from 'librechat-data-provider/react-query';
|
||||
import type { TSubmission } from 'librechat-data-provider';
|
||||
import type { TMessage, TSubmission, EventSubmission } from 'librechat-data-provider';
|
||||
import type { EventHandlerParams } from './useEventHandlers';
|
||||
import type { TResData } from '~/common';
|
||||
import { useGenTitleMutation } from '~/data-provider';
|
||||
|
|
@ -38,6 +38,7 @@ export default function useSSE(
|
|||
|
||||
const { token, isAuthenticated } = useAuthContext();
|
||||
const [completed, setCompleted] = useState(new Set());
|
||||
const setAbortScroll = useSetRecoilState(store.abortScrollFamily(runIndex));
|
||||
const setShowStopButton = useSetRecoilState(store.showStopButtonByIndex(runIndex));
|
||||
|
||||
const {
|
||||
|
|
@ -98,54 +99,57 @@ export default function useSSE(
|
|||
events.onmessage = (e: MessageEvent) => {
|
||||
const data = JSON.parse(e.data);
|
||||
|
||||
if (data.final) {
|
||||
if (data.final != null) {
|
||||
const { plugins } = data;
|
||||
finalHandler(data, { ...submission, plugins });
|
||||
startupConfig?.checkBalance && balanceQuery.refetch();
|
||||
finalHandler(data, { ...submission, plugins } as EventSubmission);
|
||||
(startupConfig?.checkBalance ?? false) && balanceQuery.refetch();
|
||||
console.log('final', data);
|
||||
}
|
||||
if (data.created) {
|
||||
if (data.created != null) {
|
||||
const runId = v4();
|
||||
setActiveRunId(runId);
|
||||
userMessage = {
|
||||
...userMessage,
|
||||
...data.message,
|
||||
overrideParentMessageId: userMessage?.overrideParentMessageId,
|
||||
overrideParentMessageId: userMessage.overrideParentMessageId,
|
||||
};
|
||||
|
||||
createdHandler(data, { ...submission, userMessage });
|
||||
} else if (data.sync) {
|
||||
createdHandler(data, { ...submission, userMessage } as EventSubmission);
|
||||
} else if (data.sync != null) {
|
||||
const runId = v4();
|
||||
setActiveRunId(runId);
|
||||
/* synchronize messages to Assistants API as well as with real DB ID's */
|
||||
syncHandler(data, { ...submission, userMessage });
|
||||
} else if (data.type) {
|
||||
syncHandler(data, { ...submission, userMessage } as EventSubmission);
|
||||
} else if (data.type != null) {
|
||||
const { text, index } = data;
|
||||
if (text && index !== textIndex) {
|
||||
if (text != null && index !== textIndex) {
|
||||
textIndex = index;
|
||||
}
|
||||
|
||||
contentHandler({ data, submission });
|
||||
contentHandler({ data, submission: submission as EventSubmission });
|
||||
} else {
|
||||
const text = data.text || data.response;
|
||||
const text = data.text ?? data.response;
|
||||
const { plugin, plugins } = data;
|
||||
|
||||
const initialResponse = {
|
||||
...submission.initialResponse,
|
||||
...(submission.initialResponse as TMessage),
|
||||
parentMessageId: data.parentMessageId,
|
||||
messageId: data.messageId,
|
||||
};
|
||||
|
||||
if (data.message) {
|
||||
if (data.message != null) {
|
||||
messageHandler(text, { ...submission, plugin, plugins, userMessage, initialResponse });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
events.onopen = () => console.log('connection is opened');
|
||||
events.onopen = () => {
|
||||
setAbortScroll(false);
|
||||
console.log('connection is opened');
|
||||
};
|
||||
|
||||
events.oncancel = async () => {
|
||||
const streamKey = submission?.initialResponse?.messageId;
|
||||
const streamKey = (submission as TSubmission | null)?.['initialResponse']?.messageId;
|
||||
if (completed.has(streamKey)) {
|
||||
setIsSubmitting(false);
|
||||
setCompleted((prev) => {
|
||||
|
|
@ -157,17 +161,17 @@ export default function useSSE(
|
|||
|
||||
setCompleted((prev) => new Set(prev.add(streamKey)));
|
||||
const latestMessages = getMessages();
|
||||
const conversationId = latestMessages?.[latestMessages?.length - 1]?.conversationId;
|
||||
const conversationId = latestMessages?.[latestMessages.length - 1]?.conversationId;
|
||||
return await abortConversation(
|
||||
conversationId ?? userMessage?.conversationId ?? submission?.conversationId,
|
||||
submission,
|
||||
conversationId ?? userMessage.conversationId ?? submission.conversationId,
|
||||
submission as EventSubmission,
|
||||
latestMessages,
|
||||
);
|
||||
};
|
||||
|
||||
events.onerror = function (e: MessageEvent) {
|
||||
console.log('error in server stream.');
|
||||
startupConfig?.checkBalance && balanceQuery.refetch();
|
||||
(startupConfig?.checkBalance ?? false) && balanceQuery.refetch();
|
||||
|
||||
let data: TResData | undefined = undefined;
|
||||
try {
|
||||
|
|
@ -178,7 +182,7 @@ export default function useSSE(
|
|||
setIsSubmitting(false);
|
||||
}
|
||||
|
||||
errorHandler({ data, submission: { ...submission, userMessage } });
|
||||
errorHandler({ data, submission: { ...submission, userMessage } as EventSubmission });
|
||||
};
|
||||
|
||||
setIsSubmitting(true);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue