mirror of
https://github.com/immich-app/immich.git
synced 2025-01-01 08:31:59 +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) => {
|
const onDrop = async (e: DragEvent) => {
|
||||||
dragStartTarget = null;
|
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) {
|
if (!files) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue