From bee7f8f245acd9bdbbf18694f274a7ca20f75572 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cau=C3=AA=20Faleiros?= Date: Wed, 30 Sep 2026 15:18:21 -0300 Subject: [PATCH] feat: the preview of a large file says how long is left, not a percentage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reading a large PNG in the browser for its preview showed "gerando a prévia… 87%". It now shows the time left, worked out from how long the reading has taken so far: "faltam cerca de 25 s", "faltam cerca de 3 min", "quase pronto". The bar still fills as it goes. Co-Authored-By: Claude Opus 5.5 --- web/site-config.js | 7 +++++++ web/site-pdf.js | 6 +++--- web/site-upload.js | 6 ++++-- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/web/site-config.js b/web/site-config.js index 826f668..155cb80 100644 --- a/web/site-config.js +++ b/web/site-config.js @@ -131,6 +131,13 @@ const duracao=s=>{ }; const faixaEnvio=bytes=>bytes/ENVIO_RAPIDO<60 ? 'até '+duracao(bytes/ENVIO_LENTO) : 'de '+duracao(bytes/ENVIO_RAPIDO)+' a '+duracao(bytes/ENVIO_LENTO); +// Quanto falta para ler um arquivo grande no navegador, pelo ritmo até aqui. +// A leitura é quase linear, então o tempo gasto diz o que resta. +function faltaLeitura(l){ + if(!l || !(l.p>0.02)) return 'calculando o tempo…'; + const s=(Date.now()-l.inicio)/1000*(1-l.p)/l.p; + return s<10 ? 'quase pronto' : s<60 ? 'faltam cerca de '+Math.ceil(s/5)*5+' s' : 'faltam cerca de '+duracao(s); +} const larguraFilme=()=>MODOS[modo].larg; // cobrança proporcional: arredonda para cima em 10 cm · 2,75 m vira 2,80 m const cobrar=m=>Math.max(MINIMO_M, Math.ceil(m*10)/10); diff --git a/web/site-pdf.js b/web/site-pdf.js index ee0692f..18e8ade 100644 --- a/web/site-pdf.js +++ b/web/site-pdf.js @@ -353,7 +353,7 @@ function medirFolha(file){ } function textoProgresso(x){ - if(x.med && x.med.grande) return 'gerando a prévia e conferindo a arte… '+x.pct+'%'; + if(x.med && x.med.grande) return 'gerando a prévia e conferindo a arte · '+faltaLeitura(x.leitura); return x.pct<50?'lendo o arquivo…':x.pct<70?'medindo a folha…':'conferindo a arte…'; } // The file card's thumbnail (52 x 96 px, drawn at twice that for sharp screens). @@ -524,7 +524,7 @@ function pintaProgressoArte(a){ const el=$('lista').querySelector('[data-arte="'+artes.indexOf(a)+'"]'); const barra=el && el.querySelector('.prog i'), texto=el && el.querySelector('.progT'); if(!barra){ pintaArtes(); return; } - barra.style.width=a.lendo+'%'; if(texto) texto.textContent='arquivo grande · gerando a prévia… '+a.lendo+'%'; + barra.style.width=a.lendo+'%'; if(texto) texto.textContent='arquivo grande · gerando a prévia · '+faltaLeitura(a.leitura); } function pintaArtes(){ invalidaItemAtual(); @@ -538,7 +538,7 @@ function pintaArtes(){ let barra='', dica='', chips='', aviso='', medida='Informe a largura'; if(a.lendo!=null){ barra='
'+ - 'arquivo grande · gerando a prévia… '+a.lendo+'%'; + 'arquivo grande · gerando a prévia · '+faltaLeitura(a.leitura)+''; }else if(a.decodeError){ aviso='

Não conseguimos ler esta imagem. Exporte novamente em PNG ou JPG.

'; }else if(a.cm>larguraFilme()){ diff --git a/web/site-upload.js b/web/site-upload.js index ddbcdd3..7d3af72 100644 --- a/web/site-upload.js +++ b/web/site-upload.js @@ -65,10 +65,11 @@ function sel(fs){ x.an={dpi:md.dpiFolha, grande:true, artes:0, residuos:0, encostadas:0, fundoChapado:false, aproveitamento:0, alturaCm:md.alt, fonteDpi:'arquivo'}; if(!/\.png$/i.test(x.f.name)){ x.pct=null; pintaFolha(); return; } - x.pct=60; pintaFolha(); + x.pct=60; x.leitura={inicio:Date.now(), p:0}; pintaFolha(); let mostrado=0; previaPngGrande(x.f, 600, p=>{ const pct=60+Math.floor(p*38); + x.leitura.p=p; if(pct-mostrado>=1){ mostrado=pct; x.pct=pct; pintaProgressoFolha(x); } }).then(cv=>{ if(cv && folhas.includes(x)){ @@ -131,10 +132,11 @@ function medir(a){ // JPG and WebP cannot be read in parts: the art is placed by its // measurements, as a full box, and the team checks it before printing. if(!/\.png$/i.test(a.f.name)){ a.semPrevia=true; return a; } - a.lendo=0; pintaArtes(); + a.lendo=0; a.leitura={inicio:Date.now(), p:0}; pintaArtes(); let mostrado=0; const cv=await previaPngGrande(a.f, 1200, p=>{ const pct=Math.floor(p*100); + a.leitura.p=p; if(pct-mostrado>=1){ mostrado=pct; a.lendo=pct; pintaProgressoArte(a); } }).catch(()=>null); a.lendo=null;