chore: prevent drag image to replace the window, and enable shortcut copy and paste image
This commit is contained in:
parent
f70449fd98
commit
e04bb86171
@ -332,6 +332,41 @@ const ChatInput = ({ model, className, initialMessage }: ChatInputProps) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handlePaste = (e: React.ClipboardEvent) => {
|
||||||
|
const clipboardItems = e.clipboardData?.items
|
||||||
|
if (!clipboardItems) return
|
||||||
|
|
||||||
|
const imageItems = Array.from(clipboardItems).filter(item =>
|
||||||
|
item.type.startsWith('image/')
|
||||||
|
)
|
||||||
|
|
||||||
|
if (imageItems.length > 0) {
|
||||||
|
e.preventDefault()
|
||||||
|
|
||||||
|
const files: File[] = []
|
||||||
|
let processedCount = 0
|
||||||
|
|
||||||
|
imageItems.forEach((item) => {
|
||||||
|
const file = item.getAsFile()
|
||||||
|
if (file) {
|
||||||
|
files.push(file)
|
||||||
|
processedCount++
|
||||||
|
|
||||||
|
// When all files are collected, process them
|
||||||
|
if (processedCount === imageItems.length) {
|
||||||
|
const syntheticEvent = {
|
||||||
|
target: {
|
||||||
|
files: files,
|
||||||
|
},
|
||||||
|
} as unknown as React.ChangeEvent<HTMLInputElement>
|
||||||
|
|
||||||
|
handleFileChange(syntheticEvent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
@ -359,6 +394,7 @@ const ChatInput = ({ model, className, initialMessage }: ChatInputProps) => {
|
|||||||
isFocused && 'ring-1 ring-main-view-fg/10',
|
isFocused && 'ring-1 ring-main-view-fg/10',
|
||||||
isDragOver && 'ring-2 ring-accent border-accent'
|
isDragOver && 'ring-2 ring-accent border-accent'
|
||||||
)}
|
)}
|
||||||
|
data-drop-zone="true"
|
||||||
onDragEnter={handleDragEnter}
|
onDragEnter={handleDragEnter}
|
||||||
onDragLeave={handleDragLeave}
|
onDragLeave={handleDragLeave}
|
||||||
onDragOver={handleDragOver}
|
onDragOver={handleDragOver}
|
||||||
@ -423,6 +459,7 @@ const ChatInput = ({ model, className, initialMessage }: ChatInputProps) => {
|
|||||||
// When Shift+Enter is pressed, a new line is added (default behavior)
|
// When Shift+Enter is pressed, a new line is added (default behavior)
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
onPaste={handlePaste}
|
||||||
placeholder={t('common:placeholder.chatInput')}
|
placeholder={t('common:placeholder.chatInput')}
|
||||||
autoFocus
|
autoFocus
|
||||||
spellCheck={spellCheckChatInput}
|
spellCheck={spellCheckChatInput}
|
||||||
|
|||||||
@ -26,7 +26,7 @@ import {
|
|||||||
ResizablePanel,
|
ResizablePanel,
|
||||||
ResizableHandle,
|
ResizableHandle,
|
||||||
} from '@/components/ui/resizable'
|
} from '@/components/ui/resizable'
|
||||||
import { useCallback } from 'react'
|
import { useCallback, useEffect } from 'react'
|
||||||
import GlobalError from '@/containers/GlobalError'
|
import GlobalError from '@/containers/GlobalError'
|
||||||
import { GlobalEventHandler } from '@/providers/GlobalEventHandler'
|
import { GlobalEventHandler } from '@/providers/GlobalEventHandler'
|
||||||
|
|
||||||
@ -65,6 +65,41 @@ const AppLayout = () => {
|
|||||||
[setLeftPanelSize, setLeftPanel]
|
[setLeftPanelSize, setLeftPanel]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Prevent default drag and drop behavior globally
|
||||||
|
useEffect(() => {
|
||||||
|
const preventDefaults = (e: DragEvent) => {
|
||||||
|
e.preventDefault()
|
||||||
|
e.stopPropagation()
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleGlobalDrop = (e: DragEvent) => {
|
||||||
|
e.preventDefault()
|
||||||
|
e.stopPropagation()
|
||||||
|
|
||||||
|
// Only prevent if the target is not within a chat input or other valid drop zone
|
||||||
|
const target = e.target as Element
|
||||||
|
const isValidDropZone = target?.closest('[data-drop-zone="true"]') ||
|
||||||
|
target?.closest('.chat-input-drop-zone') ||
|
||||||
|
target?.closest('[data-tauri-drag-region]')
|
||||||
|
|
||||||
|
if (!isValidDropZone) {
|
||||||
|
// Prevent the file from opening in the window
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add event listeners to prevent default drag/drop behavior
|
||||||
|
window.addEventListener('dragenter', preventDefaults)
|
||||||
|
window.addEventListener('dragover', preventDefaults)
|
||||||
|
window.addEventListener('drop', handleGlobalDrop)
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
window.removeEventListener('dragenter', preventDefaults)
|
||||||
|
window.removeEventListener('dragover', preventDefaults)
|
||||||
|
window.removeEventListener('drop', handleGlobalDrop)
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<AnalyticProvider />
|
<AnalyticProvider />
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user