Skip to content

Commit 0ebf6ef

Browse files
authored
Allow dropping folders (#2)
* Feature: Allow drop folder(s) * refactor: review fixes for Allow drop folder(s) feature * refactor: review 2 fixes for Allow drop folder(s) feature * refactor: review 3 fixes for Allow drop folder(s) feature
1 parent 2850a64 commit 0ebf6ef

File tree

1 file changed

+32
-1
lines changed

1 file changed

+32
-1
lines changed

src/DropAreaBase/DropAreaBase.js

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,12 @@ function cancelEvent (e) {
2424
e.stopPropagation()
2525
}
2626

27+
// Declare global DataTransferItem for standardjs lintfix
28+
/* global DataTransferItem */
29+
30+
// Browser supports webkitGetAsEntry API needed for dropping folders
31+
const folderDropSupported = !!DataTransferItem.prototype.webkitGetAsEntry
32+
2733
export default class DropAreaBase extends React.Component {
2834
fileInputRef = React.createRef()
2935

@@ -95,7 +101,32 @@ export default class DropAreaBase extends React.Component {
95101
}
96102

97103
if (this.isAcceptingTransfer(e.dataTransfer)) {
98-
this.props.onSelectFiles(e.dataTransfer.files)
104+
if (folderDropSupported === false) {
105+
this.props.onSelectFiles(e.dataTransfer.files)
106+
} else {
107+
// Recursive function to walk into directories and extract file objects
108+
const recurseItem = (item, sub) => new Promise((resolve, reject) => {
109+
// Resolve with a single item list
110+
if (item.isFile) { item.file(file => resolve([file]), e => reject(e)) }
111+
112+
// Resolve with merging all sub entry lists
113+
if (item.isDirectory) {
114+
item.createReader().readEntries(entries =>
115+
Promise
116+
.all(entries
117+
.map(entry => recurseItem(entry, sub + item.name + '/')))
118+
.then(files => files.flat())
119+
.then(files => resolve(files))
120+
, err => reject(err))
121+
}
122+
})
123+
124+
Promise
125+
.all([...e.dataTransfer.items].map(item =>
126+
recurseItem(item.webkitGetAsEntry(), '/')))
127+
.then(files => files.flat())
128+
.then(files => this.props.onSelectFiles(files))
129+
}
99130
}
100131
}
101132

0 commit comments

Comments
 (0)