mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-17 08:50:15 +01:00
🔃 refactor: Streamline Navigation, Message Loading UX (#7118)
* chore: fix logging for illegal target endpoints in getEndpointFromSetup * fix: prevent querying agent by ID for ephemeral agents * refactor: reorder variable declarations in MessagesView for clarity * fix: localize 'nothing found' message in MessagesView * refactor: streamline navigation logic and enhance loading spinner component in ChatView * refactor: simplify loading spinner logic in ChatView component * fix: ensure message queries are invalidated after new conversation creation in HeaderNewChat, MobileNav, and NewChat components * 🐛 First run dev mode will have error occur. 🐛 First run dev mode will have error occur. * fix font-size localstorage presist bug * Don't ping meilisearch if the search is disabled via env var * simplify logic in search/enable endpoint * refactor: simplify enable endpoint condition check * feat: add useIdChangeEffect hook and integrate it into ChatRoute --------- Co-authored-by: Ne0 <20765145+zeeklog@users.noreply.github.com> Co-authored-by: TinyTin <garychangcn@hotmail.com> Co-authored-by: Denis Palnitsky <denis.palnitsky@zendesk.com>
This commit is contained in:
parent
fc30482f65
commit
0e8041bcac
17 changed files with 80 additions and 131 deletions
|
|
@ -1,40 +1,17 @@
|
||||||
const { Keyv } = require('keyv');
|
|
||||||
const express = require('express');
|
const express = require('express');
|
||||||
const { MeiliSearch } = require('meilisearch');
|
const { MeiliSearch } = require('meilisearch');
|
||||||
const { Conversation } = require('~/models/Conversation');
|
|
||||||
const requireJwtAuth = require('~/server/middleware/requireJwtAuth');
|
const requireJwtAuth = require('~/server/middleware/requireJwtAuth');
|
||||||
const { Message } = require('~/models/Message');
|
|
||||||
const { isEnabled } = require('~/server/utils');
|
const { isEnabled } = require('~/server/utils');
|
||||||
const keyvRedis = require('~/cache/keyvRedis');
|
|
||||||
|
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
|
|
||||||
const expiration = 60 * 1000;
|
|
||||||
const cache = isEnabled(process.env.USE_REDIS)
|
|
||||||
? new Keyv({ store: keyvRedis })
|
|
||||||
: new Keyv({ namespace: 'search', ttl: expiration });
|
|
||||||
|
|
||||||
router.use(requireJwtAuth);
|
router.use(requireJwtAuth);
|
||||||
|
|
||||||
router.get('/sync', async function (req, res) {
|
|
||||||
await Message.syncWithMeili();
|
|
||||||
await Conversation.syncWithMeili();
|
|
||||||
res.send('synced');
|
|
||||||
});
|
|
||||||
|
|
||||||
router.get('/test', async function (req, res) {
|
|
||||||
const { q } = req.query;
|
|
||||||
const messages = (
|
|
||||||
await Message.meiliSearch(q, { attributesToHighlight: ['text'] }, true)
|
|
||||||
).hits.map((message) => {
|
|
||||||
const { _formatted, ...rest } = message;
|
|
||||||
return { ...rest, searchResult: true, text: _formatted.text };
|
|
||||||
});
|
|
||||||
res.send(messages);
|
|
||||||
});
|
|
||||||
|
|
||||||
router.get('/enable', async function (req, res) {
|
router.get('/enable', async function (req, res) {
|
||||||
let result = false;
|
if (!isEnabled(process.env.SEARCH)) {
|
||||||
|
return res.send(false);
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const client = new MeiliSearch({
|
const client = new MeiliSearch({
|
||||||
host: process.env.MEILI_HOST,
|
host: process.env.MEILI_HOST,
|
||||||
|
|
@ -42,8 +19,7 @@ router.get('/enable', async function (req, res) {
|
||||||
});
|
});
|
||||||
|
|
||||||
const { status } = await client.health();
|
const { status } = await client.health();
|
||||||
result = status === 'available' && !!process.env.SEARCH;
|
return res.send(status === 'available');
|
||||||
return res.send(result);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return res.send(false);
|
return res.send(false);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { memo, useCallback } from 'react';
|
import { memo, useMemo, useCallback } from 'react';
|
||||||
import { useRecoilValue } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
import { useForm } from 'react-hook-form';
|
import { useForm } from 'react-hook-form';
|
||||||
import { useParams } from 'react-router-dom';
|
import { useParams } from 'react-router-dom';
|
||||||
|
|
@ -19,6 +19,16 @@ import Header from './Header';
|
||||||
import Footer from './Footer';
|
import Footer from './Footer';
|
||||||
import store from '~/store';
|
import store from '~/store';
|
||||||
|
|
||||||
|
function LoadingSpinner() {
|
||||||
|
return (
|
||||||
|
<div className="relative flex-1 overflow-hidden overflow-y-auto">
|
||||||
|
<div className="relative flex h-full items-center justify-center">
|
||||||
|
<Spinner className="text-text-primary" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function ChatView({ index = 0 }: { index?: number }) {
|
function ChatView({ index = 0 }: { index?: number }) {
|
||||||
const { conversationId } = useParams();
|
const { conversationId } = useParams();
|
||||||
const rootSubmission = useRecoilValue(store.submissionByIndex(index));
|
const rootSubmission = useRecoilValue(store.submissionByIndex(index));
|
||||||
|
|
@ -52,15 +62,12 @@ function ChatView({ index = 0 }: { index?: number }) {
|
||||||
const isLandingPage =
|
const isLandingPage =
|
||||||
(!messagesTree || messagesTree.length === 0) &&
|
(!messagesTree || messagesTree.length === 0) &&
|
||||||
(conversationId === Constants.NEW_CONVO || !conversationId);
|
(conversationId === Constants.NEW_CONVO || !conversationId);
|
||||||
|
const isNavigating = (!messagesTree || messagesTree.length === 0) && conversationId != null;
|
||||||
|
|
||||||
if (isLoading && conversationId !== Constants.NEW_CONVO) {
|
if (isLoading && conversationId !== Constants.NEW_CONVO) {
|
||||||
content = (
|
content = <LoadingSpinner />;
|
||||||
<div className="relative flex-1 overflow-hidden overflow-y-auto">
|
} else if ((isLoading || isNavigating) && !isLandingPage) {
|
||||||
<div className="relative flex h-full items-center justify-center">
|
content = <LoadingSpinner />;
|
||||||
<Spinner className="text-text-primary" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
} else if (!isLandingPage) {
|
} else if (!isLandingPage) {
|
||||||
content = <MessagesView messagesTree={messagesTree} />;
|
content = <MessagesView messagesTree={messagesTree} />;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ export default function HeaderNewChat() {
|
||||||
[QueryKeys.messages, conversation?.conversationId ?? Constants.NEW_CONVO],
|
[QueryKeys.messages, conversation?.conversationId ?? Constants.NEW_CONVO],
|
||||||
[],
|
[],
|
||||||
);
|
);
|
||||||
|
queryClient.invalidateQueries([QueryKeys.messages]);
|
||||||
newConversation();
|
newConversation();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,10 +14,9 @@ export default function MessagesView({
|
||||||
messagesTree?: TMessage[] | null;
|
messagesTree?: TMessage[] | null;
|
||||||
}) {
|
}) {
|
||||||
const localize = useLocalize();
|
const localize = useLocalize();
|
||||||
const scrollButtonPreference = useRecoilValue(store.showScrollButton);
|
|
||||||
const maximizeChatSpace = useRecoilValue(store.maximizeChatSpace);
|
|
||||||
const fontSize = useRecoilValue(store.fontSize);
|
const fontSize = useRecoilValue(store.fontSize);
|
||||||
const { screenshotTargetRef } = useScreenshot();
|
const { screenshotTargetRef } = useScreenshot();
|
||||||
|
const scrollButtonPreference = useRecoilValue(store.showScrollButton);
|
||||||
const [currentEditId, setCurrentEditId] = useState<number | string | null>(-1);
|
const [currentEditId, setCurrentEditId] = useState<number | string | null>(-1);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ export default function SearchButtons({ message }: { message: TMessage }) {
|
||||||
const localize = useLocalize();
|
const localize = useLocalize();
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
const search = useRecoilValue(store.search);
|
const search = useRecoilValue(store.search);
|
||||||
const { navigateWithLastTools } = useNavigateToConvo();
|
const { navigateToConvo } = useNavigateToConvo();
|
||||||
const conversationId = message.conversationId ?? '';
|
const conversationId = message.conversationId ?? '';
|
||||||
|
|
||||||
const clickHandler = async (event: React.MouseEvent<HTMLButtonElement>) => {
|
const clickHandler = async (event: React.MouseEvent<HTMLButtonElement>) => {
|
||||||
|
|
@ -39,14 +39,13 @@ export default function SearchButtons({ message }: { message: TMessage }) {
|
||||||
}
|
}
|
||||||
|
|
||||||
document.title = title;
|
document.title = title;
|
||||||
navigateWithLastTools(
|
navigateToConvo(
|
||||||
cachedConvo ??
|
cachedConvo ??
|
||||||
({
|
({
|
||||||
conversationId,
|
conversationId,
|
||||||
title,
|
title,
|
||||||
} as TConversation),
|
} as TConversation),
|
||||||
true,
|
{ resetLatestMessage: true },
|
||||||
true,
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,11 +31,11 @@ export default function Conversation({
|
||||||
const params = useParams();
|
const params = useParams();
|
||||||
const localize = useLocalize();
|
const localize = useLocalize();
|
||||||
const { showToast } = useToastContext();
|
const { showToast } = useToastContext();
|
||||||
|
const { navigateToConvo } = useNavigateToConvo();
|
||||||
|
const { data: endpointsConfig } = useGetEndpointsQuery();
|
||||||
const currentConvoId = useMemo(() => params.conversationId, [params.conversationId]);
|
const currentConvoId = useMemo(() => params.conversationId, [params.conversationId]);
|
||||||
const updateConvoMutation = useUpdateConversationMutation(currentConvoId ?? '');
|
const updateConvoMutation = useUpdateConversationMutation(currentConvoId ?? '');
|
||||||
const activeConvos = useRecoilValue(store.allConversationsSelector);
|
const activeConvos = useRecoilValue(store.allConversationsSelector);
|
||||||
const { data: endpointsConfig } = useGetEndpointsQuery();
|
|
||||||
const { navigateWithLastTools } = useNavigateToConvo();
|
|
||||||
const isSmallScreen = useMediaQuery('(max-width: 768px)');
|
const isSmallScreen = useMediaQuery('(max-width: 768px)');
|
||||||
const { conversationId, title = '' } = conversation;
|
const { conversationId, title = '' } = conversation;
|
||||||
|
|
||||||
|
|
@ -118,10 +118,10 @@ export default function Conversation({
|
||||||
document.title = title;
|
document.title = title;
|
||||||
}
|
}
|
||||||
|
|
||||||
navigateWithLastTools(
|
navigateToConvo(conversation, {
|
||||||
conversation,
|
currentConvoId,
|
||||||
!(conversationId ?? '') || conversationId === Constants.NEW_CONVO,
|
resetLatestMessage: !(conversationId ?? '') || conversationId === Constants.NEW_CONVO,
|
||||||
);
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const convoOptionsProps = {
|
const convoOptionsProps = {
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,7 @@ export default function MobileNav({
|
||||||
[QueryKeys.messages, conversation?.conversationId ?? Constants.NEW_CONVO],
|
[QueryKeys.messages, conversation?.conversationId ?? Constants.NEW_CONVO],
|
||||||
[],
|
[],
|
||||||
);
|
);
|
||||||
|
queryClient.invalidateQueries([QueryKeys.messages]);
|
||||||
newConversation();
|
newConversation();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@ export default function NewChat({
|
||||||
[QueryKeys.messages, conversation?.conversationId ?? Constants.NEW_CONVO],
|
[QueryKeys.messages, conversation?.conversationId ?? Constants.NEW_CONVO],
|
||||||
[],
|
[],
|
||||||
);
|
);
|
||||||
|
queryClient.invalidateQueries([QueryKeys.messages]);
|
||||||
newConvo();
|
newConvo();
|
||||||
navigate('/c/new', { state: { focusChat: true } });
|
navigate('/c/new', { state: { focusChat: true } });
|
||||||
if (isSmallScreen) {
|
if (isSmallScreen) {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import type { TMessage } from 'librechat-data-provider';
|
import type { TMessage } from 'librechat-data-provider';
|
||||||
import MultiMessage from './MultiMessage';
|
import MultiMessage from './MultiMessage';
|
||||||
|
import { useLocalize } from '~/hooks';
|
||||||
|
|
||||||
export default function MessagesView({
|
export default function MessagesView({
|
||||||
messagesTree: _messagesTree,
|
messagesTree: _messagesTree,
|
||||||
|
|
@ -9,6 +10,7 @@ export default function MessagesView({
|
||||||
messagesTree?: TMessage[] | null;
|
messagesTree?: TMessage[] | null;
|
||||||
conversationId: string;
|
conversationId: string;
|
||||||
}) {
|
}) {
|
||||||
|
const localize = useLocalize();
|
||||||
const [currentEditId, setCurrentEditId] = useState<number | string | null>(-1);
|
const [currentEditId, setCurrentEditId] = useState<number | string | null>(-1);
|
||||||
return (
|
return (
|
||||||
<div className="flex-1 pb-[50px]">
|
<div className="flex-1 pb-[50px]">
|
||||||
|
|
@ -23,7 +25,7 @@ export default function MessagesView({
|
||||||
<div className="flex flex-col pb-9 text-sm dark:bg-transparent">
|
<div className="flex flex-col pb-9 text-sm dark:bg-transparent">
|
||||||
{(_messagesTree && _messagesTree.length == 0) || _messagesTree === null ? (
|
{(_messagesTree && _messagesTree.length == 0) || _messagesTree === null ? (
|
||||||
<div className="flex w-full items-center justify-center gap-1 bg-gray-50 p-3 text-sm text-gray-500 dark:border-gray-800/50 dark:bg-gray-800 dark:text-gray-300">
|
<div className="flex w-full items-center justify-center gap-1 bg-gray-50 p-3 text-sm text-gray-500 dark:border-gray-800/50 dark:bg-gray-800 dark:text-gray-300">
|
||||||
Nothing found
|
{localize('com_ui_nothing_found')}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import { useWatch, useForm, FormProvider } from 'react-hook-form';
|
||||||
import { useGetModelsQuery } from 'librechat-data-provider/react-query';
|
import { useGetModelsQuery } from 'librechat-data-provider/react-query';
|
||||||
import {
|
import {
|
||||||
Tools,
|
Tools,
|
||||||
|
Constants,
|
||||||
SystemRoles,
|
SystemRoles,
|
||||||
EModelEndpoint,
|
EModelEndpoint,
|
||||||
isAssistantsEndpoint,
|
isAssistantsEndpoint,
|
||||||
|
|
@ -45,7 +46,7 @@ export default function AgentPanel({
|
||||||
|
|
||||||
const modelsQuery = useGetModelsQuery();
|
const modelsQuery = useGetModelsQuery();
|
||||||
const agentQuery = useGetAgentByIdQuery(current_agent_id ?? '', {
|
const agentQuery = useGetAgentByIdQuery(current_agent_id ?? '', {
|
||||||
enabled: !!(current_agent_id ?? ''),
|
enabled: !!(current_agent_id ?? '') && current_agent_id !== Constants.EPHEMERAL_AGENT_ID,
|
||||||
});
|
});
|
||||||
|
|
||||||
const models = useMemo(() => modelsQuery.data ?? {}, [modelsQuery.data]);
|
const models = useMemo(() => modelsQuery.data ?? {}, [modelsQuery.data]);
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ export default function useSelectAgent() {
|
||||||
);
|
);
|
||||||
|
|
||||||
const agentQuery = useGetAgentByIdQuery(selectedAgentId ?? '', {
|
const agentQuery = useGetAgentByIdQuery(selectedAgentId ?? '', {
|
||||||
enabled: !!(selectedAgentId ?? ''),
|
enabled: !!(selectedAgentId ?? '') && selectedAgentId !== Constants.EPHEMERAL_AGENT_ID,
|
||||||
});
|
});
|
||||||
|
|
||||||
const updateConversation = useCallback(
|
const updateConversation = useCallback(
|
||||||
|
|
|
||||||
|
|
@ -2,4 +2,5 @@ export { default as useChatHelpers } from './useChatHelpers';
|
||||||
export { default as useAddedHelpers } from './useAddedHelpers';
|
export { default as useAddedHelpers } from './useAddedHelpers';
|
||||||
export { default as useAddedResponse } from './useAddedResponse';
|
export { default as useAddedResponse } from './useAddedResponse';
|
||||||
export { default as useChatFunctions } from './useChatFunctions';
|
export { default as useChatFunctions } from './useChatFunctions';
|
||||||
|
export { default as useIdChangeEffect } from './useIdChangeEffect';
|
||||||
export { default as useFocusChatEffect } from './useFocusChatEffect';
|
export { default as useFocusChatEffect } from './useFocusChatEffect';
|
||||||
|
|
|
||||||
21
client/src/hooks/Chat/useIdChangeEffect.ts
Normal file
21
client/src/hooks/Chat/useIdChangeEffect.ts
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
import { useEffect, useRef } from 'react';
|
||||||
|
import { useResetRecoilState } from 'recoil';
|
||||||
|
import { logger } from '~/utils';
|
||||||
|
import store from '~/store';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook to reset artifacts when the conversation ID changes
|
||||||
|
* @param conversationId - The current conversation ID
|
||||||
|
*/
|
||||||
|
export default function useIdChangeEffect(conversationId: string) {
|
||||||
|
const lastConvoId = useRef<string | null>(null);
|
||||||
|
const resetArtifacts = useResetRecoilState(store.artifactsState);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (conversationId !== lastConvoId.current) {
|
||||||
|
logger.log('conversation', 'Conversation ID change');
|
||||||
|
resetArtifacts();
|
||||||
|
}
|
||||||
|
lastConvoId.current = conversationId;
|
||||||
|
}, [conversationId, resetArtifacts]);
|
||||||
|
}
|
||||||
|
|
@ -1,13 +1,7 @@
|
||||||
|
import { useSetRecoilState } from 'recoil';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import { useQueryClient } from '@tanstack/react-query';
|
import { useQueryClient } from '@tanstack/react-query';
|
||||||
import { useSetRecoilState, useResetRecoilState } from 'recoil';
|
import { QueryKeys, Constants } from 'librechat-data-provider';
|
||||||
import {
|
|
||||||
QueryKeys,
|
|
||||||
Constants,
|
|
||||||
dataService,
|
|
||||||
EModelEndpoint,
|
|
||||||
LocalStorageKeys,
|
|
||||||
} from 'librechat-data-provider';
|
|
||||||
import type { TConversation, TEndpointsConfig, TModelsConfig } from 'librechat-data-provider';
|
import type { TConversation, TEndpointsConfig, TModelsConfig } from 'librechat-data-provider';
|
||||||
import { buildDefaultConvo, getDefaultEndpoint, getEndpointField, logger } from '~/utils';
|
import { buildDefaultConvo, getDefaultEndpoint, getEndpointField, logger } from '~/utils';
|
||||||
import store from '~/store';
|
import store from '~/store';
|
||||||
|
|
@ -16,48 +10,28 @@ const useNavigateToConvo = (index = 0) => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
const clearAllConversations = store.useClearConvoState();
|
const clearAllConversations = store.useClearConvoState();
|
||||||
const resetArtifacts = useResetRecoilState(store.artifactsState);
|
|
||||||
const setSubmission = useSetRecoilState(store.submissionByIndex(index));
|
const setSubmission = useSetRecoilState(store.submissionByIndex(index));
|
||||||
const clearAllLatestMessages = store.useClearLatestMessages(`useNavigateToConvo ${index}`);
|
const clearAllLatestMessages = store.useClearLatestMessages(`useNavigateToConvo ${index}`);
|
||||||
const { hasSetConversation, setConversation } = store.useCreateConversationAtom(index);
|
const { hasSetConversation, setConversation } = store.useCreateConversationAtom(index);
|
||||||
|
|
||||||
const fetchFreshData = async (conversationId?: string | null) => {
|
|
||||||
if (!conversationId) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
const data = await queryClient.fetchQuery([QueryKeys.conversation, conversationId], () =>
|
|
||||||
dataService.getConversationById(conversationId),
|
|
||||||
);
|
|
||||||
logger.log('conversation', 'Fetched fresh conversation data', data);
|
|
||||||
await queryClient.invalidateQueries([QueryKeys.messages, conversationId]);
|
|
||||||
setConversation(data);
|
|
||||||
navigate(`/c/${conversationId ?? Constants.NEW_CONVO}`, { state: { focusChat: true } });
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error fetching conversation data on navigation', error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const navigateToConvo = (
|
const navigateToConvo = (
|
||||||
conversation?: TConversation | null,
|
conversation?: TConversation | null,
|
||||||
_resetLatestMessage = true,
|
options?: {
|
||||||
/** Likely need to remove this since it happens after fetching conversation data */
|
resetLatestMessage?: boolean;
|
||||||
invalidateMessages = false,
|
currentConvoId?: string;
|
||||||
|
},
|
||||||
) => {
|
) => {
|
||||||
if (!conversation) {
|
if (!conversation) {
|
||||||
logger.warn('conversation', 'Conversation not provided to `navigateToConvo`');
|
logger.warn('conversation', 'Conversation not provided to `navigateToConvo`');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const { resetLatestMessage = true, currentConvoId } = options || {};
|
||||||
logger.log('conversation', 'Navigating to conversation', conversation);
|
logger.log('conversation', 'Navigating to conversation', conversation);
|
||||||
hasSetConversation.current = true;
|
hasSetConversation.current = true;
|
||||||
setSubmission(null);
|
setSubmission(null);
|
||||||
if (_resetLatestMessage) {
|
if (resetLatestMessage) {
|
||||||
clearAllLatestMessages();
|
clearAllLatestMessages();
|
||||||
}
|
}
|
||||||
if (invalidateMessages && conversation.conversationId != null && conversation.conversationId) {
|
|
||||||
queryClient.setQueryData([QueryKeys.messages, Constants.NEW_CONVO], []);
|
|
||||||
queryClient.invalidateQueries([QueryKeys.messages, conversation.conversationId]);
|
|
||||||
}
|
|
||||||
|
|
||||||
let convo = { ...conversation };
|
let convo = { ...conversation };
|
||||||
const endpointsConfig = queryClient.getQueryData<TEndpointsConfig>([QueryKeys.endpoints]);
|
const endpointsConfig = queryClient.getQueryData<TEndpointsConfig>([QueryKeys.endpoints]);
|
||||||
|
|
@ -84,51 +58,13 @@ const useNavigateToConvo = (index = 0) => {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
clearAllConversations(true);
|
clearAllConversations(true);
|
||||||
resetArtifacts();
|
|
||||||
setConversation(convo);
|
setConversation(convo);
|
||||||
if (convo.conversationId !== Constants.NEW_CONVO && convo.conversationId) {
|
queryClient.setQueryData([QueryKeys.messages, currentConvoId], []);
|
||||||
queryClient.invalidateQueries([QueryKeys.conversation, convo.conversationId]);
|
navigate(`/c/${convo.conversationId ?? Constants.NEW_CONVO}`, { state: { focusChat: true } });
|
||||||
fetchFreshData(convo.conversationId);
|
|
||||||
} else {
|
|
||||||
navigate(`/c/${convo.conversationId ?? Constants.NEW_CONVO}`, { state: { focusChat: true } });
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const navigateWithLastTools = (
|
|
||||||
conversation?: TConversation | null,
|
|
||||||
_resetLatestMessage?: boolean,
|
|
||||||
invalidateMessages?: boolean,
|
|
||||||
) => {
|
|
||||||
if (!conversation) {
|
|
||||||
logger.warn('conversation', 'Conversation not provided to `navigateToConvo`');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// set conversation to the new conversation
|
|
||||||
if (conversation.endpoint === EModelEndpoint.gptPlugins) {
|
|
||||||
let lastSelectedTools = [];
|
|
||||||
try {
|
|
||||||
lastSelectedTools =
|
|
||||||
JSON.parse(localStorage.getItem(LocalStorageKeys.LAST_TOOLS) ?? '') ?? [];
|
|
||||||
} catch (e) {
|
|
||||||
logger.error('conversation', 'Error parsing last selected tools', e);
|
|
||||||
}
|
|
||||||
const hasTools = (conversation.tools?.length ?? 0) > 0;
|
|
||||||
navigateToConvo(
|
|
||||||
{
|
|
||||||
...conversation,
|
|
||||||
tools: hasTools ? conversation.tools : lastSelectedTools,
|
|
||||||
},
|
|
||||||
_resetLatestMessage,
|
|
||||||
invalidateMessages,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
navigateToConvo(conversation, _resetLatestMessage, invalidateMessages);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
navigateToConvo,
|
navigateToConvo,
|
||||||
navigateWithLastTools,
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -58,10 +58,14 @@ export const ThemeProvider = ({ initialTheme, children }) => {
|
||||||
if (fontSize == null) {
|
if (fontSize == null) {
|
||||||
setFontSize('text-base');
|
setFontSize('text-base');
|
||||||
applyFontSize('text-base');
|
applyFontSize('text-base');
|
||||||
localStorage.setItem('fontSize', 'text-base');
|
localStorage.setItem('fontSize', JSON.stringify('text-base'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
applyFontSize(JSON.parse(fontSize));
|
try {
|
||||||
|
applyFontSize(JSON.parse(fontSize));
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
// Reason: This effect should only run once, and `setFontSize` is a stable function
|
// Reason: This effect should only run once, and `setFontSize` is a stable function
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, []);
|
}, []);
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,8 @@ import {
|
||||||
useGetStartupConfig,
|
useGetStartupConfig,
|
||||||
useGetEndpointsQuery,
|
useGetEndpointsQuery,
|
||||||
} from '~/data-provider';
|
} from '~/data-provider';
|
||||||
|
import { useNewConvo, useAppStartup, useAssistantListMap, useIdChangeEffect } from '~/hooks';
|
||||||
import { getDefaultModelSpec, getModelSpecPreset, logger } from '~/utils';
|
import { getDefaultModelSpec, getModelSpecPreset, logger } from '~/utils';
|
||||||
import { useNewConvo, useAppStartup, useAssistantListMap } from '~/hooks';
|
|
||||||
import { ToolCallsMapProvider } from '~/Providers';
|
import { ToolCallsMapProvider } from '~/Providers';
|
||||||
import ChatView from '~/components/Chat/ChatView';
|
import ChatView from '~/components/Chat/ChatView';
|
||||||
import useAuthRedirect from './useAuthRedirect';
|
import useAuthRedirect from './useAuthRedirect';
|
||||||
|
|
@ -34,7 +34,7 @@ export default function ChatRoute() {
|
||||||
|
|
||||||
const index = 0;
|
const index = 0;
|
||||||
const { conversationId = '' } = useParams();
|
const { conversationId = '' } = useParams();
|
||||||
|
useIdChangeEffect(conversationId);
|
||||||
const { hasSetConversation, conversation } = store.useCreateConversationAtom(index);
|
const { hasSetConversation, conversation } = store.useCreateConversationAtom(index);
|
||||||
const { newConversation } = useNewConvo();
|
const { newConversation } = useNewConvo();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ const getEndpointFromSetup = (
|
||||||
if (targetEndpoint && endpointsConfig?.[targetEndpoint]) {
|
if (targetEndpoint && endpointsConfig?.[targetEndpoint]) {
|
||||||
return targetEndpoint as EModelEndpoint;
|
return targetEndpoint as EModelEndpoint;
|
||||||
} else if (targetEndpoint) {
|
} else if (targetEndpoint) {
|
||||||
console.warn(`Illegal target endpoint ${targetEndpoint} ${endpointsConfig}`);
|
console.warn(`Illegal target endpoint ${targetEndpoint}`, endpointsConfig);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue