mirror of
https://github.com/voideditor/void
synced 2026-05-24 09:58:23 +00:00
inputbox ref is now an internal widget (and works better!)
This commit is contained in:
parent
86294c676a
commit
18e3f19512
2 changed files with 71 additions and 41 deletions
|
|
@ -1,36 +1,59 @@
|
|||
// import { useEffect, useRef } from 'react'
|
||||
// import { HistoryInputBox } from '../../../../../../../base/browser/ui/inputbox/inputBox.js'
|
||||
// import { useService } from '../util/services.js'
|
||||
// import { defaultInputBoxStyles } from '../../../../../../../platform/theme/browser/defaultStyles.js'
|
||||
import React, { useEffect, useRef } from 'react';
|
||||
import { useService } from '../util/services.js';
|
||||
import { HistoryInputBox } from '../../../../../../../base/browser/ui/inputbox/inputBox.js';
|
||||
import { defaultInputBoxStyles } from '../../../../../../../platform/theme/browser/defaultStyles.js';
|
||||
|
||||
// export const InputBox = ({ onChangeText, placeholder, className }: { onChangeText: (value: string) => void, placeholder: string, className: string }) => {
|
||||
export const InputBox = ({ onChangeText, placeholder, historyInputBoxRef, }: {
|
||||
onChangeText: (value: string) => void;
|
||||
placeholder: string;
|
||||
historyInputBoxRef: React.MutableRefObject<HistoryInputBox | null>; // update this whenever historyInputBoxRef.current changes
|
||||
}) => {
|
||||
const contextViewProvider = useService('contextViewService');
|
||||
|
||||
// const domNodeRef = useRef<HTMLDivElement | null>(null)
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
// const contextViewProvider = useService('contextViewService')
|
||||
useEffect(() => {
|
||||
if (!containerRef.current) return;
|
||||
|
||||
// create and mount the HistoryInputBox
|
||||
historyInputBoxRef.current = new HistoryInputBox(
|
||||
containerRef.current,
|
||||
contextViewProvider,
|
||||
{
|
||||
inputBoxStyles: {
|
||||
...defaultInputBoxStyles,
|
||||
inputBackground: 'transparent',
|
||||
},
|
||||
placeholder,
|
||||
history: [],
|
||||
flexibleHeight: true,
|
||||
flexibleMaxHeight: 500,
|
||||
flexibleWidth: false,
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
// useEffect(() => {
|
||||
historyInputBoxRef.current.onDidChange((newStr) => {
|
||||
onChangeText(newStr)
|
||||
})
|
||||
|
||||
// const htmlNode = domNodeRef.current
|
||||
// if (!htmlNode) return
|
||||
// historyInputBoxRef.current.onDidHeightChange((newHeight) => {
|
||||
// console.log('CHANGE height', newHeight);
|
||||
// })
|
||||
|
||||
// cleanup
|
||||
return () => {
|
||||
if (historyInputBoxRef.current) {
|
||||
historyInputBoxRef.current.dispose();
|
||||
if (containerRef.current) {
|
||||
while (containerRef.current.firstChild) {
|
||||
containerRef.current.removeChild(containerRef.current.firstChild);
|
||||
}
|
||||
}
|
||||
historyInputBoxRef.current = null;
|
||||
}
|
||||
};
|
||||
}, [onChangeText, placeholder, contextViewProvider]); // Empty dependency array since we only want to mount/unmount once
|
||||
|
||||
// console.log('creating inputbox')
|
||||
// const widget = new HistoryInputBox(htmlNode, contextViewProvider, {
|
||||
// inputBoxStyles: defaultInputBoxStyles,
|
||||
// placeholder,
|
||||
// history: [],
|
||||
// })
|
||||
|
||||
|
||||
// widget.onDidChange((newStr) => { onChangeText(newStr) })
|
||||
|
||||
// return () => {
|
||||
// console.log('disposing inputbox')
|
||||
// widget.dispose()
|
||||
// }
|
||||
// }, [onChangeText, contextViewProvider, placeholder])
|
||||
|
||||
// return <div ref={domNodeRef}className={className}/>
|
||||
// }
|
||||
return <div ref={containerRef} className="w-full" />;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@ import { IDisposable } from '../../../../../../../base/common/lifecycle.js';
|
|||
import { ErrorDisplay } from './ErrorDisplay.js';
|
||||
import { LLMMessageServiceParams } from '../../../../../../../platform/void/common/llmMessageTypes.js';
|
||||
import { getCmdKey } from '../../../getCmdKey.js'
|
||||
import { InputBox } from './InputBox.js';
|
||||
import { HistoryInputBox } from '../../../../../../../base/browser/ui/inputbox/inputBox.js';
|
||||
|
||||
// read files from VSCode
|
||||
const VSReadFile = async (modelService: IModelService, uri: URI): Promise<string | null> => {
|
||||
|
|
@ -147,8 +149,6 @@ export const SidebarChat = () => {
|
|||
const threadsStateService = useService('threadsStateService')
|
||||
|
||||
// ----- SIDEBAR CHAT state (local) -----
|
||||
// state of current message
|
||||
const [instructions, setInstructions] = useState('') // the user's instructions
|
||||
|
||||
// state of chat
|
||||
const [messageStream, setMessageStream] = useState<string | null>(null)
|
||||
|
|
@ -159,9 +159,14 @@ export const SidebarChat = () => {
|
|||
|
||||
const sendLLMMessageService = useService('sendLLMMessageService')
|
||||
|
||||
const isDisabled = !instructions
|
||||
|
||||
// state of current message
|
||||
const [instructions, setInstructions] = useState('') // the user's instructions
|
||||
const onChangeText = useCallback((newStr: string) => { setInstructions(newStr) }, [setInstructions])
|
||||
const isDisabled = !instructions
|
||||
const formRef = useRef<HTMLFormElement | null>(null)
|
||||
const inputBoxRef: React.MutableRefObject<HistoryInputBox | null> = useRef(null);
|
||||
|
||||
const onSubmit = async (e: FormEvent<HTMLFormElement>) => {
|
||||
|
||||
e.preventDefault()
|
||||
|
|
@ -223,8 +228,10 @@ export const SidebarChat = () => {
|
|||
|
||||
|
||||
setIsLoading(true)
|
||||
setInstructions('');
|
||||
formRef.current?.reset(); // reset the form's text when clear instructions or unexpected behavior happens
|
||||
if (inputBoxRef.current) {
|
||||
inputBoxRef.current.value = ''; // this triggers onDidChangeText
|
||||
inputBoxRef.current.blur();
|
||||
}
|
||||
threadsStateService.setStaging([]) // clear staging
|
||||
setLatestError(null)
|
||||
|
||||
|
|
@ -257,7 +264,7 @@ export const SidebarChat = () => {
|
|||
<ChatBubble key={i} chatMessage={message} />
|
||||
)}
|
||||
{/* message stream */}
|
||||
<ChatBubble chatMessage={{ role: 'assistant', content: messageStream , displayContent: messageStream || null }} />
|
||||
<ChatBubble chatMessage={{ role: 'assistant', content: messageStream, displayContent: messageStream || null }} />
|
||||
</div>
|
||||
{/* chatbar */}
|
||||
<div className="shrink-0 py-4">
|
||||
|
|
@ -288,20 +295,20 @@ export const SidebarChat = () => {
|
|||
}}>
|
||||
|
||||
{/* input */}
|
||||
{/* <InputBox
|
||||
<InputBox
|
||||
placeholder={`${getCmdKey()}+L to select`}
|
||||
onChangeText={(newStr) => { setInstructions(newStr) }}
|
||||
className='w-full p-2 leading-tight resize-none max-h-[50vh] overflow-auto bg-transparent border-none !outline-none'
|
||||
/> */}
|
||||
onChangeText={onChangeText}
|
||||
historyInputBoxRef={inputBoxRef}
|
||||
/>
|
||||
|
||||
<textarea
|
||||
{/* <textarea
|
||||
ref={chatInputRef}
|
||||
placeholder={`Press ${getCmdKey()}+L to select.`}
|
||||
onChange={(e) => { setInstructions(e.target.value) }}
|
||||
className={`w-full p-2 leading-tight resize-none max-h-[50vh] overflow-auto bg-transparent border-none !outline-none`}
|
||||
placeholder={`${getCmdKey()}+L to select`}
|
||||
rows={1}
|
||||
onInput={e => { e.currentTarget.style.height = 'auto'; e.currentTarget.style.height = e.currentTarget.scrollHeight + 'px' }} // Adjust height dynamically
|
||||
/>
|
||||
/> */}
|
||||
|
||||
{isLoading ?
|
||||
// stop button
|
||||
|
|
|
|||
Loading…
Reference in a new issue