Fix async picker race

This commit is contained in:
“Naeel”
2026-09-05 12:31:17 +03:00
parent eda5263d8b
commit 1e305485be
4 changed files with 75 additions and 44 deletions
+8 -2
View File
@@ -25,7 +25,13 @@ export async function addFiles(state, cfg, files, elements) {
}
export function onFilesChange(state, cfg, elements) {
return () => {
if (!state.busy) addFiles(state, cfg, elements.fileInputEl.files, elements);
return async () => {
if (state.busy) return;
state.busy = true;
try {
await addFiles(state, cfg, elements.fileInputEl.files, elements);
} finally {
state.busy = false;
}
};
}
+46 -41
View File
@@ -12,49 +12,54 @@ function rebaseTree(root, prefix) {
export function onFolderChange(state, cfg, elements) {
return async () => {
if (state.busy) return;
const roots = new Map();
for (const file of Array.from(elements.folderInputEl.files)) {
const parts = (file.webkitRelativePath || file.name).split('/');
const relativePath = parts.slice(1).join('/') || file.name;
const lowerPath = relativePath.toLowerCase();
const rootName = parts[0] || file.name;
if (!roots.has(rootName)) {
roots.set(rootName, { id: crypto.randomUUID(), kind: 'folder', name: rootName,
path: rootName, children: [], expanded: true });
}
const root = roots.get(rootName);
const addToFolder = (node) => {
let current = root;
const nodeParts = node.path.split('/').slice(1);
nodeParts.forEach((part, index) => {
const last = index === nodeParts.length - 1;
let child = current.children.find((item) => item.name === part);
if (!child) {
child = last ? node : { id: crypto.randomUUID(), kind: 'folder', name: part,
path: `${rootName}/${nodeParts.slice(0, index + 1).join('/')}`,
children: [], expanded: true };
current.children.push(child);
}
current = child;
});
};
if (lowerPath.endsWith('.zip')) {
try {
const zip = await listZipFiles(file, cfg.allowedExt);
if (zip) {
rebaseTree(zip, rootName);
addToFolder(zip);
}
} catch (error) {
continue;
state.busy = true;
try {
const roots = new Map();
for (const file of Array.from(elements.folderInputEl.files)) {
const parts = (file.webkitRelativePath || file.name).split('/');
const relativePath = parts.slice(1).join('/') || file.name;
const lowerPath = relativePath.toLowerCase();
const rootName = parts[0] || file.name;
if (!roots.has(rootName)) {
roots.set(rootName, { id: crypto.randomUUID(), kind: 'folder', name: rootName,
path: rootName, children: [], expanded: true });
}
const root = roots.get(rootName);
const addToFolder = (node) => {
let current = root;
const nodeParts = node.path.split('/').slice(1);
nodeParts.forEach((part, index) => {
const last = index === nodeParts.length - 1;
let child = current.children.find((item) => item.name === part);
if (!child) {
child = last ? node : { id: crypto.randomUUID(), kind: 'folder', name: part,
path: `${rootName}/${nodeParts.slice(0, index + 1).join('/')}`,
children: [], expanded: true };
current.children.push(child);
}
current = child;
});
};
if (lowerPath.endsWith('.zip')) {
try {
const zip = await listZipFiles(file, cfg.allowedExt);
if (zip) {
rebaseTree(zip, rootName);
addToFolder(zip);
}
} catch (error) {
continue;
}
} else if (cfg.allowedExt.some((extension) => lowerPath.endsWith(extension))) {
addToFolder({ id: crypto.randomUUID(), kind: 'file', name: parts.at(-1),
path: `${rootName}/${relativePath}`, file, children: [], expanded: true });
}
} else if (cfg.allowedExt.some((extension) => lowerPath.endsWith(extension))) {
addToFolder({ id: crypto.randomUUID(), kind: 'file', name: parts.at(-1),
path: `${rootName}/${relativePath}`, file, children: [], expanded: true });
}
roots.forEach((root) => addFileWithDedup(state, root));
elements.folderInputEl.value = '';
render(state, elements);
} finally {
state.busy = false;
}
roots.forEach((root) => addFileWithDedup(state, root));
elements.folderInputEl.value = '';
render(state, elements);
};
}