feat: improved input bar functionality and added text insertion feature
- Improved functionality for handling text input and file uploads in the input bar. - Added functionality to insert text at cursor position in a text area.
This commit is contained in:
parent
0140ff5f6e
commit
ae4542ce68
@ -21,6 +21,7 @@ import store, { useAppDispatch, useAppSelector } from '@renderer/store'
|
|||||||
import { setGenerating, setSearching } from '@renderer/store/runtime'
|
import { setGenerating, setSearching } from '@renderer/store/runtime'
|
||||||
import { Assistant, FileType, Message, Topic } from '@renderer/types'
|
import { Assistant, FileType, Message, Topic } from '@renderer/types'
|
||||||
import { delay, getFileExtension, uuid } from '@renderer/utils'
|
import { delay, getFileExtension, uuid } from '@renderer/utils'
|
||||||
|
import { insertTextAtCursor } from '@renderer/utils/input'
|
||||||
import { Button, Popconfirm, Tooltip } from 'antd'
|
import { Button, Popconfirm, Tooltip } from 'antd'
|
||||||
import TextArea, { TextAreaRef } from 'antd/es/input/TextArea'
|
import TextArea, { TextAreaRef } from 'antd/es/input/TextArea'
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
@ -40,6 +41,7 @@ interface Props {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let _text = ''
|
let _text = ''
|
||||||
|
let _files: FileType[] = []
|
||||||
|
|
||||||
const Inputbar: FC<Props> = ({ assistant, setActiveTopic }) => {
|
const Inputbar: FC<Props> = ({ assistant, setActiveTopic }) => {
|
||||||
const [text, setText] = useState(_text)
|
const [text, setText] = useState(_text)
|
||||||
@ -60,8 +62,10 @@ const Inputbar: FC<Props> = ({ assistant, setActiveTopic }) => {
|
|||||||
|
|
||||||
const isVision = useMemo(() => isVisionModel(model), [model])
|
const isVision = useMemo(() => isVisionModel(model), [model])
|
||||||
const supportExts = useMemo(() => [...textExts, ...(isVision ? imageExts : [])], [isVision])
|
const supportExts = useMemo(() => [...textExts, ...(isVision ? imageExts : [])], [isVision])
|
||||||
|
const inputTokenCount = useMemo(() => estimateTextTokens(text), [text])
|
||||||
|
|
||||||
_text = text
|
_text = text
|
||||||
|
_files = files
|
||||||
|
|
||||||
const sendMessage = useCallback(async () => {
|
const sendMessage = useCallback(async () => {
|
||||||
if (generating) {
|
if (generating) {
|
||||||
@ -96,8 +100,6 @@ const Inputbar: FC<Props> = ({ assistant, setActiveTopic }) => {
|
|||||||
setExpend(false)
|
setExpend(false)
|
||||||
}, [assistant.id, assistant.topics, generating, files, text])
|
}, [assistant.id, assistant.topics, generating, files, text])
|
||||||
|
|
||||||
const inputTokenCount = useMemo(() => estimateTextTokens(text), [text])
|
|
||||||
|
|
||||||
const handleKeyDown = (event: React.KeyboardEvent<HTMLTextAreaElement>) => {
|
const handleKeyDown = (event: React.KeyboardEvent<HTMLTextAreaElement>) => {
|
||||||
const isEnterPressed = event.keyCode == 13
|
const isEnterPressed = event.keyCode == 13
|
||||||
|
|
||||||
@ -142,10 +144,7 @@ const Inputbar: FC<Props> = ({ assistant, setActiveTopic }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const onNewContext = () => {
|
const onNewContext = () => {
|
||||||
if (generating) {
|
if (generating) return onPause()
|
||||||
onPause()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
EventEmitter.emit(EVENT_NAMES.NEW_CONTEXT)
|
EventEmitter.emit(EVENT_NAMES.NEW_CONTEXT)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -204,22 +203,21 @@ const Inputbar: FC<Props> = ({ assistant, setActiveTopic }) => {
|
|||||||
const item = event.clipboardData?.items[0]
|
const item = event.clipboardData?.items[0]
|
||||||
if (item && item.kind === 'string' && item.type === 'text/plain') {
|
if (item && item.kind === 'string' && item.type === 'text/plain') {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
item.getAsString(async (text) => {
|
item.getAsString(async (pasteText) => {
|
||||||
if (text.length > 1500) {
|
if (pasteText.length > 1500) {
|
||||||
console.debug(item.getAsFile())
|
|
||||||
const tempFilePath = await window.api.file.create('pasted_text.txt')
|
const tempFilePath = await window.api.file.create('pasted_text.txt')
|
||||||
await window.api.file.write(tempFilePath, text)
|
await window.api.file.write(tempFilePath, pasteText)
|
||||||
const selectedFile = await window.api.file.get(tempFilePath)
|
const selectedFile = await window.api.file.get(tempFilePath)
|
||||||
selectedFile && setFiles((prevFiles) => [...prevFiles, selectedFile])
|
selectedFile && setFiles((prevFiles) => [...prevFiles, selectedFile])
|
||||||
} else {
|
} else {
|
||||||
setText((prevText) => prevText + text)
|
insertTextAtCursor({ text, pasteText, textareaRef, setText })
|
||||||
setTimeout(() => resizeTextArea(), 0)
|
setTimeout(() => resizeTextArea(), 0)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[supportExts, pasteLongTextAsFile]
|
[pasteLongTextAsFile, supportExts, text]
|
||||||
)
|
)
|
||||||
|
|
||||||
// Command or Ctrl + N create new topic
|
// Command or Ctrl + N create new topic
|
||||||
|
|||||||
31
src/renderer/src/utils/input.ts
Normal file
31
src/renderer/src/utils/input.ts
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import { TextAreaRef } from 'antd/es/input/TextArea'
|
||||||
|
import { RefObject } from 'react'
|
||||||
|
|
||||||
|
export const insertTextAtCursor = ({
|
||||||
|
text,
|
||||||
|
pasteText,
|
||||||
|
textareaRef,
|
||||||
|
setText
|
||||||
|
}: {
|
||||||
|
text: string
|
||||||
|
pasteText: string
|
||||||
|
textareaRef: RefObject<TextAreaRef>
|
||||||
|
setText: (text: string) => void
|
||||||
|
}) => {
|
||||||
|
const textarea = textareaRef.current?.resizableTextArea?.textArea
|
||||||
|
|
||||||
|
if (!textarea) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const start = textarea.selectionStart
|
||||||
|
const end = textarea.selectionEnd
|
||||||
|
const newValue = text.substring(0, start) + pasteText + text.substring(end)
|
||||||
|
|
||||||
|
setText(newValue)
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
textarea.setSelectionRange(start + pasteText.length, start + pasteText.length)
|
||||||
|
textarea.focus()
|
||||||
|
}, 0)
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user