diff --git a/web-app/src/containers/ChatInput.tsx b/web-app/src/containers/ChatInput.tsx index 1ed69df96..24b1bf57c 100644 --- a/web-app/src/containers/ChatInput.tsx +++ b/web-app/src/containers/ChatInput.tsx @@ -16,6 +16,7 @@ import { IconCodeCircle2, IconPlayerStopFilled, IconBrandSpeedtest, + IconX, } from '@tabler/icons-react' import { useTranslation } from 'react-i18next' import { useGeneralSetting } from '@/hooks/useGeneralSetting' @@ -56,8 +57,16 @@ const ChatInput = ({ const { selectedModel } = useModelProvider() const { sendMessage } = useChat() + const [message, setMessage] = useState('') - console.log(model) + const handleSendMesage = (prompt: string) => { + if (!selectedModel) { + setMessage('Please select a model to start chatting.') + return + } + setMessage('') + sendMessage(prompt) + } useEffect(() => { const handleFocusIn = () => { @@ -130,154 +139,173 @@ const ChatInput = ({ return (
-
- {streamingContent && ( -
- -
- -
- )} +
- { - setPrompt(e.target.value) - // Count the number of newlines to estimate rows - const newRows = (e.target.value.match(/\n/g) || []).length + 1 - setRows(Math.min(newRows, maxRows)) - }} - onKeyDown={(e) => { - if (e.key === 'Enter' && !e.shiftKey && prompt) { - e.preventDefault() - // Submit the message when Enter is pressed without Shift - sendMessage(prompt) - // When Shift+Enter is pressed, a new line is added (default behavior) - } - }} - placeholder={t('common.placeholder.chatInput')} - autoFocus - spellCheck={spellCheckChatInput} - data-gramm={spellCheckChatInput} - data-gramm_editor={spellCheckChatInput} - data-gramm_grammarly={spellCheckChatInput} + {streamingContent && ( +
+ +
+ +
+ )} +
-
-
-
-
-
-
+ { + setPrompt(e.target.value) + // Count the number of newlines to estimate rows + const newRows = (e.target.value.match(/\n/g) || []).length + 1 + setRows(Math.min(newRows, maxRows)) + }} + onKeyDown={(e) => { + if (e.key === 'Enter' && !e.shiftKey && prompt) { + e.preventDefault() + // Submit the message when Enter is pressed without Shift + handleSendMesage(prompt) + // When Shift+Enter is pressed, a new line is added (default behavior) + } + }} + placeholder={t('common.placeholder.chatInput')} + autoFocus + spellCheck={spellCheckChatInput} + data-gramm={spellCheckChatInput} + data-gramm_editor={spellCheckChatInput} + data-gramm_grammarly={spellCheckChatInput} className={cn( - 'px-1 flex items-center gap-1', - streamingContent && 'opacity-50 pointer-events-none' - )} - > - {model?.provider === 'llama.cpp' && loadingModel ? ( - - ) : ( - + 'bg-transparent pt-4 w-full flex-shrink-0 border-none resize-none outline-0 px-4', + rows < maxRows && 'scrollbar-hide', + className )} + /> +
+
- {/* File attachment - always available */} -
- -
+
+
+
+
+ {model?.provider === 'llama.cpp' && loadingModel ? ( + + ) : ( + + )} - {/* Microphone - always available - Temp Hide */} - {/*
+ {/* File attachment - always available */} +
+ +
+ + {/* Microphone - always available - Temp Hide */} + {/*
*/} - {selectedModel?.capabilities?.includes('vision') && ( -
- -
- )} + {selectedModel?.capabilities?.includes('vision') && ( +
+ +
+ )} - {selectedModel?.capabilities?.includes('embeddings') && ( -
- -
- )} + {selectedModel?.capabilities?.includes('embeddings') && ( +
+ +
+ )} - {selectedModel?.capabilities?.includes('tools') && ( -
- -
- )} + {selectedModel?.capabilities?.includes('tools') && ( +
+ +
+ )} - {selectedModel?.capabilities?.includes('web_search') && ( -
- -
- )} + {selectedModel?.capabilities?.includes('web_search') && ( +
+ +
+ )} - {selectedModel?.capabilities?.includes('reasoning') && ( -
- + {selectedModel?.capabilities?.includes('reasoning') && ( +
+ +
+ )} +
+ + {showSpeedToken && ( +
+ + + {Math.round(tokenSpeed?.tokenSpeed ?? 0)} tokens/sec +
)}
- {showSpeedToken && ( -
- - - {Math.round(tokenSpeed?.tokenSpeed ?? 0)} tokens/sec - -
+ {streamingContent ? ( + + ) : ( + )}
- - {streamingContent ? ( - - ) : ( - - )}
+ {message && !selectedModel && ( +
+
+ {message} + { + setMessage('') + }} + /> +
+
+ )}
) }