@@ -107,6 +107,7 @@ function Dropzone(props) {
107107 maxFiles,
108108 maxFileSize,
109109 handleUpload,
110+ handleFileRemoved,
110111 } = props ;
111112
112113 const [ files , setFiles ] = useState ( [ ] ) ;
@@ -134,6 +135,100 @@ function Dropzone(props) {
134135 return errors [ 0 ] ;
135136 } ;
136137
138+ const removeFile = removedFile => {
139+ if ( removedFile . status === 'uploading' ) {
140+ const confirmed = confirm ( 'The file is being uploaded, stop it?' ) ;
141+
142+ if ( ! confirmed ) {
143+ return ;
144+ }
145+ }
146+
147+ if ( removedFile . status === 'uploaded' ) {
148+ handleFileRemoved ( ( ) => {
149+ setFiles ( files . filter ( file => file . url !== removedFile . url ) ) ;
150+ } ) ;
151+
152+ return ;
153+ }
154+
155+ setFiles ( files . filter ( file => file . url !== removedFile . url ) ) ;
156+ } ;
157+
158+ useEffect (
159+ ( ) => ( ) =>
160+ files . forEach ( file => {
161+ // Make sure to revoke the data uris to avoid memory leaks.
162+ URL . revokeObjectURL ( file . preview ) ;
163+ } ) ,
164+ [ files ] ,
165+ ) ;
166+
167+ /**
168+ * Handle the queueing of files here.
169+ */
170+ useEffect ( ( ) => {
171+ // If nothing is in the queue, stop.
172+ if ( files . findIndex ( file => file . status === 'queued' ) < 0 ) {
173+ return ;
174+ }
175+
176+ // Stop if there is a file being uploaded.
177+ if ( files . findIndex ( file => file . status === 'uploading' ) > - 1 ) {
178+ return ;
179+ }
180+
181+ // Queue out a file if the one being uploaded is removed / has finished.
182+ setFiles (
183+ files
184+ // Set aside the uploaded files
185+ . filter ( file => file . status === 'uploaded' )
186+ . concat (
187+ files
188+ // Only the queued files should be a candidate for uploading.
189+ . filter ( file => file . status === 'queued' )
190+ . map ( ( file , key ) => {
191+ // Upload the first in the queue
192+ if ( key === 0 ) {
193+ return Object . assign ( file , {
194+ status : 'uploading' ,
195+ message : '' ,
196+ } ) ;
197+ }
198+
199+ return file ;
200+ } ) ,
201+ )
202+ // Append the rejected files at the end.
203+ . concat ( files . filter ( file => file . status === 'rejected' ) ) ,
204+ ) ;
205+ } , [ files ] ) ;
206+
207+ /**
208+ * Handle the file being uploaded here.
209+ */
210+ useEffect ( ( ) => {
211+ // Stop if there are nothing to be uploaded.
212+ if ( files . findIndex ( file => file . status === 'uploading' ) < 0 ) {
213+ return ;
214+ }
215+
216+ handleUpload ( files . find ( file => file . status === 'uploading' ) , ( ) => {
217+ setFiles (
218+ files . map ( file => {
219+ if ( file . status === 'uploading' ) {
220+ return Object . assign ( file , {
221+ status : 'uploaded' ,
222+ message : '' ,
223+ } ) ;
224+ }
225+
226+ return file ;
227+ } ) ,
228+ ) ;
229+ } ) ;
230+ } , [ files ] ) ;
231+
137232 const { getRootProps, getInputProps, open, isDragActive } = useDropzone ( {
138233 accept : acceptedFileTypes . join ( ',' ) ,
139234 maxSize : maxFileSize * 1000 * 1000 ,
@@ -158,10 +253,12 @@ function Dropzone(props) {
158253
159254 setFiles (
160255 files . concat ( acceptedFiles , rejectedFiles ) . map ( ( file , key ) => {
256+ // Set the first one as uploading.
161257 if ( key === 0 && file . status === 'queued' ) {
162- file . status = 'uploading' ;
163-
164- return file ;
258+ return Object . assign ( file , {
259+ status : 'uploading' ,
260+ message : '' ,
261+ } ) ;
165262 }
166263
167264 return file ;
@@ -174,18 +271,6 @@ function Dropzone(props) {
174271
175272 const { ref, ...rootProps } = getRootProps ( ) ;
176273
177- useEffect (
178- ( ) => ( ) => {
179- files . forEach ( file => {
180- // Make sure to revoke the data uris to avoid memory leaks.
181- URL . revokeObjectURL ( file . preview ) ;
182- } ) ;
183-
184- // If there aren't any one being uploaded, pick one from the queue.
185- } ,
186- [ files ] ,
187- ) ;
188-
189274 return (
190275 < RootRef rootRef = { ref } >
191276 < Grid
@@ -278,25 +363,11 @@ function Dropzone(props) {
278363 < Typography
279364 color = "primary"
280365 className = { classes . removeLink }
281- onClick = { ( ) => {
282- if ( file . status === 'uploading' ) {
283- const confirmed = confirm (
284- 'The file is being uploaded, stop it?' ,
285- ) ;
286-
287- if ( ! confirmed ) {
288- return ;
289- }
290- }
291-
292- setFiles (
293- files . filter (
294- ( file , i ) => i !== key ,
295- ) ,
296- ) ;
297- } }
366+ onClick = { ( ) => removeFile ( file ) }
298367 >
299- Remove File
368+ { file . status === 'uploading'
369+ ? 'Cancel'
370+ : 'Remove File' }
300371 </ Typography >
301372 </ Grid >
302373 ) )
@@ -360,6 +431,7 @@ Dropzone.propTypes = {
360431 maxFiles : PropTypes . number ,
361432 maxFileSize : PropTypes . number ,
362433 handleUpload : PropTypes . func . isRequired ,
434+ handleFileRemoved : PropTypes . func . isRequired ,
363435} ;
364436
365437Dropzone . defaultProps = {
0 commit comments