feat: support clipboard images in mini assistant

This commit is contained in:
who is 2025-12-10 00:44:38 +00:00
parent 7507443d8b
commit 4a7986f041
2 changed files with 35 additions and 4 deletions

View File

@ -7,12 +7,14 @@ import i18n from '@renderer/i18n'
import { fetchChatCompletion } from '@renderer/services/ApiService'
import { getDefaultTopic } from '@renderer/services/AssistantService'
import { ConversationService } from '@renderer/services/ConversationService'
import FileManager from '@renderer/services/FileManager'
import { getAssistantMessage, getUserMessage } from '@renderer/services/MessagesService'
import PasteService from '@renderer/services/PasteService'
import store, { useAppSelector } from '@renderer/store'
import { updateOneBlock, upsertManyBlocks, upsertOneBlock } from '@renderer/store/messageBlock'
import { newMessagesActions, selectMessagesForTopic } from '@renderer/store/newMessage'
import { cancelThrottledBlockUpdate, throttledBlockUpdate } from '@renderer/store/thunk/messageThunk'
import type { Topic } from '@renderer/types'
import type { FileMetadata, Topic } from '@renderer/types'
import { ThemeMode } from '@renderer/types'
import type { Chunk } from '@renderer/types/chunk'
import { ChunkType } from '@renderer/types/chunk'
@ -51,6 +53,7 @@ const HomeWindow: FC<{ draggable?: boolean }> = ({ draggable = true }) => {
const [isFirstMessage, setIsFirstMessage] = useState(true)
const [userInputText, setUserInputText] = useState('')
const [files, setFiles] = useState<FileMetadata[]>([])
const [clipboardText, setClipboardText] = useState('')
const lastClipboardTextRef = useRef<string | null>(null)
@ -73,6 +76,8 @@ const HomeWindow: FC<{ draggable?: boolean }> = ({ draggable = true }) => {
const inputBarRef = useRef<HTMLDivElement>(null)
const featureMenusRef = useRef<FeatureMenusRef>(null)
const supportedImageExts = useMemo(() => ['.png', '.jpg', '.jpeg', '.gif', '.bmp', '.webp'], [])
const referenceText = useMemo(() => clipboardText || userInputText, [clipboardText, userInputText])
const userContent = useMemo(() => {
@ -213,6 +218,23 @@ const HomeWindow: FC<{ draggable?: boolean }> = ({ draggable = true }) => {
setUserInputText(e.target.value)
}
const handlePaste = useCallback(
async (event: React.ClipboardEvent<HTMLInputElement>) => {
await PasteService.handlePaste(
event.nativeEvent,
supportedImageExts,
setFiles,
setUserInputText,
false,
undefined,
userInputText,
undefined,
t
)
},
[supportedImageExts, t, userInputText]
)
const handleError = (error: Error) => {
setIsLoading(false)
setError(error.message)
@ -227,10 +249,13 @@ const HomeWindow: FC<{ draggable?: boolean }> = ({ draggable = true }) => {
try {
const topicId = currentTopic.current.id
const uploadedFiles = files.length ? await FileManager.uploadFiles(files) : []
const { message: userMessage, blocks } = getUserMessage({
content: [prompt, userContent].filter(Boolean).join('\n\n'),
assistant: currentAssistant,
topic: currentTopic.current
topic: currentTopic.current,
files: uploadedFiles
})
store.dispatch(newMessagesActions.addMessage({ topicId, message: userMessage }))
@ -272,6 +297,7 @@ const HomeWindow: FC<{ draggable?: boolean }> = ({ draggable = true }) => {
setIsFirstMessage(false)
setUserInputText('')
setFiles([])
const newAssistant = cloneDeep(currentAssistant)
if (!newAssistant.settings) {
@ -452,7 +478,7 @@ const HomeWindow: FC<{ draggable?: boolean }> = ({ draggable = true }) => {
currentAskId.current = ''
}
},
[userContent, currentAssistant]
[files, userContent, currentAssistant]
)
const handlePause = useCallback(() => {
@ -546,6 +572,7 @@ const HomeWindow: FC<{ draggable?: boolean }> = ({ draggable = true }) => {
loading={isLoading}
handleKeyDown={handleKeyDown}
handleChange={handleChange}
handlePaste={handlePaste}
ref={inputBarRef}
/>
<Divider style={{ margin: '10px 0' }} />
@ -590,6 +617,7 @@ const HomeWindow: FC<{ draggable?: boolean }> = ({ draggable = true }) => {
loading={isLoading}
handleKeyDown={handleKeyDown}
handleChange={handleChange}
handlePaste={handlePaste}
ref={inputBarRef}
/>
<Divider style={{ margin: '10px 0' }} />

View File

@ -14,6 +14,7 @@ interface InputBarProps {
loading: boolean
handleKeyDown: (e: React.KeyboardEvent<HTMLInputElement>) => void
handleChange: (e: React.ChangeEvent<HTMLInputElement>) => void
handlePaste: (e: React.ClipboardEvent<HTMLInputElement>) => void
}
const InputBar = ({
@ -23,7 +24,8 @@ const InputBar = ({
placeholder,
loading,
handleKeyDown,
handleChange
handleChange,
handlePaste
}: InputBarProps & { ref?: React.RefObject<HTMLDivElement | null> }) => {
const inputRef = useRef<InputRef>(null)
const { setTimeoutTimer } = useTimer()
@ -40,6 +42,7 @@ const InputBar = ({
autoFocus
onKeyDown={handleKeyDown}
onChange={handleChange}
onPaste={handlePaste}
ref={inputRef}
/>
</InputWrapper>