Files
drhider/History/plans/2026-08-24-folder-select-plan.md
T

64 lines
6.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# План для Flash: выбор целой папки рекурсивно (v0.0.68)
> Самодостаточный план. Файл: `site/templates/index.html` (весь фронт — ванильный JS, без сборки).
> Текущая версия 0.0.67 → поднять до **0.0.68** (в `site/app.py` `VERSION`).
## Задача
Кнопка «📁 Выбрать папку»: юзер выбирает папку → в таблицу рекурсивно добавляются ВСЕ файлы
(включая вложенные подпапки), как сейчас раскрываются 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 () => { ... })`:
1. `if (busy) return;`
2. `const files = Array.from(folderInput.files);`у каждого есть `file.webkitRelativePath` (вида `TopFolder/Подпапка/report.pdf`).
3. Для каждого файла:
- Определить `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}))`.
- Иначе — пропустить (не документ).
4. В конце — показать индикатор «Разбираю папку…» на время обработки (как с 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/обработчик выбора папки.