mirror of
https://github.com/aljazceru/goose.git
synced 2025-12-19 07:04:21 +01:00
feat: remove the disable state from chat input box (#1341)
This commit is contained in:
@@ -193,12 +193,7 @@ export default function ChatView({ setView }: { setView: (view: View) => void })
|
|||||||
|
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
{isLoading && <LoadingGoose />}
|
{isLoading && <LoadingGoose />}
|
||||||
<Input
|
<Input handleSubmit={handleSubmit} isLoading={isLoading} onStop={onStopGoose} />
|
||||||
handleSubmit={handleSubmit}
|
|
||||||
disabled={isLoading}
|
|
||||||
isLoading={isLoading}
|
|
||||||
onStop={onStopGoose}
|
|
||||||
/>
|
|
||||||
<BottomMenu hasMessages={hasMessages} setView={setView} />
|
<BottomMenu hasMessages={hasMessages} setView={setView} />
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
|
|||||||
@@ -5,27 +5,21 @@ import { Attach, Send } from './icons';
|
|||||||
|
|
||||||
interface InputProps {
|
interface InputProps {
|
||||||
handleSubmit: (e: React.FormEvent) => void;
|
handleSubmit: (e: React.FormEvent) => void;
|
||||||
disabled?: boolean;
|
|
||||||
isLoading?: boolean;
|
isLoading?: boolean;
|
||||||
onStop?: () => void;
|
onStop?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function Input({
|
export default function Input({ handleSubmit, isLoading = false, onStop }: InputProps) {
|
||||||
handleSubmit,
|
|
||||||
disabled = false,
|
|
||||||
isLoading = false,
|
|
||||||
onStop,
|
|
||||||
}: InputProps) {
|
|
||||||
const [value, setValue] = useState('');
|
const [value, setValue] = useState('');
|
||||||
// State to track if the IME is composing (i.e., in the middle of Japanese IME input)
|
// State to track if the IME is composing (i.e., in the middle of Japanese IME input)
|
||||||
const [isComposing, setIsComposing] = useState(false);
|
const [isComposing, setIsComposing] = useState(false);
|
||||||
const textAreaRef = useRef<HTMLTextAreaElement>(null);
|
const textAreaRef = useRef<HTMLTextAreaElement>(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (textAreaRef.current && !disabled) {
|
if (textAreaRef.current) {
|
||||||
textAreaRef.current.focus();
|
textAreaRef.current.focus();
|
||||||
}
|
}
|
||||||
}, [disabled, value]);
|
}, [value]);
|
||||||
|
|
||||||
const useAutosizeTextArea = (textAreaRef: HTMLTextAreaElement | null, value: string) => {
|
const useAutosizeTextArea = (textAreaRef: HTMLTextAreaElement | null, value: string) => {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -57,10 +51,19 @@ export default function Input({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleKeyDown = (evt: React.KeyboardEvent<HTMLTextAreaElement>) => {
|
const handleKeyDown = (evt: React.KeyboardEvent<HTMLTextAreaElement>) => {
|
||||||
// Only trigger submit on Enter if not composing (IME input in progress) and shift is not pressed
|
if (evt.key === 'Enter') {
|
||||||
if (evt.key === 'Enter' && !evt.shiftKey && !isComposing) {
|
// should not trigger submit on Enter if it's composing (IME input in progress) or shift is pressed
|
||||||
|
if (evt.shiftKey || isComposing) {
|
||||||
|
// Allow line break for Shift+Enter or during IME composition
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prevent default Enter behavior when loading or when not loading but has content
|
||||||
|
// So it won't trigger a new line
|
||||||
evt.preventDefault();
|
evt.preventDefault();
|
||||||
if (value.trim()) {
|
|
||||||
|
// Only submit if not loading and has content
|
||||||
|
if (!isLoading && value.trim()) {
|
||||||
handleSubmit(new CustomEvent('submit', { detail: { value } }));
|
handleSubmit(new CustomEvent('submit', { detail: { value } }));
|
||||||
setValue('');
|
setValue('');
|
||||||
}
|
}
|
||||||
@@ -69,7 +72,7 @@ export default function Input({
|
|||||||
|
|
||||||
const onFormSubmit = (e: React.FormEvent) => {
|
const onFormSubmit = (e: React.FormEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
if (value.trim()) {
|
if (value.trim() && !isLoading) {
|
||||||
handleSubmit(new CustomEvent('submit', { detail: { value } }));
|
handleSubmit(new CustomEvent('submit', { detail: { value } }));
|
||||||
setValue('');
|
setValue('');
|
||||||
}
|
}
|
||||||
@@ -97,7 +100,6 @@ export default function Input({
|
|||||||
onCompositionStart={handleCompositionStart}
|
onCompositionStart={handleCompositionStart}
|
||||||
onCompositionEnd={handleCompositionEnd}
|
onCompositionEnd={handleCompositionEnd}
|
||||||
onKeyDown={handleKeyDown}
|
onKeyDown={handleKeyDown}
|
||||||
disabled={disabled}
|
|
||||||
ref={textAreaRef}
|
ref={textAreaRef}
|
||||||
rows={1}
|
rows={1}
|
||||||
style={{
|
style={{
|
||||||
@@ -105,19 +107,14 @@ export default function Input({
|
|||||||
maxHeight: `${maxHeight}px`,
|
maxHeight: `${maxHeight}px`,
|
||||||
overflowY: 'auto',
|
overflowY: 'auto',
|
||||||
}}
|
}}
|
||||||
className={`w-full outline-none border-none focus:ring-0 bg-transparent p-0 text-base resize-none text-textStandard ${
|
className="w-full outline-none border-none focus:ring-0 bg-transparent p-0 text-base resize-none text-textStandard"
|
||||||
disabled ? 'cursor-not-allowed opacity-50' : ''
|
|
||||||
}`}
|
|
||||||
/>
|
/>
|
||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
size="icon"
|
size="icon"
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
onClick={handleFileSelect}
|
onClick={handleFileSelect}
|
||||||
disabled={disabled}
|
className="absolute right-[40px] top-1/2 -translate-y-1/2 text-textSubtle hover:text-textStandard"
|
||||||
className={`absolute right-[40px] top-1/2 -translate-y-1/2 text-textSubtle hover:text-textStandard ${
|
|
||||||
disabled ? 'text-textSubtle cursor-not-allowed' : ''
|
|
||||||
}`}
|
|
||||||
>
|
>
|
||||||
<Attach />
|
<Attach />
|
||||||
</Button>
|
</Button>
|
||||||
@@ -126,7 +123,11 @@ export default function Input({
|
|||||||
type="button"
|
type="button"
|
||||||
size="icon"
|
size="icon"
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
onClick={onStop}
|
onClick={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
onStop();
|
||||||
|
}}
|
||||||
className="absolute right-2 top-1/2 -translate-y-1/2 [&_svg]:size-5 text-textSubtle hover:text-textStandard"
|
className="absolute right-2 top-1/2 -translate-y-1/2 [&_svg]:size-5 text-textSubtle hover:text-textStandard"
|
||||||
>
|
>
|
||||||
<Stop size={24} />
|
<Stop size={24} />
|
||||||
@@ -136,9 +137,9 @@ export default function Input({
|
|||||||
type="submit"
|
type="submit"
|
||||||
size="icon"
|
size="icon"
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
disabled={disabled || !value.trim()}
|
disabled={!value.trim()}
|
||||||
className={`absolute right-2 top-1/2 -translate-y-1/2 text-textSubtle hover:text-textStandard ${
|
className={`absolute right-2 top-1/2 -translate-y-1/2 text-textSubtle hover:text-textStandard ${
|
||||||
disabled || !value.trim() ? 'text-textSubtle cursor-not-allowed' : ''
|
!value.trim() ? 'text-textSubtle cursor-not-allowed' : ''
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<Send />
|
<Send />
|
||||||
|
|||||||
Reference in New Issue
Block a user