mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-28 14:18:51 +01:00
🪶 refactor: Chat Input Focus for Conversation Navigations & ChatForm Optimizations (#7100)
* refactor: improve ChatView layout by keeping ChatForm mounted * feat: implement focusChat functionality for new conversations and navigations * refactor: reset artifacts when navigating to prevent any from rendering in a conversation when none exist; edge case, artifacts get created by search route (TODO: use a different artifact renderer for Search markdown)
This commit is contained in:
parent
6826c0ed43
commit
fc30482f65
8 changed files with 68 additions and 41 deletions
|
|
@ -2,6 +2,7 @@ import { memo, useCallback } from 'react';
|
|||
import { useRecoilValue } from 'recoil';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { Constants } from 'librechat-data-provider';
|
||||
import { useGetMessagesByConvoId } from 'librechat-data-provider/react-query';
|
||||
import type { TMessage } from 'librechat-data-provider';
|
||||
import type { ChatFormValues } from '~/common';
|
||||
|
|
@ -11,8 +12,8 @@ import ConversationStarters from './Input/ConversationStarters';
|
|||
import MessagesView from './Messages/MessagesView';
|
||||
import { Spinner } from '~/components/svg';
|
||||
import Presentation from './Presentation';
|
||||
import { buildTree, cn } from '~/utils';
|
||||
import ChatForm from './Input/ChatForm';
|
||||
import { buildTree } from '~/utils';
|
||||
import Landing from './Landing';
|
||||
import Header from './Header';
|
||||
import Footer from './Footer';
|
||||
|
|
@ -48,9 +49,11 @@ function ChatView({ index = 0 }: { index?: number }) {
|
|||
});
|
||||
|
||||
let content: JSX.Element | null | undefined;
|
||||
const isLandingPage = !messagesTree || messagesTree.length === 0;
|
||||
const isLandingPage =
|
||||
(!messagesTree || messagesTree.length === 0) &&
|
||||
(conversationId === Constants.NEW_CONVO || !conversationId);
|
||||
|
||||
if (isLoading && conversationId !== 'new') {
|
||||
if (isLoading && conversationId !== Constants.NEW_CONVO) {
|
||||
content = (
|
||||
<div className="relative flex-1 overflow-hidden overflow-y-auto">
|
||||
<div className="relative flex h-full items-center justify-center">
|
||||
|
|
@ -71,27 +74,28 @@ function ChatView({ index = 0 }: { index?: number }) {
|
|||
<Presentation>
|
||||
<div className="flex h-full w-full flex-col">
|
||||
{!isLoading && <Header />}
|
||||
|
||||
{isLandingPage ? (
|
||||
<>
|
||||
<div className="flex flex-1 flex-col items-center justify-end sm:justify-center">
|
||||
{content}
|
||||
<div className="w-full max-w-3xl transition-all duration-200 xl:max-w-4xl">
|
||||
<ChatForm index={index} />
|
||||
<ConversationStarters />
|
||||
</div>
|
||||
</div>
|
||||
<Footer />
|
||||
</>
|
||||
) : (
|
||||
<div className="flex h-full flex-col overflow-y-auto">
|
||||
<>
|
||||
<div
|
||||
className={cn(
|
||||
'flex flex-col',
|
||||
isLandingPage
|
||||
? 'flex-1 items-center justify-end sm:justify-center'
|
||||
: 'h-full overflow-y-auto',
|
||||
)}
|
||||
>
|
||||
{content}
|
||||
<div className="w-full">
|
||||
<div
|
||||
className={cn(
|
||||
'w-full',
|
||||
isLandingPage && 'max-w-3xl transition-all duration-200 xl:max-w-4xl',
|
||||
)}
|
||||
>
|
||||
<ChatForm index={index} />
|
||||
<Footer />
|
||||
{isLandingPage ? <ConversationStarters /> : <Footer />}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{isLandingPage && <Footer />}
|
||||
</>
|
||||
</div>
|
||||
</Presentation>
|
||||
</AddedChatContext.Provider>
|
||||
|
|
|
|||
|
|
@ -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<HTMLButtonElement>(null);
|
||||
const textAreaRef = useRef<HTMLTextAreaElement>(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<Pick<BadgeItem, 'id'>[]>([]);
|
||||
|
||||
const search = useRecoilValue(store.search);
|
||||
const SpeechToText = useRecoilValue(store.speechToText);
|
||||
const TextToSpeech = useRecoilValue(store.textToSpeech);
|
||||
const chatDirection = useRecoilValue(store.chatDirection);
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ export default function NewChat({
|
|||
[],
|
||||
);
|
||||
newConvo();
|
||||
navigate('/c/new');
|
||||
navigate('/c/new', { state: { focusChat: true } });
|
||||
if (isSmallScreen) {
|
||||
toggleNav();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue