Refactor AiChat component to enhance message history navigation and input handling

- Introduced state management for message history, allowing users to navigate through previous messages using the up and down arrow keys.
- Updated input handling to reset history index when the user types a new message, improving user experience.
- Changed the key event handler from 'onKeyPress' to 'onKeyDown' for better control over key events during message input.
- Adjusted appsettings.json to simplify the default model configuration for Gemini integration.
This commit is contained in:
2026-01-06 22:53:58 +07:00
parent 2814d67c58
commit b7b4f1d12f
2 changed files with 68 additions and 4 deletions

View File

@@ -28,7 +28,7 @@
}, },
"Llm": { "Llm": {
"Gemini": { "Gemini": {
"DefaultModel": "gemini/gemini-3-flash-preview" "DefaultModel": "gemini-3-flash-preview"
}, },
"OpenAI": { "OpenAI": {
"DefaultModel": "gpt-4o" "DefaultModel": "gpt-4o"

View File

@@ -31,6 +31,9 @@ function AiChat({ onClose }: AiChatProps): JSX.Element {
const [provider, setProvider] = useState<string>('auto') const [provider, setProvider] = useState<string>('auto')
const [availableProviders, setAvailableProviders] = useState<string[]>([]) const [availableProviders, setAvailableProviders] = useState<string[]>([])
const [currentProgress, setCurrentProgress] = useState<LlmProgressUpdate | null>(null) const [currentProgress, setCurrentProgress] = useState<LlmProgressUpdate | null>(null)
const [messageHistory, setMessageHistory] = useState<string[]>([])
const [historyIndex, setHistoryIndex] = useState<number>(-1)
const [tempInput, setTempInput] = useState<string>('')
const messagesEndRef = useRef<HTMLDivElement>(null) const messagesEndRef = useRef<HTMLDivElement>(null)
const { apiUrl, userToken } = useApiUrlStore() const { apiUrl, userToken } = useApiUrlStore()
@@ -66,6 +69,11 @@ function AiChat({ onClose }: AiChatProps): JSX.Element {
timestamp: new Date() timestamp: new Date()
} }
// Add to message history
setMessageHistory(prev => [...prev, input.trim()])
setHistoryIndex(-1)
setTempInput('')
setMessages(prev => [...prev, userMessage]) setMessages(prev => [...prev, userMessage])
setInput('') setInput('')
setIsLoading(true) setIsLoading(true)
@@ -167,10 +175,54 @@ function AiChat({ onClose }: AiChatProps): JSX.Element {
} }
} }
const handleKeyPress = (e: React.KeyboardEvent<HTMLTextAreaElement>) => { const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
// Handle Enter key
if (e.key === 'Enter' && !e.shiftKey) { if (e.key === 'Enter' && !e.shiftKey) {
e.preventDefault() e.preventDefault()
sendMessage() sendMessage()
return
}
// Handle Up arrow - navigate backward through history
if (e.key === 'ArrowUp') {
e.preventDefault()
if (messageHistory.length === 0) return
// If we're at the beginning (no history navigation yet), save current input
if (historyIndex === -1) {
setTempInput(input)
}
// Navigate backward
const newIndex = historyIndex === -1
? messageHistory.length - 1
: Math.max(0, historyIndex - 1)
setHistoryIndex(newIndex)
setInput(messageHistory[newIndex])
return
}
// Handle Down arrow - navigate forward through history
if (e.key === 'ArrowDown') {
e.preventDefault()
if (messageHistory.length === 0) return
// If we're at the last message, clear input and reset
if (historyIndex >= messageHistory.length - 1) {
setHistoryIndex(-1)
setInput(tempInput)
setTempInput('')
return
}
// Navigate forward
const newIndex = historyIndex + 1
setHistoryIndex(newIndex)
setInput(messageHistory[newIndex])
return
} }
} }
@@ -261,8 +313,20 @@ function AiChat({ onClose }: AiChatProps): JSX.Element {
<div className="flex gap-2"> <div className="flex gap-2">
<textarea <textarea
value={input} value={input}
onChange={(e) => setInput(e.target.value)} onChange={(e) => {
onKeyPress={handleKeyPress} const newValue = e.target.value
setInput(newValue)
// Reset history index if user manually types something different
if (historyIndex !== -1) {
const currentHistoryItem = messageHistory[historyIndex]
if (newValue !== currentHistoryItem) {
setHistoryIndex(-1)
setTempInput('')
}
}
}}
onKeyDown={handleKeyDown}
placeholder="Ask me anything about your backtests..." placeholder="Ask me anything about your backtests..."
className="textarea textarea-bordered flex-1 resize-none" className="textarea textarea-bordered flex-1 resize-none"
rows={2} rows={2}