Support paste image to input

This commit is contained in:
wong2
2023-11-09 16:59:39 +08:00
parent fffaea8a8d
commit 15f22c2019
5 changed files with 33 additions and 4 deletions

View File

@@ -78,6 +78,10 @@ export abstract class AbstractBot {
return undefined
}
get supportsImageInput() {
return false
}
abstract doSendMessage(params: SendMessageParams): Promise<void>
abstract resetConversation(): void
}
@@ -118,4 +122,8 @@ export abstract class AsyncAbstractBot extends AbstractBot {
get name() {
return this.#bot.name
}
get supportsImageInput() {
return this.#bot.supportsImageInput
}
}

View File

@@ -67,6 +67,10 @@ export class BardBot extends AbstractBot {
this.conversationContext = undefined
}
get supportsImageInput() {
return true
}
private async uploadImage(image: File) {
const headers = {
'content-type': 'application/x-www-form-urlencoded;charset=UTF-8',

View File

@@ -228,6 +228,10 @@ export class BingWebBot extends AbstractBot {
this.conversationContext = undefined
}
get supportsImageInput() {
return true
}
private async uploadImage(image: File) {
const formData = new FormData()
formData.append(

View File

@@ -13,7 +13,7 @@ import {
} from '@floating-ui/react'
import { fileOpen } from 'browser-fs-access'
import { cx } from '~/utils'
import { FC, ReactNode, memo, useCallback, useMemo, useRef, useState } from 'react'
import { ClipboardEventHandler, FC, ReactNode, memo, useCallback, useMemo, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { GoBook, GoImage } from 'react-icons/go'
import { RiDeleteBackLine } from 'react-icons/ri'
@@ -145,6 +145,19 @@ const ChatMessageInput: FC<Props> = (props) => {
inputRef.current?.focus()
}, [])
const onPaste: ClipboardEventHandler<HTMLTextAreaElement> = useCallback((event) => {
const files = event.clipboardData.files
if (!files.length) {
return
}
const imageFile = Array.from(files).find((file) => file.type.startsWith('image/'))
if (imageFile) {
event.preventDefault()
setImage(imageFile)
inputRef.current?.focus()
}
}, [])
return (
<form className={cx('flex flex-row items-center gap-3', props.className)} onSubmit={onFormSubmit} ref={formRef}>
{props.mode === 'full' && (
@@ -195,6 +208,7 @@ const ChatMessageInput: FC<Props> = (props) => {
value={value}
onValueChange={onValueChange}
autoFocus={props.autoFocus}
onPaste={props.supportImageInput ? onPaste : undefined}
/>
</div>
{props.actionButton || <Button text="-" className="invisible" size={props.mode === 'full' ? 'normal' : 'tiny'} />}

View File

@@ -13,12 +13,11 @@ import { BotId, BotInstance } from '../../bots'
import Button from '../Button'
import HistoryDialog from '../History/Dialog'
import ShareDialog from '../Share/Dialog'
import SwitchBotDropdown from '../SwitchBotDropdown'
import Tooltip from '../Tooltip'
import ChatMessageInput from './ChatMessageInput'
import ChatMessageList from './ChatMessageList'
import WebAccessCheckbox from './WebAccessCheckbox'
import ChatbotName from './ChatbotName'
import WebAccessCheckbox from './WebAccessCheckbox'
interface Props {
botId: BotId
@@ -146,7 +145,7 @@ const ConversationPanel: FC<Props> = (props) => {
placeholder={mode === 'compact' ? '' : undefined}
onSubmit={onSubmit}
autoFocus={mode === 'full'}
supportImageInput={mode === 'full' && (props.botId === 'bard' || props.botId === 'bing')}
supportImageInput={mode === 'full' && props.bot.supportsImageInput}
actionButton={inputActionButton}
/>
</div>