Skip to content

Commit e9014bc

Browse files
committed
feat: Enhance drag-and-drop functionality to support folder uploads and improve user feedback
1 parent 28e68af commit e9014bc

File tree

1 file changed

+102
-14
lines changed

1 file changed

+102
-14
lines changed

index.js

Lines changed: 102 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2030,25 +2030,113 @@
20302030
}, false);
20312031
});
20322032

2033-
// Handle dropped files
2034-
document.addEventListener('drop', e => {
2033+
// Handle dropped items (folders/files)
2034+
document.addEventListener('drop', async e => {
20352035
dragDropZone.classList.remove('drag-over');
20362036

2037-
const files = e.dataTransfer.files;
2038-
if (files.length > 0) {
2039-
// Hide drag-drop zone and show editor
2040-
dragDropZone.style.display = 'none';
2041-
if (codeEditor) codeEditor.style.display = 'block';
2042-
2043-
// Show loader IMMEDIATELY
2044-
load(true, 'Loading dropped files...');
2045-
// Process files in next tick to let loader render
2046-
setTimeout(() => loadFiles(files), 0);
2047-
} else {
2048-
toast('Please drop a folder with files', 'warning');
2037+
const items = e.dataTransfer.items;
2038+
if (!items || items.length === 0) {
2039+
toast('No items detected. Please try using "Select Directory" button', 'warning');
2040+
return;
2041+
}
2042+
2043+
// Hide drag-drop zone and show editor
2044+
dragDropZone.style.display = 'none';
2045+
if (codeEditor) codeEditor.style.display = 'block';
2046+
2047+
// Show loader IMMEDIATELY
2048+
load(true, 'Processing dropped folder...');
2049+
2050+
// Process dropped items
2051+
const allFiles = [];
2052+
2053+
// Use webkitGetAsEntry for folder support
2054+
for (let i = 0; i < items.length; i++) {
2055+
const item = items[i].webkitGetAsEntry();
2056+
if (item) {
2057+
if (item.isDirectory) {
2058+
await traverseDirectory(item, '', allFiles);
2059+
} else if (item.isFile) {
2060+
const file = items[i].getAsFile();
2061+
if (file) {
2062+
// Add webkitRelativePath property
2063+
Object.defineProperty(file, 'webkitRelativePath', {
2064+
value: file.name,
2065+
writable: false
2066+
});
2067+
allFiles.push(file);
2068+
}
2069+
}
2070+
}
2071+
}
2072+
2073+
if (allFiles.length === 0) {
2074+
toast('No files found in dropped folder', 'warning');
2075+
load(false);
2076+
dragDropZone.style.display = 'flex';
2077+
if (codeEditor) codeEditor.style.display = 'none';
2078+
return;
20492079
}
2080+
2081+
// Create a FileList-like object
2082+
const fileList = {
2083+
length: allFiles.length,
2084+
item: i => allFiles[i],
2085+
[Symbol.iterator]: function* () {
2086+
for (let i = 0; i < allFiles.length; i++) {
2087+
yield allFiles[i];
2088+
}
2089+
}
2090+
};
2091+
2092+
// Add array access
2093+
allFiles.forEach((file, idx) => {
2094+
fileList[idx] = file;
2095+
});
2096+
2097+
// Process files
2098+
setTimeout(() => loadFiles(fileList), 0);
20502099
}, false);
20512100

2101+
// Recursive function to traverse directory structure
2102+
async function traverseDirectory(entry, path, files) {
2103+
if (entry.isFile) {
2104+
return new Promise((resolve) => {
2105+
entry.file(file => {
2106+
// Add webkitRelativePath property
2107+
const relativePath = path + file.name;
2108+
Object.defineProperty(file, 'webkitRelativePath', {
2109+
value: relativePath,
2110+
writable: false
2111+
});
2112+
files.push(file);
2113+
resolve();
2114+
});
2115+
});
2116+
} else if (entry.isDirectory) {
2117+
const dirReader = entry.createReader();
2118+
return new Promise((resolve) => {
2119+
const readEntries = () => {
2120+
dirReader.readEntries(async entries => {
2121+
if (entries.length === 0) {
2122+
resolve();
2123+
return;
2124+
}
2125+
for (const childEntry of entries) {
2126+
await traverseDirectory(
2127+
childEntry,
2128+
path + entry.name + '/',
2129+
files
2130+
);
2131+
}
2132+
readEntries(); // Continue reading if there are more entries
2133+
});
2134+
};
2135+
readEntries();
2136+
});
2137+
}
2138+
}
2139+
20522140
// Click on zone to trigger folder selection
20532141
dragDropZone.addEventListener('click', () => {
20542142
if (D.sel) D.sel.click();

0 commit comments

Comments
 (0)