6.0 KiB
6.0 KiB
План для Flash: выбор целой папки рекурсивно (v0.0.68)
Самодостаточный план. Файл:
site/templates/index.html(весь фронт — ванильный JS, без сборки). Текущая версия 0.0.67 → поднять до 0.0.68 (вsite/app.pyVERSION).
Задача
Кнопка «📁 Выбрать папку»: юзер выбирает папку → в таблицу рекурсивно добавляются ВСЕ файлы
(включая вложенные подпапки), как сейчас раскрываются ZIP. Относительный путь сохраняется
(без имени верхней выбранной папки): Подпапка/Внутри/report.pdf.
Что уже есть (ориентиры в index.html)
<input type="file" id="fileInput" multiple accept=".doc,.docx,.pdf,.txt,.zip">в.file-input-wrap.const fi = document.getElementById('fileInput');(в начале<script>).fi.addEventListener('change', async () => {...})— текущий обработчик: для.zip→listZipFiles(f)(раскрывает архив, возвращаетFile[]), иначеaddFileWithDedup(f); в конце пересобираетDataTransfer,rr().addFileWithDedup(file)— дедуп поfile.name+file.size, лимитыMAX_FILE_BYTES/MAX_SESSION_BYTES,overNames.listZipFiles(file)— рекурсивно раскрывает.zip(в т.ч. вложенные), фильтрует только документы['.pdf','.doc','.docx','.txt','.md'], возвращаетFile[](имена = пути внутри архива).busy— флаг «идёт загрузка/обработка»; естьsetBusy(b), guard'ы вchangeиrm.- Footer:
<div class="footer-bar">содержитfileCount,cancelBtn,newSessionBtn,uploadBtn.
Реализация
1. HTML — кнопка и скрытый input
- В
.file-input-wrap(рядом с кнопкой «Choose File», т.е.#fileInput) добавить кнопку:<button type="button" class="btn" id="folderBtn">📁 Выбрать папку</button> - Добавить скрытый input (вне/внутри формы без разницы):
<input type="file" id="folderInput" webkitdirectory style="display:none"> folderBtn.onclick = () => folderInput.click();
2. JS — ссылки и обработчик
const folderInput = document.getElementById('folderInput');const DOC_EXTS = ['.pdf', '.doc', '.docx', '.txt', '.md'];(можно переиспользовать из listZipFiles — там это локальная константаallowedExt; продублировать на верхнем уровне или вынести).folderInput.addEventListener('change', async () => { ... }):if (busy) return;const files = Array.from(folderInput.files);— у каждого естьfile.webkitRelativePath(видаTopFolder/Подпапка/report.pdf).- Для каждого файла:
- Определить
rel = file.webkitRelativePath.split('/')и отбросить первый сегмент (верхняя папка):rel = rel.slice(1).join('/'). const low = rel.toLowerCase();- Если
.zip→const nested = await listZipFiles(file);затем для каждогоnfсоздатьnew File([nf], rel_dir + '/' + nf.name, {lastModified: nf.lastModified}), гдеrel_dir = rel.slice(0, rel.lastIndexOf('/'))(папка, в которой лежал zip; если в корне — пусто), иaddFileWithDedup(that). Обернуть в try/catch: при ошибке раскрытия добавить сам.zipкак есть (по аналогии с текущим обработчиком). - Иначе если
DOC_EXTS.some(e => low.endsWith(e))→addFileWithDedup(new File([file], rel, {lastModified: file.lastModified})). - Иначе — пропустить (не документ).
- Определить
- В конце — показать индикатор «Разбираю папку…» на время обработки (как с ZIP:
document.body.style.cursor='wait'+st), затемrr().
- Показать индикатор до цикла, сбросить в
finally(как текущий change-обработчик).
3. Важные детали
- Дедуп/лимиты:
addFileWithDedupуже работает поfile.name; так как имя = относительный путь, файлы из разных подпапок не сливаются. Лимиты 50МБ/500МБ применяются автоматически. - Имя в таблице и в выходном ZIP = относительный путь (с
/). Это ожидаемо. webkitdirectory: поддерживается Chrome/Edge (полно), Firefox (частично), Safari — нет. Best-effort, ничего не ломается в неподдерживаемых браузерах (кнопка просто не откроет выбор папки).- Guard
busy: во время загрузки/обработки выбор папки не должен работать (как и обычный input).
4. Версия и проверка
site/app.py:VERSION = "0.0.68".- Проверки:
python3 -m py_compile site/app.py;node --checkна извлечённом<script>(как обычно). - Тест вручную/браузером: папка с подпапками + вложенный zip + кириллические имена → все файлы в таблице с относительными путями, дедуп/лимиты работают.
Не трогать
- Логику обфускации, SSE, сессии, лимиты — только добавить кнопку/input/обработчик выбора папки.