diff --git a/deploy/files.js b/deploy/files.js index 0410baa..cb5f2a9 100644 --- a/deploy/files.js +++ b/deploy/files.js @@ -305,10 +305,10 @@ function applyParseResult(entry, parsed, elapsed) { async function addZipFile(file) { var zipEntry = { name: file.name, lastModified: file.lastModified, size: file.size, status: { kind: 'unzipping' } }; state.files.push(zipEntry); - var zipIdx = state.files.length - 1; render(state); try { + // Шаг 1: распаковать ZIP на бэкенде var zipResp = await new Promise(function(resolve, reject) { var xhr = new XMLHttpRequest(); xhr.open('POST', UNZIP_URL); @@ -323,16 +323,17 @@ async function addZipFile(file) { }); if (!zipResp.ok || !zipResp.files) throw new Error('unzip failed'); - // Убрать временную строку ZIP - state.files.splice(zipIdx, 1); - render(state); - - // Каждый файл из архива — через addRegularFile (единый путь) - for (var zi = 0; zi < zipResp.files.length; zi++) { + // Шаг 2: обработать каждый файл из архива + // Временная строка ZIP остаётся в таблице — обновляем её статус + var total = zipResp.files.length; + for (var zi = 0; zi < total; zi++) { var zf = zipResp.files[zi]; + zipEntry.status = { kind: 'unzipping' }; // обновляем статус + render(state); + if (zf.error) continue; - // base64 → Blob → File + // base64 → File → addRegularFile (единый путь) var byteStr = atob(zf.data_b64); var bytes = new Uint8Array(byteStr.length); for (var b = 0; b < byteStr.length; b++) bytes[b] = byteStr.charCodeAt(b); @@ -341,8 +342,15 @@ async function addZipFile(file) { await addRegularFile(extractedFile); } + + // Шаг 3: убрать временную строку ZIP (только после успешной обработки всех файлов) + var zipPos = state.files.indexOf(zipEntry); + if (zipPos >= 0) state.files.splice(zipPos, 1); + render(state); + } catch(ze) { - state.files[zipIdx].status = { kind: 'error', text: 'ZIP: ' + ze.message }; + // Ошибка — показать на строке ZIP (zipEntry всё ещё в state.files) + zipEntry.status = { kind: 'error', text: 'ZIP: ' + ze.message }; render(state); } }