diff --git a/src/renderer/src/hooks/useModel.ts b/src/renderer/src/hooks/useModel.ts new file mode 100644 index 00000000..05b164e3 --- /dev/null +++ b/src/renderer/src/hooks/useModel.ts @@ -0,0 +1,7 @@ +import { useProviders } from './useProvider' + +export function useModel(id?: string) { + const { providers } = useProviders() + const allModels = providers.map((p) => p.models).flat() + return allModels.find((m) => m.id === id) +} diff --git a/src/renderer/src/i18n/index.ts b/src/renderer/src/i18n/index.ts index a996ca78..ead15a5b 100644 --- a/src/renderer/src/i18n/index.ts +++ b/src/renderer/src/i18n/index.ts @@ -77,6 +77,7 @@ const resources = { 'input.send': 'Send', 'input.pause': 'Pause', 'input.settings': 'Settings', + 'input.upload': 'Upload image png、jpg、jpeg', 'input.context_count.tip': 'Context Count', 'input.estimated_tokens.tip': 'Estimated tokens', 'settings.temperature': 'Temperature', @@ -314,6 +315,7 @@ const resources = { 'input.send': '发送', 'input.pause': '暂停', 'input.settings': '设置', + 'input.upload': '上传图片 png、jpg、jpeg', 'input.context_count.tip': '上下文数', 'input.estimated_tokens.tip': '预估 token 数', 'settings.temperature': '模型温度', diff --git a/src/renderer/src/pages/home/Inputbar/AttachmentButton.tsx b/src/renderer/src/pages/home/Inputbar/AttachmentButton.tsx new file mode 100644 index 00000000..db805eab --- /dev/null +++ b/src/renderer/src/pages/home/Inputbar/AttachmentButton.tsx @@ -0,0 +1,45 @@ +import { PaperClipOutlined } from '@ant-design/icons' +import { Tooltip, Upload } from 'antd' +import { FC } from 'react' +import { useTranslation } from 'react-i18next' + +interface Props { + images: string[] + setImages: (images: string[]) => void + ToolbarButton: any +} + +const AttachmentButton: FC = ({ images, setImages, ToolbarButton }) => { + const { t } = useTranslation() + + return ( + + {}} + accept="image/*" + itemRender={() => null} + maxCount={1} + onChange={async ({ file }) => { + try { + const _file = file.originFileObj as File + const reader = new FileReader() + reader.onload = (e: ProgressEvent) => { + const result = e.target?.result + if (typeof result === 'string') { + setImages([result]) + } + } + reader.readAsDataURL(_file) + } catch (error: any) { + window.message.error(error.message) + } + }}> + + + + + + ) +} + +export default AttachmentButton diff --git a/src/renderer/src/pages/home/Inputbar/Inputbar.tsx b/src/renderer/src/pages/home/Inputbar/Inputbar.tsx index a43f4e52..ad953359 100644 --- a/src/renderer/src/pages/home/Inputbar/Inputbar.tsx +++ b/src/renderer/src/pages/home/Inputbar/Inputbar.tsx @@ -26,6 +26,7 @@ import { FC, useCallback, useEffect, useMemo, useRef, useState } from 'react' import { useTranslation } from 'react-i18next' import styled from 'styled-components' +import AttachmentButton from './AttachmentButton' import SendMessageButton from './SendMessageButton' interface Props { @@ -44,6 +45,7 @@ const Inputbar: FC = ({ assistant, setActiveTopic }) => { const [estimateTokenCount, setEstimateTokenCount] = useState(0) const generating = useAppSelector((state) => state.runtime.generating) const inputRef = useRef(null) + const [images, setImages] = useState([]) const { t } = useTranslation() _text = text @@ -67,13 +69,18 @@ const Inputbar: FC = ({ assistant, setActiveTopic }) => { status: 'success' } + if (images.length > 0) { + message.images = images + } + EventEmitter.emit(EVENT_NAMES.SEND_MESSAGE, message) setText('') + setImages([]) setTimeout(() => setText(''), 500) setExpend(false) - }, [assistant.id, assistant.topics, generating, text]) + }, [assistant.id, assistant.topics, generating, images, text]) const inputTokenCount = useMemo(() => estimateInputTokenCount(text), [text]) @@ -153,6 +160,20 @@ const Inputbar: FC = ({ assistant, setActiveTopic }) => { id="inputbar" style={{ minHeight: expended ? '60%' : 'var(--input-bar-height)' }} className={inputFocus ? 'focus' : ''}> +