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": {
"Gemini": {
"DefaultModel": "gemini/gemini-3-flash-preview"
"DefaultModel": "gemini-3-flash-preview"
},
"OpenAI": {
"DefaultModel": "gpt-4o"

View File

@@ -31,6 +31,9 @@ function AiChat({ onClose }: AiChatProps): JSX.Element {
const [provider, setProvider] = useState<string>('auto')
const [availableProviders, setAvailableProviders] = useState<string[]>([])
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 { apiUrl, userToken } = useApiUrlStore()
@@ -66,6 +69,11 @@ function AiChat({ onClose }: AiChatProps): JSX.Element {
timestamp: new Date()
}
// Add to message history
setMessageHistory(prev => [...prev, input.trim()])
setHistoryIndex(-1)
setTempInput('')
setMessages(prev => [...prev, userMessage])
setInput('')
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) {
e.preventDefault()
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">
<textarea
value={input}
onChange={(e) => setInput(e.target.value)}
onKeyPress={handleKeyPress}
onChange={(e) => {
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..."
className="textarea textarea-bordered flex-1 resize-none"
rows={2}