@@ -107,6 +107,7 @@ function Dropzone(props) {
107
107
maxFiles,
108
108
maxFileSize,
109
109
handleUpload,
110
+ handleFileRemoved,
110
111
} = props ;
111
112
112
113
const [ files , setFiles ] = useState ( [ ] ) ;
@@ -134,6 +135,100 @@ function Dropzone(props) {
134
135
return errors [ 0 ] ;
135
136
} ;
136
137
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
+
137
232
const { getRootProps, getInputProps, open, isDragActive } = useDropzone ( {
138
233
accept : acceptedFileTypes . join ( ',' ) ,
139
234
maxSize : maxFileSize * 1000 * 1000 ,
@@ -158,10 +253,12 @@ function Dropzone(props) {
158
253
159
254
setFiles (
160
255
files . concat ( acceptedFiles , rejectedFiles ) . map ( ( file , key ) => {
256
+ // Set the first one as uploading.
161
257
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
+ } ) ;
165
262
}
166
263
167
264
return file ;
@@ -174,18 +271,6 @@ function Dropzone(props) {
174
271
175
272
const { ref, ...rootProps } = getRootProps ( ) ;
176
273
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
-
189
274
return (
190
275
< RootRef rootRef = { ref } >
191
276
< Grid
@@ -278,25 +363,11 @@ function Dropzone(props) {
278
363
< Typography
279
364
color = "primary"
280
365
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 ) }
298
367
>
299
- Remove File
368
+ { file . status === 'uploading'
369
+ ? 'Cancel'
370
+ : 'Remove File' }
300
371
</ Typography >
301
372
</ Grid >
302
373
) )
@@ -360,6 +431,7 @@ Dropzone.propTypes = {
360
431
maxFiles : PropTypes . number ,
361
432
maxFileSize : PropTypes . number ,
362
433
handleUpload : PropTypes . func . isRequired ,
434
+ handleFileRemoved : PropTypes . func . isRequired ,
363
435
} ;
364
436
365
437
Dropzone . defaultProps = {
0 commit comments