-
Notifications
You must be signed in to change notification settings - Fork 453
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve chat input #472
Improve chat input #472
Changes from 2 commits
fb3d397
15a4e52
38ccb04
c53c371
3781ea6
48b22d4
a6270f0
bc27a15
5985f4f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,57 +2,55 @@ import React from 'react' | |
|
||
import { PiPaperPlaneRight } from 'react-icons/pi' | ||
import { LoadingState } from '../../lib/llm/types' | ||
import { Button } from '../ui/button' | ||
import LLMSelectOrButton from '../Settings/LLMSettings/LLMSelectOrButton' | ||
|
||
interface ChatInputProps { | ||
userTextFieldInput: string | ||
setUserTextFieldInput: (value: string) => void | ||
handleSubmitNewMessage: () => void | ||
loadingState: LoadingState | ||
selectedLLM: string | undefined | ||
setSelectedLLM: (value: string | undefined) => void | ||
} | ||
|
||
const ChatInput: React.FC<ChatInputProps> = ({ | ||
userTextFieldInput, | ||
setUserTextFieldInput, | ||
handleSubmitNewMessage, | ||
loadingState, | ||
selectedLLM, | ||
setSelectedLLM, | ||
}) => ( | ||
<div className="flex h-titlebar w-full items-center justify-center p-10"> | ||
<div className=" relative bottom-5 flex w-full max-w-3xl"> | ||
<div className="w-full rounded-lg border-2 border-solid border-neutral-700 p-3 focus-within:ring-1 focus-within:ring-[#8c8c8c]"> | ||
<div className="flex h-full pr-8"> | ||
<textarea | ||
onKeyDown={(e) => { | ||
if (userTextFieldInput && !e.shiftKey && e.key === 'Enter') { | ||
e.preventDefault() | ||
handleSubmitNewMessage() | ||
} | ||
}} | ||
onChange={(e) => setUserTextFieldInput(e.target.value)} | ||
value={userTextFieldInput} | ||
className="mr-2 max-h-[50px] w-full resize-none overflow-y-auto border-0 bg-gray-300 focus:outline-none" | ||
name="Outlined" | ||
placeholder="Follow up..." | ||
rows={1} | ||
// eslint-disable-next-line jsx-a11y/no-autofocus | ||
autoFocus | ||
style={{ | ||
backgroundColor: 'rgba(255, 255, 255, 0)', | ||
color: 'rgb(212 212 212)', | ||
border: 'none', | ||
}} | ||
onInput={(e) => { | ||
const target = e.target as HTMLTextAreaElement // Prevent TS inferring type error | ||
target.style.height = 'auto' | ||
target.style.height = `${Math.min(target.scrollHeight, 160)}px` | ||
}} | ||
/> | ||
<div className="absolute right-3 top-1/2 -translate-y-1/2"> | ||
<PiPaperPlaneRight | ||
color={userTextFieldInput && loadingState !== 'idle' ? 'white' : 'gray'} | ||
onClick={userTextFieldInput ? handleSubmitNewMessage : undefined} | ||
className={userTextFieldInput ? 'cursor-pointer' : ''} | ||
/> | ||
</div> | ||
<div className=" flex w-full "> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. syntax: Extra space in className string (' flex' and trailing space) |
||
<div className="z-50 flex w-full flex-col overflow-hidden rounded border-2 border-solid border-border bg-background focus-within:ring-1 focus-within:ring-ring"> | ||
<textarea | ||
value={userTextFieldInput} | ||
onKeyDown={(e) => { | ||
if (!e.shiftKey && e.key === 'Enter') { | ||
e.preventDefault() | ||
handleSubmitNewMessage() | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. logic: Submit message is now triggered even when input is empty, unlike previous version which checked userTextFieldInput |
||
}} | ||
className="h-[100px] w-[600px] resize-none border-0 bg-transparent p-4 text-foreground caret-current focus:outline-none" | ||
placeholder="What can Reor help you with today?" | ||
onChange={(e) => setUserTextFieldInput(e.target.value)} | ||
// eslint-disable-next-line jsx-a11y/no-autofocus | ||
autoFocus | ||
/> | ||
<div className="mx-auto h-px w-[96%] bg-background/20" /> | ||
<div className="flex h-10 flex-col items-center justify-between gap-2 py-2 md:flex-row md:gap-4"> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. syntax: Extra space in gap-2 py-2 |
||
<div className="flex flex-col items-center justify-between rounded-md border-0 py-2 md:flex-row"> | ||
<LLMSelectOrButton selectedLLM={selectedLLM} setSelectedLLM={setSelectedLLM} /> | ||
</div> | ||
<div className="flex items-center"> | ||
<Button | ||
className="m-2 flex items-center justify-between gap-2 bg-transparent text-primary hover:bg-transparent hover:text-accent-foreground" | ||
onClick={handleSubmitNewMessage} | ||
disabled={loadingState !== 'idle'} | ||
> | ||
<PiPaperPlaneRight className="size-4" /> | ||
</Button> | ||
</div> | ||
</div> | ||
</div> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,6 +7,8 @@ import AssistantMessage from './MessageComponents/AssistantMessage' | |
import SystemMessage from './MessageComponents/SystemMessage' | ||
import ChatSources from './MessageComponents/ChatSources' | ||
import LoadingDots from '@/lib/animations' | ||
import useLLMConfigs from '@/lib/hooks/use-llm-configs' | ||
import useAgentConfig from '@/lib/hooks/use-agent-configs' | ||
|
||
interface MessageProps { | ||
message: ReorChatMessage | ||
|
@@ -41,7 +43,7 @@ interface ChatMessagesProps { | |
currentChat: Chat | undefined | ||
setCurrentChat: React.Dispatch<React.SetStateAction<Chat | undefined>> | ||
loadingState: LoadingState | ||
handleNewChatMessage: (userTextFieldInput?: string, agentConfig?: AgentConfig) => void | ||
handleNewChatMessage: (llmName: string, userTextFieldInput?: string, agentConfig?: AgentConfig) => void | ||
} | ||
|
||
const ChatMessages: React.FC<ChatMessagesProps> = ({ | ||
|
@@ -50,11 +52,18 @@ const ChatMessages: React.FC<ChatMessagesProps> = ({ | |
handleNewChatMessage, | ||
loadingState, | ||
}) => { | ||
const { agentConfig } = useAgentConfig() | ||
const [userTextFieldInput, setUserTextFieldInput] = useState<string | undefined>() | ||
const { defaultLLM, setDefaultLLM } = useLLMConfigs() | ||
const [selectedLLM, setSelectedLLM] = useState<string>() | ||
const [shouldAutoScroll, setShouldAutoScroll] = useState(true) | ||
const chatContainerRef = useRef<HTMLDivElement>(null) | ||
const lastMessageRef = useRef<HTMLDivElement>(null) | ||
|
||
useEffect(() => { | ||
setSelectedLLM(defaultLLM) | ||
}, [defaultLLM]) | ||
|
||
const scrollToBottom = useCallback(() => { | ||
if (chatContainerRef.current) { | ||
const { scrollHeight, clientHeight } = chatContainerRef.current | ||
|
@@ -78,13 +87,11 @@ const ChatMessages: React.FC<ChatMessagesProps> = ({ | |
|
||
const handleSubmitNewMessage = async () => { | ||
if (userTextFieldInput) { | ||
// this for v1 could just use the default agent config... | ||
const agentConfigs = await window.electronStore.getAgentConfigs() | ||
if (agentConfigs && agentConfigs.length > 0) { | ||
handleNewChatMessage(userTextFieldInput, agentConfigs[0]) | ||
} else { | ||
handleNewChatMessage(userTextFieldInput) | ||
if (!selectedLLM) { | ||
throw new Error('Select an LLM.') | ||
} | ||
Comment on lines
88
to
92
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. logic: Throwing an error directly will crash the UI. Should handle this gracefully with toast/alert instead. |
||
setDefaultLLM(selectedLLM) | ||
handleNewChatMessage(selectedLLM, userTextFieldInput, agentConfig) | ||
Comment on lines
+93
to
+94
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. logic: setDefaultLLM is async but not awaited, could cause race conditions with message sending |
||
setUserTextFieldInput('') | ||
setShouldAutoScroll(true) | ||
} | ||
|
@@ -134,6 +141,8 @@ const ChatMessages: React.FC<ChatMessagesProps> = ({ | |
setUserTextFieldInput={setUserTextFieldInput} | ||
handleSubmitNewMessage={handleSubmitNewMessage} | ||
loadingState={loadingState} | ||
selectedLLM={selectedLLM} | ||
setSelectedLLM={setSelectedLLM} | ||
/> | ||
</div> | ||
</div> | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
syntax: unnecessary trailing whitespace after ToastContainer closing tag