# ПЛАН: компонент выбора файлов/папок/архивов → файловое дерево > Для Flash. Vanilla JS, БЕЗ React и сборщика (как drhider). Новое — только если проще. > Переиспользуемый компонент (слой 1 из `PLAN-upload-layers.md`). ## Решения (фиксировано) | Вопрос | Решение | Почему | |---|---|---| | Стек | **vanilla JS**, один модуль | drhider без сборщика; React избыточен | | ZIP | **`fflate`** (`unzipSync`/`unzip` + `filter`) | заменяет ручной `parseZip` (~200 строк); 8 kB; filter по расширению ДО распаковки | | Выбор папки | `webkitdirectory` (оставить) | уже в drhider, рекурсивно | | Дерево | **свой лёгкий** рендер (ленивый + делегирование) | jsTree старые, react — нет | | Единственная новая зависимость | `fflate` (CDN `unpkg`/`jsdelivr`) | оправдано и проще | ## Модель узла ``` node = { type:'dir'|'zip'|'file', name, path, size, file, children, collapsed } ``` - `path` для file — полный относительный путь: `"Папка/архив.zip/Внутри/файл.txt"`. - Дубль = `path`+`size` → пропуск; имя то же, размер другой → суффикс `_2`. ## API компонента ``` createFilePicker({ container, allowedExt, maxFileBytes, onSelectionChange }) -> { pickFiles(), pickFolder(), getFlatFiles() -> [{path,name,size,file}], // в слой закачки getOverNames(), clear(), setStatus(path, html) } ``` ## Сборка дерева 1. **Папка**: `webkitRelativePath="Top/…"` → отбросить `Top` → вставить по сегментам. 2. **Файлы**: в корень; `.zip` → `fflate.unzip` (рекурсивно по вложенным `.zip`), узел `zip` + дети. 3. **Фильтр**: лист принимается только если расширение ∈ `allowedExt`; `.zip` — ради раскрытия. ## Рендер (сотни файлов) - Свёрнутый `dir`/`zip` **не рендерит детей** (ленивый). - Плоский список «видимых строк» одним проходом (или `DocumentFragment`). - Клики — **делегирование** (один обработчик на контейнер по `data-path`), не сотни слушателей. - `getFlatFiles()` — обход дерева, только листья-файлы. ## Шаги (для Flash) 1. Подключить `fflate` (CDN). Написать обёртку `zip.js`: `listZip(f) -> [{path,name,size,file}]` с `filter` по `allowedExt`. 2. Модель узла + вставка по сегментам пути. 3. Сборка из `folderInput` (webkitRelativePath) и `fileInput` (раскрытие zip рекурсивно). 4. Дедуп (`path`+`size`, суффикс `_2`). 5. Рендер дерева: collapse, ленивый рендер, делегирование кликов. 6. Фильтр `allowedExt` + лимит + статус «пропущен (лимит)». 7. `getFlatFiles()` → слой закачки. ## Чек-лист приёмки - [ ] дерево папок/архивов сворачивается/разворачивается; - [ ] путь файла из архива виден (`Папка/архив.zip/…`); - [ ] дубли исключены, коллизия имени → `_2`; - [ ] `allowedExt` — параметр (фильтр и в zip, и в папке); - [ ] сотни файлов не тормозят (ленивый рендер + делегирование); - [ ] `getFlatFiles()` отдаёт только учитываемые файлы. ## Не делать (не оправдано) - React / сборщик / jQuery-деревья (jsTree, Fancytree). - Виртуализация `react-arborist` — только если появятся тысячи узлов и будет React.