LibreChat/client/src/components/Conversations/Conversation.jsx

134 lines
3.8 KiB
React
Raw Normal View History

import { useState, useRef, useEffect} from 'react';
import { useRecoilState, useSetRecoilState } from 'recoil';
import { useUpdateConversationMutation } from '~/data-provider';
2023-02-06 21:17:46 -05:00
import RenameButton from './RenameButton';
import DeleteButton from './DeleteButton';
import ConvoIcon from '../svg/ConvoIcon';
import store from '~/store';
export default function Conversation({ conversation, retainView }) {
const [currentConversation, setCurrentConversation] = useRecoilState(store.conversation);
const setSubmission = useSetRecoilState(store.submission);
const { refreshConversations } = store.useConversations();
const { switchToConversation } = store.useConversation();
const updateConvoMutation = useUpdateConversationMutation(currentConversation?.conversationId);
const [renaming, setRenaming] = useState(false);
const inputRef = useRef(null);
const { conversationId, title } = conversation;
const [titleInput, setTitleInput] = useState(title);
const clickHandler = async () => {
if (currentConversation?.conversationId === conversationId) {
return;
}
// stop existing submission
setSubmission(null);
// set document title
document.title = title;
// set conversation to the new conversation
switchToConversation(conversation);
2023-02-07 00:05:00 -05:00
};
2023-02-06 13:27:28 -05:00
const renameHandler = e => {
e.preventDefault();
setTitleInput(title);
setRenaming(true);
setTimeout(() => {
inputRef.current.focus();
}, 25);
};
const cancelHandler = e => {
e.preventDefault();
setRenaming(false);
};
const onRename = e => {
e.preventDefault();
setRenaming(false);
if (titleInput === title) {
return;
}
updateConvoMutation.mutate({ conversationId, title: titleInput });
};
useEffect(() => {
if (updateConvoMutation.isSuccess) {
refreshConversations();
if (conversationId == currentConversation?.conversationId) {
setCurrentConversation(prevState => ({
...prevState,
title: titleInput
}));
}
}
}, [updateConvoMutation.isSuccess]);
const handleKeyDown = e => {
if (e.key === 'Enter') {
onRename(e);
}
};
2023-02-08 11:05:54 -05:00
const aProps = {
className:
'animate-flash group relative flex cursor-pointer items-center gap-3 break-all rounded-md bg-gray-800 py-3 px-3 pr-14 hover:bg-gray-800'
};
if (currentConversation?.conversationId !== conversationId) {
2023-02-08 11:05:54 -05:00
aProps.className =
'group relative flex cursor-pointer items-center gap-3 break-all rounded-md py-3 px-3 hover:bg-[#2A2B32] hover:pr-4';
}
2023-02-06 13:27:28 -05:00
return (
<a
onClick={() => clickHandler()}
2023-02-08 11:05:54 -05:00
{...aProps}
>
<ConvoIcon />
2023-02-20 21:16:40 -05:00
<div className="relative max-h-5 flex-1 overflow-hidden text-ellipsis break-all">
{renaming === true ? (
<input
ref={inputRef}
type="text"
2023-02-20 21:16:40 -05:00
className="m-0 mr-0 w-full border border-blue-500 bg-transparent p-0 text-sm leading-tight outline-none"
value={titleInput}
onChange={e => setTitleInput(e.target.value)}
onBlur={onRename}
2023-03-07 13:53:23 -05:00
onKeyDown={handleKeyDown}
/>
) : (
title
)}
2023-02-06 13:27:28 -05:00
</div>
{currentConversation?.conversationId === conversationId ? (
2023-02-08 11:05:54 -05:00
<div className="visible absolute right-1 z-10 flex text-gray-300">
<RenameButton
conversationId={conversationId}
renaming={renaming}
renameHandler={renameHandler}
onRename={onRename}
/>
<DeleteButton
conversationId={conversationId}
renaming={renaming}
cancelHandler={cancelHandler}
retainView={retainView}
/>
2023-02-08 11:05:54 -05:00
</div>
) : (
2023-05-14 21:36:53 +05:30
<div className="absolute inset-y-0 right-0 z-10 w-8 bg-gradient-to-l from-gray-900 group-hover:from-[#2A2B32] rounded-r-md" />
2023-02-08 11:05:54 -05:00
)}
2023-02-06 13:27:28 -05:00
</a>
);
}