82 lines
2.1 KiB
TypeScript
Executable File
82 lines
2.1 KiB
TypeScript
Executable File
import {UploadedFile} from '../uploaded-file';
|
|
|
|
export async function getDroppedFiles(
|
|
dataTransfer: DataTransfer
|
|
): Promise<UploadedFile[]> {
|
|
let files: UploadedFile[] = [];
|
|
|
|
if (dataTransfer.items?.[0] && 'webkitGetAsEntry' in dataTransfer.items[0]) {
|
|
// need to make a copy if transfer items and get entry here, it
|
|
// might not be available anymore in subsequent loop iterations
|
|
const entries = [...dataTransfer.items].map(item => {
|
|
return item.webkitGetAsEntry();
|
|
});
|
|
for (const entry of entries) {
|
|
if (entry && !entry.isDirectory) {
|
|
files.push(await filesystemEntryToFile(entry as FileSystemFileEntry));
|
|
} else if (entry) {
|
|
files = [
|
|
...files,
|
|
...(await readDirRecursive(entry as FileSystemDirectoryEntry)),
|
|
];
|
|
}
|
|
}
|
|
} else {
|
|
files = [...dataTransfer.files].map(f => new UploadedFile(f));
|
|
}
|
|
return files;
|
|
}
|
|
|
|
function filesystemEntryToFile(
|
|
entry: FileSystemFileEntry
|
|
): Promise<UploadedFile> {
|
|
return new Promise(resolve => {
|
|
entry.file(file => {
|
|
resolve(new UploadedFile(file, entry.fullPath));
|
|
});
|
|
});
|
|
}
|
|
|
|
async function readDirRecursive(
|
|
entry: FileSystemDirectoryEntry,
|
|
files: UploadedFile[] = []
|
|
) {
|
|
const entries = await readEntries(entry);
|
|
|
|
for (const childEntry of entries) {
|
|
if (childEntry.isDirectory) {
|
|
await readDirRecursive(childEntry as FileSystemDirectoryEntry, files);
|
|
} else {
|
|
files.push(
|
|
await filesystemEntryToFile(childEntry as FileSystemFileEntry)
|
|
);
|
|
}
|
|
}
|
|
|
|
return files;
|
|
}
|
|
|
|
function readEntries(
|
|
dir: FileSystemDirectoryEntry
|
|
): Promise<FileSystemEntry[]> {
|
|
return new Promise(resolve => {
|
|
drainDirReader(dir.createReader(), resolve);
|
|
});
|
|
}
|
|
|
|
function drainDirReader(
|
|
reader: FileSystemDirectoryReader,
|
|
resolve: (value: FileSystemEntry[]) => void,
|
|
allEntries: FileSystemEntry[] = []
|
|
) {
|
|
// directory reader needs to be called repeatedly until it returns an empty array
|
|
reader.readEntries(entries => {
|
|
if (entries.length) {
|
|
allEntries = [...allEntries, ...entries];
|
|
drainDirReader(reader, resolve, allEntries);
|
|
} else {
|
|
resolve(allEntries);
|
|
}
|
|
});
|
|
}
|