@@ -77,9 +77,18 @@ export default {
7777 v-model="messageText"
7878 @keydown.enter.exact.prevent="sendMessage"
7979 @keydown.enter.shift.exact="addNewLine"
80- placeholder="Type your message... (Enter to send, Shift+Enter for new line)"
80+ @paste="onPaste"
81+ @dragover="onDragOver"
82+ @dragleave="onDragLeave"
83+ @drop="onDrop"
84+ placeholder="Type your message... (Enter to send, Shift+Enter for new line, drag & drop or paste files)"
8185 rows="3"
82- class="block w-full rounded-md border border-gray-300 px-3 py-2 pr-12 text-sm placeholder-gray-500 focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500"
86+ :class="[
87+ 'block w-full rounded-md border px-3 py-2 pr-12 text-sm placeholder-gray-500 focus:outline-none focus:ring-1',
88+ isDragging
89+ ? 'border-blue-500 bg-blue-50 ring-1 ring-blue-500'
90+ : 'border-gray-300 focus:border-blue-500 focus:ring-blue-500'
91+ ]"
8392 :disabled="isGenerating || !model"
8493 ></textarea>
8594 <button title="Send (Enter)" type="button"
@@ -169,6 +178,93 @@ export default {
169178 attachedFiles . value . splice ( i , 1 )
170179 }
171180
181+ // Helper function to add files and set default message
182+ const addFilesAndSetMessage = ( files ) => {
183+ if ( files . length === 0 ) return
184+
185+ attachedFiles . value . push ( ...files )
186+
187+ // Set default message text if empty
188+ if ( ! messageText . value . trim ( ) ) {
189+ if ( hasImage ( ) ) {
190+ messageText . value = getTextContent ( config . defaults . image )
191+ } else if ( hasAudio ( ) ) {
192+ messageText . value = getTextContent ( config . defaults . audio )
193+ } else {
194+ messageText . value = getTextContent ( config . defaults . file )
195+ }
196+ }
197+ }
198+
199+ // Handle paste events for clipboard images, audio, and files
200+ const onPaste = async ( e ) => {
201+ // Use the paste event's clipboardData directly (works best for paste events)
202+ const items = e . clipboardData ?. items
203+ if ( ! items ) return
204+
205+ const files = [ ]
206+
207+ // Check all clipboard items
208+ for ( let i = 0 ; i < items . length ; i ++ ) {
209+ const item = items [ i ]
210+
211+ // Handle files (images, audio, etc.)
212+ if ( item . kind === 'file' ) {
213+ const file = item . getAsFile ( )
214+ if ( file ) {
215+ // Generate a better filename based on type
216+ let filename = file . name
217+ if ( ! filename || filename === 'image.png' || filename === 'blob' ) {
218+ const ext = file . type . split ( '/' ) [ 1 ] || 'png'
219+ const timestamp = new Date ( ) . getTime ( )
220+ if ( file . type . startsWith ( 'image/' ) ) {
221+ filename = `pasted-image-${ timestamp } .${ ext } `
222+ } else if ( file . type . startsWith ( 'audio/' ) ) {
223+ filename = `pasted-audio-${ timestamp } .${ ext } `
224+ } else {
225+ filename = `pasted-file-${ timestamp } .${ ext } `
226+ }
227+ // Create a new File object with the better name
228+ files . push ( new File ( [ file ] , filename , { type : file . type } ) )
229+ } else {
230+ files . push ( file )
231+ }
232+ }
233+ }
234+ }
235+
236+ if ( files . length > 0 ) {
237+ e . preventDefault ( )
238+ addFilesAndSetMessage ( files )
239+ }
240+ }
241+
242+ // Handle drag and drop events
243+ const isDragging = ref ( false )
244+
245+ const onDragOver = ( e ) => {
246+ e . preventDefault ( )
247+ e . stopPropagation ( )
248+ isDragging . value = true
249+ }
250+
251+ const onDragLeave = ( e ) => {
252+ e . preventDefault ( )
253+ e . stopPropagation ( )
254+ isDragging . value = false
255+ }
256+
257+ const onDrop = ( e ) => {
258+ e . preventDefault ( )
259+ e . stopPropagation ( )
260+ isDragging . value = false
261+
262+ const files = Array . from ( e . dataTransfer ?. files || [ ] )
263+ if ( files . length > 0 ) {
264+ addFilesAndSetMessage ( files )
265+ }
266+ }
267+
172268 function createChatRequest ( ) {
173269 if ( hasImage ( ) ) {
174270 return deepClone ( config . defaults . image )
@@ -433,8 +529,13 @@ export default {
433529 messageText,
434530 fileInput,
435531 showSettings,
532+ isDragging,
436533 triggerFilePicker,
437534 onFilesSelected,
535+ onPaste,
536+ onDragOver,
537+ onDragLeave,
538+ onDrop,
438539 removeAttachment,
439540 sendMessage,
440541 addNewLine,
0 commit comments