+ <>
+
{content}
-
+
-
+ {isLandingPage ? : }
- )}
+ {isLandingPage &&
}
+ >
diff --git a/client/src/components/Chat/Input/ChatForm.tsx b/client/src/components/Chat/Input/ChatForm.tsx
index 7ac983099f..4e5e68c073 100644
--- a/client/src/components/Chat/Input/ChatForm.tsx
+++ b/client/src/components/Chat/Input/ChatForm.tsx
@@ -15,6 +15,7 @@ import {
useHandleKeyUp,
useQueryParams,
useSubmitMessage,
+ useFocusChatEffect,
} from '~/hooks';
import { mainTextareaId, BadgeItem } from '~/common';
import AttachFileChat from './Files/AttachFileChat';
@@ -36,6 +37,7 @@ import store from '~/store';
const ChatForm = memo(({ index = 0 }: { index?: number }) => {
const submitButtonRef = useRef
(null);
const textAreaRef = useRef(null);
+ useFocusChatEffect(textAreaRef);
const [isCollapsed, setIsCollapsed] = useState(false);
const [, setIsScrollable] = useState(false);
@@ -43,7 +45,6 @@ const ChatForm = memo(({ index = 0 }: { index?: number }) => {
const [isTextAreaFocused, setIsTextAreaFocused] = useState(false);
const [backupBadges, setBackupBadges] = useState[]>([]);
- const search = useRecoilValue(store.search);
const SpeechToText = useRecoilValue(store.speechToText);
const TextToSpeech = useRecoilValue(store.textToSpeech);
const chatDirection = useRecoilValue(store.chatDirection);
diff --git a/client/src/components/Nav/NewChat.tsx b/client/src/components/Nav/NewChat.tsx
index a8a75c8b04..7b3129adb5 100644
--- a/client/src/components/Nav/NewChat.tsx
+++ b/client/src/components/Nav/NewChat.tsx
@@ -41,7 +41,7 @@ export default function NewChat({
[],
);
newConvo();
- navigate('/c/new');
+ navigate('/c/new', { state: { focusChat: true } });
if (isSmallScreen) {
toggleNav();
}
diff --git a/client/src/hooks/Chat/index.ts b/client/src/hooks/Chat/index.ts
index 5439604276..b9b286c8e2 100644
--- a/client/src/hooks/Chat/index.ts
+++ b/client/src/hooks/Chat/index.ts
@@ -2,3 +2,4 @@ export { default as useChatHelpers } from './useChatHelpers';
export { default as useAddedHelpers } from './useAddedHelpers';
export { default as useAddedResponse } from './useAddedResponse';
export { default as useChatFunctions } from './useChatFunctions';
+export { default as useFocusChatEffect } from './useFocusChatEffect';
diff --git a/client/src/hooks/Chat/useChatFunctions.ts b/client/src/hooks/Chat/useChatFunctions.ts
index b75d97d6a2..5f83fb106a 100644
--- a/client/src/hooks/Chat/useChatFunctions.ts
+++ b/client/src/hooks/Chat/useChatFunctions.ts
@@ -148,7 +148,7 @@ export default function useChatFunctions({
parentMessageId = Constants.NO_PARENT;
currentMessages = [];
conversationId = null;
- navigate('/c/new');
+ navigate('/c/new', { state: { focusChat: true } });
}
const targetParentMessageId = isRegenerate ? messageId : latestMessage?.parentMessageId;
diff --git a/client/src/hooks/Chat/useFocusChatEffect.ts b/client/src/hooks/Chat/useFocusChatEffect.ts
new file mode 100644
index 0000000000..3a22533b75
--- /dev/null
+++ b/client/src/hooks/Chat/useFocusChatEffect.ts
@@ -0,0 +1,18 @@
+import { useEffect } from 'react';
+import { useLocation, useNavigate } from 'react-router-dom';
+import { logger } from '~/utils';
+
+export default function useFocusChatEffect(textAreaRef: React.RefObject) {
+ const location = useLocation();
+ const navigate = useNavigate();
+ useEffect(() => {
+ if (textAreaRef?.current && location.state?.focusChat) {
+ logger.log(
+ 'conversation',
+ `Focusing textarea on location state change: ${location.pathname}`,
+ );
+ textAreaRef.current?.focus();
+ navigate(`${location.pathname}${location.search ?? ''}`, { replace: true, state: {} });
+ }
+ }, [navigate, textAreaRef, location.pathname, location.state?.focusChat, location.search]);
+}
diff --git a/client/src/hooks/Conversations/useNavigateToConvo.tsx b/client/src/hooks/Conversations/useNavigateToConvo.tsx
index 1a990e642f..c31fb08a3a 100644
--- a/client/src/hooks/Conversations/useNavigateToConvo.tsx
+++ b/client/src/hooks/Conversations/useNavigateToConvo.tsx
@@ -1,6 +1,6 @@
-import { useSetRecoilState } from 'recoil';
import { useNavigate } from 'react-router-dom';
import { useQueryClient } from '@tanstack/react-query';
+import { useSetRecoilState, useResetRecoilState } from 'recoil';
import {
QueryKeys,
Constants,
@@ -16,8 +16,9 @@ const useNavigateToConvo = (index = 0) => {
const navigate = useNavigate();
const queryClient = useQueryClient();
const clearAllConversations = store.useClearConvoState();
- const clearAllLatestMessages = store.useClearLatestMessages(`useNavigateToConvo ${index}`);
+ const resetArtifacts = useResetRecoilState(store.artifactsState);
const setSubmission = useSetRecoilState(store.submissionByIndex(index));
+ const clearAllLatestMessages = store.useClearLatestMessages(`useNavigateToConvo ${index}`);
const { hasSetConversation, setConversation } = store.useCreateConversationAtom(index);
const fetchFreshData = async (conversationId?: string | null) => {
@@ -31,6 +32,7 @@ const useNavigateToConvo = (index = 0) => {
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);
}
@@ -82,11 +84,13 @@ const useNavigateToConvo = (index = 0) => {
});
}
clearAllConversations(true);
+ resetArtifacts();
setConversation(convo);
- navigate(`/c/${convo.conversationId ?? Constants.NEW_CONVO}`);
if (convo.conversationId !== Constants.NEW_CONVO && convo.conversationId) {
queryClient.invalidateQueries([QueryKeys.conversation, convo.conversationId]);
fetchFreshData(convo.conversationId);
+ } else {
+ navigate(`/c/${convo.conversationId ?? Constants.NEW_CONVO}`, { state: { focusChat: true } });
}
};
diff --git a/client/src/hooks/useNewConvo.ts b/client/src/hooks/useNewConvo.ts
index d27f80a306..095e29962d 100644
--- a/client/src/hooks/useNewConvo.ts
+++ b/client/src/hooks/useNewConvo.ts
@@ -1,6 +1,6 @@
-import { useCallback, useRef } from 'react';
+import { useCallback } from 'react';
+import { useNavigate, useSearchParams } from 'react-router-dom';
import { useGetModelsQuery } from 'librechat-data-provider/react-query';
-import { useNavigate } from 'react-router-dom';
import {
Constants,
FileSources,
@@ -30,12 +30,12 @@ import { useDeleteFilesMutation, useGetEndpointsQuery, useGetStartupConfig } fro
import useAssistantListMap from './Assistants/useAssistantListMap';
import { useResetChatBadges } from './useChatBadges';
import { usePauseGlobalAudio } from './Audio';
-import { mainTextareaId } from '~/common';
import { logger } from '~/utils';
import store from '~/store';
const useNewConvo = (index = 0) => {
const navigate = useNavigate();
+ const [searchParams] = useSearchParams();
const { data: startupConfig } = useGetStartupConfig();
const clearAllConversations = store.useClearConvoState();
const defaultPreset = useRecoilValue(store.defaultPreset);
@@ -47,7 +47,6 @@ const useNewConvo = (index = 0) => {
const { data: endpointsConfig = {} as TEndpointsConfig } = useGetEndpointsQuery();
const modelsQuery = useGetModelsQuery();
- const timeoutIdRef = useRef();
const assistantsListMap = useAssistantListMap();
const { pauseGlobalAudio } = usePauseGlobalAudio(index);
const saveDrafts = useRecoilValue(store.saveDrafts);
@@ -159,24 +158,24 @@ const useNewConvo = (index = 0) => {
clearAllLatestMessages();
}
+ const searchParamsString = searchParams?.toString();
+ const getParams = () => (searchParamsString ? `?${searchParamsString}` : '');
+
if (conversation.conversationId === Constants.NEW_CONVO && !modelsData) {
const appTitle = localStorage.getItem(LocalStorageKeys.APP_TITLE) ?? '';
if (appTitle) {
document.title = appTitle;
}
- navigate(`/c/${Constants.NEW_CONVO}`);
- }
-
- clearTimeout(timeoutIdRef.current);
- if (disableFocus === true) {
+ const path = `/c/${Constants.NEW_CONVO}${getParams()}`;
+ navigate(path, { state: { focusChat: true } });
return;
}
- timeoutIdRef.current = setTimeout(() => {
- const textarea = document.getElementById(mainTextareaId);
- if (textarea) {
- textarea.focus();
- }
- }, 150);
+
+ const path = `/c/${conversation.conversationId}${getParams()}`;
+ navigate(path, {
+ replace: true,
+ state: disableFocus ? {} : { focusChat: true },
+ });
},
[endpointsConfig, defaultPreset, assistantsListMap, modelsQuery.data],
);