From be76c32f698121348137a0f049b0e3c06d1ffbcd Mon Sep 17 00:00:00 2001 From: Nate Kelley Date: Wed, 5 Mar 2025 10:36:31 -0700 Subject: [PATCH] input chat --- .../components/ui/inputs/InputTextArea.tsx | 13 +- .../ui/inputs/InputTextAreaButton.tsx | 10 +- .../NewChatProvider/useAutoAppendThought.ts | 3 - .../ChatContent/ChatInput/ChatInput.tsx | 112 +++++------------- .../ChatContent/ChatInput/useChatInputFlow.ts | 15 ++- 5 files changed, 47 insertions(+), 106 deletions(-) diff --git a/web/src/components/ui/inputs/InputTextArea.tsx b/web/src/components/ui/inputs/InputTextArea.tsx index 8745f57eb..419f915c6 100644 --- a/web/src/components/ui/inputs/InputTextArea.tsx +++ b/web/src/components/ui/inputs/InputTextArea.tsx @@ -37,6 +37,7 @@ export interface InputTextAreaProps VariantProps { autoResize?: AutoResizeOptions; onPressMetaEnter?: (e: React.KeyboardEvent) => void; + onPressEnter?: (e: React.KeyboardEvent) => void; } export const InputTextArea = React.forwardRef( @@ -49,6 +50,7 @@ export const InputTextArea = React.forwardRef) => { - if (e.key === 'Enter' && (e.metaKey || e.ctrlKey)) { - e.preventDefault(); - onPressMetaEnter?.(e); + if (e.key === 'Enter') { + if ((e.metaKey || e.ctrlKey) && onPressMetaEnter) { + e.preventDefault(); + onPressMetaEnter(e); + } else if (!e.shiftKey) { + e.preventDefault(); + onPressEnter?.(e); + } } props.onKeyDown?.(e); }); diff --git a/web/src/components/ui/inputs/InputTextAreaButton.tsx b/web/src/components/ui/inputs/InputTextAreaButton.tsx index ec9636b72..84a4b5c93 100644 --- a/web/src/components/ui/inputs/InputTextAreaButton.tsx +++ b/web/src/components/ui/inputs/InputTextAreaButton.tsx @@ -1,4 +1,4 @@ -import React, { useMemo, useRef, forwardRef } from 'react'; +import React, { useMemo, forwardRef } from 'react'; import { InputTextArea, InputTextAreaProps } from './InputTextArea'; import { cn } from '@/lib/classMerge'; import { cva } from 'class-variance-authority'; @@ -6,7 +6,6 @@ import { Button } from '../buttons/Button'; import { ArrowUp } from '../icons/NucleoIconOutlined'; import { ShapeSquare } from '../icons/NucleoIconFilled'; import { useMemoizedFn } from 'ahooks'; -import { Tooltip } from '../tooltip'; const inputTextAreaButtonVariants = cva( 'relative flex w-full items-center overflow-visible rounded-xl border border-border transition-all duration-200', @@ -53,10 +52,6 @@ export const InputTextAreaButton = forwardRef { - onSubmitPreflight(); - }); - return (
diff --git a/web/src/context/Chats/NewChatProvider/useAutoAppendThought.ts b/web/src/context/Chats/NewChatProvider/useAutoAppendThought.ts index 93a390d81..514e59b92 100644 --- a/web/src/context/Chats/NewChatProvider/useAutoAppendThought.ts +++ b/web/src/context/Chats/NewChatProvider/useAutoAppendThought.ts @@ -4,10 +4,7 @@ import type { } from '@/api/asset_interfaces'; import { useMemoizedFn } from 'ahooks'; import sample from 'lodash/sample'; -import last from 'lodash/last'; import { useBusterChatContextSelector } from '../ChatProvider'; -import { timeout } from '@/lib/timeout'; -import random from 'lodash/random'; export const useAutoAppendThought = () => { const onUpdateChatMessage = useBusterChatContextSelector((x) => x.onUpdateChatMessage); diff --git a/web/src/layouts/ChatLayout/ChatContainer/ChatContent/ChatInput/ChatInput.tsx b/web/src/layouts/ChatLayout/ChatContainer/ChatContent/ChatInput/ChatInput.tsx index 4095732c7..b926d1ea2 100644 --- a/web/src/layouts/ChatLayout/ChatContainer/ChatContent/ChatInput/ChatInput.tsx +++ b/web/src/layouts/ChatLayout/ChatContainer/ChatContent/ChatInput/ChatInput.tsx @@ -1,90 +1,57 @@ -import React, { useMemo, useRef, useState } from 'react'; -import { Input } from 'antd'; -import { createStyles } from 'antd-style'; +import React, { ChangeEvent, useMemo, useRef, useState } from 'react'; import { useMemoizedFn } from 'ahooks'; -import { inputHasText } from '@/lib'; +import { inputHasText } from '@/lib/text'; import { AIWarning } from './AIWarning'; -import { SubmitButton } from './SubmitButton'; import { useChatInputFlow } from './useChatInputFlow'; -import type { TextAreaRef } from 'antd/es/input/TextArea'; import { useChatIndividualContextSelector } from '../../../ChatContext'; +import { InputTextAreaButton } from '@/components/ui/inputs/InputTextAreaButton'; +import { cn } from '@/lib/classMerge'; -const autoSize = { minRows: 3, maxRows: 16 }; +const autoResizeConfig = { minRows: 3, maxRows: 16 }; export const ChatInput: React.FC<{}> = React.memo(({}) => { - const { styles, cx } = useStyles(); - const inputRef = useRef(null); - + const textAreaRef = useRef(null); const loading = useChatIndividualContextSelector((x) => x.isLoading); const [inputValue, setInputValue] = useState(''); - const [isFocused, setIsFocused] = useState(false); - const disableSendButton = useMemo(() => { + const disableSubmit = useMemo(() => { return !inputHasText(inputValue); }, [inputValue]); const { onSubmitPreflight } = useChatInputFlow({ - disableSendButton, + disableSubmit, inputValue, setInputValue, loading, - inputRef + textAreaRef }); - const onPressEnter = useMemoizedFn((e: React.KeyboardEvent) => { - if (e.metaKey && e.key === 'Enter') { - onSubmitPreflight(); - } - }); - - const onChangeInput = useMemoizedFn((e: React.ChangeEvent) => { + const onChange = useMemoizedFn((e: ChangeEvent) => { setInputValue(e.target.value); }); - const onBlurInput = useMemoizedFn(() => { - setIsFocused(false); - }); - - const onFocusInput = useMemoizedFn(() => { - setIsFocused(true); + const onStop = useMemoizedFn(() => { + // setInputValue(''); }); return (
-
- - -
- -
-
+
@@ -92,28 +59,3 @@ export const ChatInput: React.FC<{}> = React.memo(({}) => { }); ChatInput.displayName = 'ChatInput'; - -const useStyles = createStyles(({ token, css }) => ({ - inputCard: css` - box-shadow: 0px -10px 18px 10px ${token.colorBgContainerDisabled}; - `, - inputContainer: css` - background: ${token.colorBgBase}; - border-radius: ${token.borderRadius}px; - border: 0.5px solid ${token.colorBorder}; - transition: border-color 0.2s; - min-height: 40px; - &:hover { - border-color: ${token.colorPrimaryHover}; - } - &.focused { - border-color: ${token.colorPrimary}; - } - &.loading { - border-color: ${token.colorText}; - textarea { - background: ${token.colorBgContainerDisabled}; - } - } - ` -})); diff --git a/web/src/layouts/ChatLayout/ChatContainer/ChatContent/ChatInput/useChatInputFlow.ts b/web/src/layouts/ChatLayout/ChatContainer/ChatContent/ChatInput/useChatInputFlow.ts index 7f202ff9d..cc17619cf 100644 --- a/web/src/layouts/ChatLayout/ChatContainer/ChatContent/ChatInput/useChatInputFlow.ts +++ b/web/src/layouts/ChatLayout/ChatContainer/ChatContent/ChatInput/useChatInputFlow.ts @@ -1,22 +1,21 @@ import React, { useMemo } from 'react'; -import { useChatIndividualContextSelector } from '../../../ChatContext'; +import { useChatIndividualContextSelector } from '@/layouts/ChatLayout/ChatContext'; import { useMemoizedFn } from 'ahooks'; import { useBusterNewChatContextSelector } from '@/context/Chats'; -import type { TextAreaRef } from 'antd/es/input/TextArea'; type FlowType = 'followup-chat' | 'followup-metric' | 'followup-dashboard' | 'new'; export const useChatInputFlow = ({ - disableSendButton, + disableSubmit, inputValue, setInputValue, - inputRef, + textAreaRef, loading }: { - disableSendButton: boolean; + disableSubmit: boolean; inputValue: string; setInputValue: (value: string) => void; - inputRef: React.RefObject; + textAreaRef: React.RefObject; loading: boolean; }) => { const hasChat = useChatIndividualContextSelector((x) => x.hasChat); @@ -37,7 +36,7 @@ export const useChatInputFlow = ({ }, [hasChat, selectedFileType, selectedFileId]); const onSubmitPreflight = useMemoizedFn(async () => { - if (disableSendButton || !chatId || !currentMessageId) return; + if (disableSubmit || !chatId || !currentMessageId) return; if (loading) { onStopChat({ chatId: chatId!, messageId: currentMessageId }); @@ -76,7 +75,7 @@ export const useChatInputFlow = ({ setInputValue(''); setTimeout(() => { - inputRef.current?.focus(); + textAreaRef.current?.focus(); }, 50); });