@@ -6,7 +6,7 @@ import React, {
66 useContext ,
77 useEffect ,
88 useMemo ,
9- useState ,
9+ useRef ,
1010} from 'react' ;
1111import {
1212 MessageInputContextValue ,
@@ -18,34 +18,27 @@ import { useDropzone } from 'react-dropzone';
1818import clsx from 'clsx' ;
1919
2020const DragAndDropUploadContext = React . createContext < {
21- fileQueue : File [ ] ;
22- addFilesToQueue : ( ( files : File [ ] ) => void ) | null ;
23- removeFilesFromQueue : ( ( files : File [ ] ) => void ) | null ;
21+ subscribeToDrop : ( ( fn : ( files : File [ ] ) => void ) => ( ) => void ) | null ;
2422} > ( {
25- addFilesToQueue : null ,
26- fileQueue : [ ] ,
27- removeFilesFromQueue : null ,
23+ subscribeToDrop : null ,
2824} ) ;
2925
3026export const useDragAndDropUploadContext = ( ) => useContext ( DragAndDropUploadContext ) ;
3127
3228/**
33- * @private To maintain top -> bottom data flow, the drag-and-drop functionality allows dragging any files to the queue - the closest
34- * `MessageInputProvider` will be notified through `DragAndDropUploadContext.fileQueue` and starts the upload with `uploadNewAttachments`,
35- * forwarded files are removed from the queue immediately after.
29+ * @private This hook should be used only once directly in the `MessageInputProvider` to
30+ * register `uploadNewFiles` functions of the rendered `MessageInputs`. Each `MessageInput`
31+ * will then be notified when the drop event occurs from within the `WithDragAndDropUpload`
32+ * component.
3633 */
37- export const useHandleDragAndDropQueuedFiles = ( {
38- uploadNewFiles,
39- } : MessageInputContextValue ) => {
40- const { fileQueue, removeFilesFromQueue } = useDragAndDropUploadContext ( ) ;
34+ export const useRegisterDropHandlers = ( { uploadNewFiles } : MessageInputContextValue ) => {
35+ const { subscribeToDrop } = useDragAndDropUploadContext ( ) ;
4136
4237 useEffect ( ( ) => {
43- if ( ! removeFilesFromQueue ) return ;
38+ const unsubscribe = subscribeToDrop ?. ( uploadNewFiles ) ;
4439
45- uploadNewFiles ( fileQueue ) ;
46-
47- removeFilesFromQueue ( fileQueue ) ;
48- } , [ fileQueue , removeFilesFromQueue , uploadNewFiles ] ) ;
40+ return unsubscribe ;
41+ } , [ subscribeToDrop , uploadNewFiles ] ) ;
4942} ;
5043
5144/**
@@ -78,7 +71,7 @@ export const WithDragAndDropUpload = ({
7871 className ?: string ;
7972 style ?: CSSProperties ;
8073} > ) => {
81- const [ files , setFiles ] = useState < File [ ] > ( [ ] ) ;
74+ const dropHandlersRef = useRef < Set < ( f : File [ ] ) => void > > ( new Set ( ) ) ;
8275 const { acceptedFiles = [ ] , multipleUploads } = useChannelStateContext ( ) ;
8376 const { t } = useTranslationContext ( ) ;
8477
@@ -98,13 +91,16 @@ export const WithDragAndDropUpload = ({
9891 [ acceptedFiles ] ,
9992 ) ;
10093
101- const addFilesToQueue = useCallback ( ( files : File [ ] ) => {
102- setFiles ( ( cv ) => cv . concat ( files ) ) ;
94+ const subscribeToDrop = useCallback ( ( fn : ( files : File [ ] ) => void ) => {
95+ dropHandlersRef . current . add ( fn ) ;
96+
97+ return ( ) => {
98+ dropHandlersRef . current . delete ( fn ) ;
99+ } ;
103100 } , [ ] ) ;
104101
105- const removeFilesFromQueue = useCallback ( ( files : File [ ] ) => {
106- if ( ! files . length ) return ;
107- setFiles ( ( cv ) => cv . filter ( ( f ) => files . indexOf ( f ) === - 1 ) ) ;
102+ const handleDrop = useCallback ( ( files : File [ ] ) => {
103+ dropHandlersRef . current . forEach ( ( fn ) => fn ( files ) ) ;
108104 } , [ ] ) ;
109105
110106 const { getRootProps, isDragActive, isDragReject } = useDropzone ( {
@@ -116,20 +112,20 @@ export const WithDragAndDropUpload = ({
116112 : false ,
117113 multiple : multipleUploads ,
118114 noClick : true ,
119- onDrop : isWithinMessageInputContext
120- ? messageInputContext . uploadNewFiles
121- : addFilesToQueue ,
115+ onDrop : isWithinMessageInputContext ? messageInputContext . uploadNewFiles : handleDrop ,
122116 } ) ;
123117
124118 // nested WithDragAndDropUpload components render wrappers without functionality
125119 // (MessageInputFlat has a default WithDragAndDropUpload)
126- if ( dragAndDropUploadContext . removeFilesFromQueue !== null ) {
120+ if ( dragAndDropUploadContext . subscribeToDrop !== null ) {
127121 return < Component className = { className } > { children } </ Component > ;
128122 }
129123
130124 return (
131125 < DragAndDropUploadContext . Provider
132- value = { { addFilesToQueue, fileQueue : files , removeFilesFromQueue } }
126+ value = { {
127+ subscribeToDrop,
128+ } }
133129 >
134130 < Component { ...getRootProps ( { className, style } ) } >
135131 { /* TODO: could be a replaceable component */ }
0 commit comments