mirror of
https://github.com/nexu-io/open-design.git
synced 2026-05-31 19:04:39 +07:00
Support folder drops in Design Files (#1662)
Co-authored-by: mzl2233 <mzl2233@users.noreply.github.com>
This commit is contained in:
parent
db9752f5ae
commit
b311885bee
1 changed files with 57 additions and 2 deletions
|
|
@ -37,6 +37,18 @@ type DesignFilesGroupMode = 'kind' | 'modified';
|
|||
type ModifiedSection = 'today' | 'yesterday' | 'previous7Days' | 'previous30Days' | 'older';
|
||||
type SortKey = 'name' | 'kind' | 'mtime';
|
||||
type SortDir = 'asc' | 'desc';
|
||||
type FileSystemEntryWithReader = FileSystemEntry & {
|
||||
createReader?: () => FileSystemDirectoryReader;
|
||||
};
|
||||
type FileSystemFileEntryWithFile = FileSystemFileEntry & {
|
||||
file: (
|
||||
successCallback: (file: File) => void,
|
||||
errorCallback?: (error: DOMException) => void,
|
||||
) => void;
|
||||
};
|
||||
type DataTransferItemWithEntry = DataTransferItem & {
|
||||
webkitGetAsEntry?: () => FileSystemEntry | null;
|
||||
};
|
||||
|
||||
const MODIFIED_SECTION_ORDER: ModifiedSection[] = [
|
||||
'today',
|
||||
|
|
@ -671,11 +683,11 @@ export function DesignFilesPanel({
|
|||
}
|
||||
}
|
||||
|
||||
function handleDrop(ev: React.DragEvent<HTMLDivElement>) {
|
||||
async function handleDrop(ev: React.DragEvent<HTMLDivElement>) {
|
||||
ev.preventDefault();
|
||||
dragDepthRef.current = 0;
|
||||
setDraggingFiles(false);
|
||||
const dropped = Array.from(ev.dataTransfer.files ?? []);
|
||||
const dropped = await filesFromDataTransfer(ev.dataTransfer);
|
||||
if (dropped.length > 0) onUploadFiles(dropped);
|
||||
}
|
||||
|
||||
|
|
@ -1394,6 +1406,49 @@ function dateDaysBefore(date: Date, days: number): Date {
|
|||
return result;
|
||||
}
|
||||
|
||||
async function filesFromDataTransfer(dataTransfer: DataTransfer): Promise<File[]> {
|
||||
const items = Array.from(dataTransfer.items ?? []);
|
||||
if (items.length === 0) return Array.from(dataTransfer.files ?? []);
|
||||
|
||||
const files = await Promise.all(items.map(filesFromDataTransferItem));
|
||||
const flattened = files.flat();
|
||||
return flattened.length > 0 ? flattened : Array.from(dataTransfer.files ?? []);
|
||||
}
|
||||
|
||||
async function filesFromDataTransferItem(item: DataTransferItem): Promise<File[]> {
|
||||
const entry = (item as DataTransferItemWithEntry).webkitGetAsEntry?.();
|
||||
if (!entry) {
|
||||
const file = item.kind === 'file' ? item.getAsFile() : null;
|
||||
return file ? [file] : [];
|
||||
}
|
||||
return filesFromFileSystemEntry(entry);
|
||||
}
|
||||
|
||||
async function filesFromFileSystemEntry(entry: FileSystemEntry): Promise<File[]> {
|
||||
if (entry.isFile) return [await fileFromEntry(entry as FileSystemFileEntryWithFile)];
|
||||
if (!entry.isDirectory) return [];
|
||||
|
||||
const reader = (entry as FileSystemEntryWithReader).createReader?.();
|
||||
if (!reader) return [];
|
||||
|
||||
const files: File[] = [];
|
||||
for (;;) {
|
||||
const entries = await readEntryBatch(reader);
|
||||
if (entries.length === 0) break;
|
||||
const nested = await Promise.all(entries.map(filesFromFileSystemEntry));
|
||||
files.push(...nested.flat());
|
||||
}
|
||||
return files;
|
||||
}
|
||||
|
||||
function fileFromEntry(entry: FileSystemFileEntryWithFile): Promise<File> {
|
||||
return new Promise((resolve, reject) => entry.file(resolve, reject));
|
||||
}
|
||||
|
||||
function readEntryBatch(reader: FileSystemDirectoryReader): Promise<FileSystemEntry[]> {
|
||||
return new Promise((resolve, reject) => reader.readEntries(resolve, reject));
|
||||
}
|
||||
|
||||
function kindGlyph(kind: ProjectFileKind): string {
|
||||
if (kind === 'html') return '\u27E8\u27E9';
|
||||
if (kind === 'image') return '\u25A3';
|
||||
|
|
|
|||
Loading…
Reference in a new issue