|
|
@ -130,36 +130,65 @@ export class FileDropDirective { |
|
|
return null; |
|
|
return null; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
let files: File[] = []; |
|
|
const files: File[] = []; |
|
|
|
|
|
|
|
|
for (let i = 0; i < dataTransfer.items.length; i++) { |
|
|
const items = getItems(dataTransfer); |
|
|
const item = dataTransfer.items[i]; |
|
|
|
|
|
|
|
|
// Loop over files first, otherwise Chromes deletes them in the async call.
|
|
|
|
|
|
for (const item of items) { |
|
|
|
|
|
const file = item.getAsFile(); |
|
|
|
|
|
|
|
|
await transferFileTree(item, files); |
|
|
if (file && !!file.type && this.isAllowedFile(file)) { |
|
|
|
|
|
files.push(file); |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
files = files.filter(f => this.isAllowedFile(f)); |
|
|
for (const item of items) { |
|
|
|
|
|
if (Types.isFunction(item['webkitGetAsEntry'])) { |
|
|
|
|
|
const webkitEntry = item.webkitGetAsEntry(); |
|
|
|
|
|
|
|
|
return files.length > 0 ? files : null; |
|
|
if (webkitEntry && webkitEntry.isDirectory) { |
|
|
|
|
|
await this.transferWebkitTree(webkitEntry, files); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
private hasAllowedFile(dataTransfer: DataTransfer | null) { |
|
|
if (files.length === 0) { |
|
|
if (!dataTransfer || !hasFiles(dataTransfer)) { |
|
|
|
|
|
return null; |
|
|
return null; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
for (let i = 0; i < dataTransfer.files.length; i++) { |
|
|
return files; |
|
|
const file = dataTransfer.files.item(i); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private async transferWebkitTree(item: any, files: File[]) { |
|
|
|
|
|
if (item.isFile) { |
|
|
|
|
|
const file = await getFilePromise(item); |
|
|
|
|
|
|
|
|
if (file && this.isAllowedFile(file)) { |
|
|
if (file && this.isAllowedFile(file)) { |
|
|
return true; |
|
|
files.push(file); |
|
|
|
|
|
} |
|
|
|
|
|
} else if (item.isDirectory) { |
|
|
|
|
|
const entries = await getFilesPromise(item); |
|
|
|
|
|
|
|
|
|
|
|
for (const entry of entries) { |
|
|
|
|
|
await this.transferWebkitTree(entry, files); |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
for (let i = 0; i < dataTransfer.items.length; i++) { |
|
|
private hasAllowedFile(dataTransfer: DataTransfer | null) { |
|
|
const file = dataTransfer.items[i]; |
|
|
if (!dataTransfer || !hasFiles(dataTransfer)) { |
|
|
|
|
|
return null; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
if (file && this.isAllowedFile(file)) { |
|
|
for (const file of getFiles(dataTransfer)) { |
|
|
|
|
|
if (this.isAllowedFile(file)) { |
|
|
|
|
|
return true; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
for (const item of getItems(dataTransfer)) { |
|
|
|
|
|
if (this.isAllowedFile(item)) { |
|
|
return true; |
|
|
return true; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
@ -196,40 +225,6 @@ function hasFiles(dataTransfer: DataTransfer): boolean { |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
async function transferWebkitTree(item: any, files: File[]) { |
|
|
|
|
|
if (item.isFile) { |
|
|
|
|
|
const file = await getFilePromise(item); |
|
|
|
|
|
|
|
|
|
|
|
files.push(file); |
|
|
|
|
|
} else if (item.isDirectory) { |
|
|
|
|
|
const entries = await getFilesPromise(item); |
|
|
|
|
|
|
|
|
|
|
|
for (const entry of entries) { |
|
|
|
|
|
await transferWebkitTree(entry, files); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
async function transferFileTree(item: DataTransferItem, files: File[]) { |
|
|
|
|
|
if (Types.isFunction(item['webkitGetAsEntry'])) { |
|
|
|
|
|
const webkitEntry = item.webkitGetAsEntry(); |
|
|
|
|
|
|
|
|
|
|
|
if (webkitEntry) { |
|
|
|
|
|
await transferWebkitTree(webkitEntry, files); |
|
|
|
|
|
|
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (Types.isFunction(item['getAsFile'])) { |
|
|
|
|
|
const fileItem = item.getAsFile(); |
|
|
|
|
|
|
|
|
|
|
|
if (fileItem) { |
|
|
|
|
|
files.push(fileItem); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
function getFilesPromise(item: any): Promise<ReadonlyArray<any>> { |
|
|
function getFilesPromise(item: any): Promise<ReadonlyArray<any>> { |
|
|
return new Promise((resolve, reject) => { |
|
|
return new Promise((resolve, reject) => { |
|
|
try { |
|
|
try { |
|
|
@ -252,6 +247,38 @@ function getFilePromise(item: any): Promise<File> { |
|
|
}); |
|
|
}); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
function getItems(dataTransfer: DataTransfer) { |
|
|
|
|
|
const result: DataTransferItem[] = []; |
|
|
|
|
|
|
|
|
|
|
|
if (dataTransfer.files) { |
|
|
|
|
|
for (let i = 0; i < dataTransfer.items.length; i++) { |
|
|
|
|
|
const item = dataTransfer.items[i]; |
|
|
|
|
|
|
|
|
|
|
|
if (item) { |
|
|
|
|
|
result.push(item); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return result; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
function getFiles(dataTransfer: DataTransfer) { |
|
|
|
|
|
const result: File[] = []; |
|
|
|
|
|
|
|
|
|
|
|
if (dataTransfer.files) { |
|
|
|
|
|
for (let i = 0; i < dataTransfer.files.length; i++) { |
|
|
|
|
|
const file = dataTransfer.files[i]; |
|
|
|
|
|
|
|
|
|
|
|
if (file) { |
|
|
|
|
|
result.push(file); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return result; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
interface DragDropEvent extends MouseEvent { |
|
|
interface DragDropEvent extends MouseEvent { |
|
|
readonly dataTransfer: DataTransfer; |
|
|
readonly dataTransfer: DataTransfer; |
|
|
} |
|
|
} |