import { listZipFiles } from '../zip/list_zip_files.js'; import { addFileWithDedup } from './add_file_with_dedup.js'; import { render } from './render.js'; function rebaseTree(root, prefix) { root.path = `${prefix}/${root.path}`; if (root.file) root.file = new File([root.file], root.path, { lastModified: root.file.lastModified }); root.children.forEach((child) => rebaseTree(child, prefix)); return root; } 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; } } 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); }; }