@@ -54,6 +54,7 @@ interface State {
54
54
isUploadingResource : boolean ;
55
55
isRequesting : boolean ;
56
56
isComposing : boolean ;
57
+ isDraggingFile : boolean ;
57
58
}
58
59
59
60
const MemoEditor = observer ( ( props : Props ) => {
@@ -71,6 +72,7 @@ const MemoEditor = observer((props: Props) => {
71
72
isUploadingResource : false ,
72
73
isRequesting : false ,
73
74
isComposing : false ,
75
+ isDraggingFile : false ,
74
76
} ) ;
75
77
const [ displayTime , setDisplayTime ] = useState < Date | undefined > ( ) ;
76
78
const [ hasContent , setHasContent ] = useState < boolean > ( false ) ;
@@ -222,6 +224,12 @@ const MemoEditor = observer((props: Props) => {
222
224
} catch ( error : any ) {
223
225
console . error ( error ) ;
224
226
toast . error ( error . details ) ;
227
+ setState ( ( state ) => {
228
+ return {
229
+ ...state ,
230
+ isUploadingResource : false ,
231
+ } ;
232
+ } ) ;
225
233
}
226
234
} ;
227
235
@@ -253,10 +261,36 @@ const MemoEditor = observer((props: Props) => {
253
261
const handleDropEvent = async ( event : React . DragEvent ) => {
254
262
if ( event . dataTransfer && event . dataTransfer . files . length > 0 ) {
255
263
event . preventDefault ( ) ;
264
+ setState ( ( prevState ) => ( {
265
+ ...prevState ,
266
+ isDraggingFile : false ,
267
+ } ) ) ;
268
+
256
269
await uploadMultiFiles ( event . dataTransfer . files ) ;
257
270
}
258
271
} ;
259
272
273
+ const handleDragOver = ( event : React . DragEvent ) => {
274
+ if ( event . dataTransfer && event . dataTransfer . types . includes ( "Files" ) ) {
275
+ event . preventDefault ( ) ;
276
+ event . dataTransfer . dropEffect = "copy" ;
277
+ if ( ! state . isDraggingFile ) {
278
+ setState ( ( prevState ) => ( {
279
+ ...prevState ,
280
+ isDraggingFile : true ,
281
+ } ) ) ;
282
+ }
283
+ }
284
+ } ;
285
+
286
+ const handleDragLeave = ( event : React . DragEvent ) => {
287
+ event . preventDefault ( ) ;
288
+ setState ( ( prevState ) => ( {
289
+ ...prevState ,
290
+ isDraggingFile : false ,
291
+ } ) ) ;
292
+ } ;
293
+
260
294
const handlePasteEvent = async ( event : React . ClipboardEvent ) => {
261
295
if ( event . clipboardData && event . clipboardData . files . length > 0 ) {
262
296
event . preventDefault ( ) ;
@@ -384,6 +418,7 @@ const MemoEditor = observer((props: Props) => {
384
418
resourceList : [ ] ,
385
419
relationList : [ ] ,
386
420
location : undefined ,
421
+ isDraggingFile : false ,
387
422
} ;
388
423
} ) ;
389
424
} ;
@@ -436,10 +471,16 @@ const MemoEditor = observer((props: Props) => {
436
471
< div
437
472
className = { `${
438
473
className ?? ""
439
- } relative w-full flex flex-col justify-start items-start bg-white dark:bg-zinc-800 px-4 pt-4 rounded-lg border border-gray-200 dark:border-zinc-700`}
474
+ } relative w-full flex flex-col justify-start items-start bg-white dark:bg-zinc-800 px-4 pt-4 rounded-lg border ${
475
+ state . isDraggingFile
476
+ ? "border-dashed border-gray-400 dark:border-primary-400 cursor-copy"
477
+ : "border-gray-200 dark:border-zinc-700 cursor-auto"
478
+ } `}
440
479
tabIndex = { 0 }
441
480
onKeyDown = { handleKeyDown }
442
481
onDrop = { handleDropEvent }
482
+ onDragOver = { handleDragOver }
483
+ onDragLeave = { handleDragLeave }
443
484
onFocus = { handleEditorFocus }
444
485
onCompositionStart = { handleCompositionStart }
445
486
onCompositionEnd = { handleCompositionEnd }
@@ -464,7 +505,7 @@ const MemoEditor = observer((props: Props) => {
464
505
< div className = "flex flex-row justify-start items-center opacity-80 dark:opacity-60 -space-x-1" >
465
506
< TagSelector editorRef = { editorRef } />
466
507
< MarkdownMenu editorRef = { editorRef } />
467
- < UploadResourceButton />
508
+ < UploadResourceButton isUploadingResource = { state . isUploadingResource } />
468
509
< AddMemoRelationPopover editorRef = { editorRef } />
469
510
{ workspaceMemoRelatedSetting . enableLocation && (
470
511
< LocationSelector
0 commit comments