mirror of
https://github.com/immich-app/immich.git
synced 2024-12-29 15:11:58 +00:00
feat(web): drag and drop or paste directories for upload (#11879)
feat(web): support for directories drag and drop Allows directories to be drag and dropped or pasted for upload.
This commit is contained in:
parent
bd42e05152
commit
5ab92f346a
1 changed files with 58 additions and 3 deletions
|
@ -26,12 +26,67 @@
|
|||
|
||||
const onDrop = async (e: DragEvent) => {
|
||||
dragStartTarget = null;
|
||||
await handleFiles(e.dataTransfer?.files);
|
||||
await handleDataTransfer(e.dataTransfer);
|
||||
};
|
||||
|
||||
const onPaste = ({ clipboardData }: ClipboardEvent) => handleFiles(clipboardData?.files);
|
||||
const onPaste = ({ clipboardData }: ClipboardEvent) => handleDataTransfer(clipboardData);
|
||||
|
||||
const handleFiles = async (files?: FileList) => {
|
||||
const handleDataTransfer = async (dataTransfer?: DataTransfer | null) => {
|
||||
if (!dataTransfer) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!browserSupportsDirectoryUpload()) {
|
||||
return handleFiles(dataTransfer.files);
|
||||
}
|
||||
|
||||
const transferEntries = Array.from(dataTransfer.items)
|
||||
.map((i: DataTransferItem) => i.webkitGetAsEntry())
|
||||
.filter((i) => i !== null);
|
||||
const files = await getAllFilesFromTransferEntries(transferEntries);
|
||||
return handleFiles(files);
|
||||
};
|
||||
|
||||
const browserSupportsDirectoryUpload = () => typeof DataTransferItem.prototype.webkitGetAsEntry === 'function';
|
||||
|
||||
const getAllFilesFromTransferEntries = async (transferEntries: FileSystemEntry[]): Promise<File[]> => {
|
||||
const allFiles: File[] = [];
|
||||
let entriesToCheckForSubDirectories = [...transferEntries];
|
||||
while (entriesToCheckForSubDirectories.length > 0) {
|
||||
const currentEntry = entriesToCheckForSubDirectories.pop();
|
||||
|
||||
if (isFileSystemDirectoryEntry(currentEntry)) {
|
||||
entriesToCheckForSubDirectories = entriesToCheckForSubDirectories.concat(
|
||||
await getContentsFromFileSystemDirectoryEntry(currentEntry),
|
||||
);
|
||||
} else if (isFileSystemFileEntry(currentEntry)) {
|
||||
allFiles.push(await getFileFromFileSystemEntry(currentEntry));
|
||||
}
|
||||
}
|
||||
|
||||
return allFiles;
|
||||
};
|
||||
|
||||
const isFileSystemDirectoryEntry = (entry?: FileSystemEntry): entry is FileSystemDirectoryEntry =>
|
||||
!!entry && entry.isDirectory;
|
||||
const isFileSystemFileEntry = (entry?: FileSystemEntry): entry is FileSystemFileEntry => !!entry && entry.isFile;
|
||||
|
||||
const getFileFromFileSystemEntry = async (fileSystemFileEntry: FileSystemFileEntry): Promise<File> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
fileSystemFileEntry.file(resolve, reject);
|
||||
});
|
||||
};
|
||||
|
||||
const getContentsFromFileSystemDirectoryEntry = async (
|
||||
fileSystemDirectoryEntry: FileSystemDirectoryEntry,
|
||||
): Promise<FileSystemEntry[]> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const reader = fileSystemDirectoryEntry.createReader();
|
||||
reader.readEntries(resolve, reject);
|
||||
});
|
||||
};
|
||||
|
||||
const handleFiles = async (files?: FileList | File[]) => {
|
||||
if (!files) {
|
||||
return;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue