// Обработчик change: дедуп + раскрытие ZIP + фильтр. // Экспортируется и чистая логика добавления массива файлов (addFiles), // и фабрика обработчика для input (makeFilesChangeHandler). import { listZipFiles } from '../zip/list_zip_files.js'; import { addFileWithDedup } from './add_file_with_dedup.js'; import { render } from './render.js'; // Добавить массив файлов в список (дедуп + раскрытие ZIP + лимиты). // files: File[]. els.fileInput — для синхронизации input.files (DataTransfer), // чтобы повторный выбор того же файла сработал. onStatus(cls, text) — колбэк сообщений. export async function addFiles(state, cfg, files, els, onStatus) { const incoming = Array.from(files); const hasZip = incoming.some(f => f.name.toLowerCase().endsWith('.zip')); if (hasZip) { document.body.style.cursor = 'wait'; if (onStatus) onStatus('progress', 'Разбираю архивы…'); } try { for (const f of incoming) { if (f.name.toLowerCase().endsWith('.zip')) { try { const nested = await listZipFiles(f, cfg.allowedExt); if (nested.length) nested.forEach(x => addFileWithDedup(state, x, cfg)); else addFileWithDedup(state, f, cfg); // в архиве нет документов — архив как есть } catch (err) { addFileWithDedup(state, f, cfg); // не удалось распаковать — zip как есть } } else { addFileWithDedup(state, f, cfg); } } } finally { if (hasZip) { document.body.style.cursor = ''; if (onStatus) onStatus('', ''); } } // Синхронизировать input.files — чтобы повторный выбор того же файла сработал if (els && els.fileInput && els.fileInput.files) { const d = new DataTransfer(); state.files.forEach(f => d.items.add(f)); els.fileInput.files = d.files; } render(state, els, cfg); } // Фабрика обработчика change для . // ctx = { state, cfg, els, onStatus } export function makeFilesChangeHandler(ctx) { const { state, cfg, els, onStatus } = ctx; return () => { if (state.busy) return; // во время загрузки/обработки менять список нельзя addFiles(state, cfg, els.fileInput.files, els, onStatus); }; }