/* Site DTF — Accepting files: the drop zone, the accept rules, first measurement. Extracted verbatim from the single inline script in web/index.html. Loaded as classic scripts in the order listed there: they share one global scope and run top to bottom, exactly as the original did. */ // ── upload // Untrusted filenames and recovered cart text must never become HTML. function escapeHTML(value){ return String(value).replace(/[&<>"']/g,c=>({'&':'&','<':'<','>':'>','"':'"',"'":'''}[c])); } function recusa(lista){ const el=$('recusa'); if(!el) return; if(!lista.length){ el.style.display='none'; el.innerHTML=''; return; } const exts=escapeHTML([...new Set(lista.map(f=>extDe(f.name)))].join(', ')); el.style.display='block'; el.innerHTML = ehFolha() ? ''+exts+' não dá para enviar aqui. A folha pronta aceita PNG, JPG, TIFF, '+ 'PDF, PSD, AI e CDR.' : ''+exts+' não dá para enviar aqui. Artes avulsas precisam de PNG ou JPG com '+ 'fundo transparente — é o que a montagem enxerga para encaixar. '+ 'Se o seu arquivo é CDR, AI ou PSD, exporte em PNG ou use Arquivo por metro.'; } const Z=$('zona'), I=$('inp'); Z.addEventListener('click',()=>I.click()); Z.addEventListener('keydown',e=>{if(e.key==='Enter'||e.key===' '){I.click();e.preventDefault();}}); ['dragover','dragenter'].forEach(ev=>Z.addEventListener(ev,e=>{e.preventDefault();Z.classList.add('sobre')})); ['dragleave','drop'].forEach(ev=>Z.addEventListener(ev,e=>{ e.preventDefault(); Z.classList.remove('sobre'); if(ev==='drop') sel([...e.dataTransfer.files]); })); I.addEventListener('change',()=>sel([...I.files])); function sel(fs){ if(!fs.length) return; // Pixels cannot tell a loose artwork from a finished sheet, so the customer // declares it by choosing the product in the selector above. The declaration is // verified in medirFolha; the file never changes product or price on its own. const regra = ehFolha() ? ACEITA.folha : ACEITA.avulsa; const fora = fs.filter(f=>!regra.test(f.name)); fs = fs.filter(f=>regra.test(f.name)); recusa(fora); const max=window.dtfUploadMaxBytes||128*1048576; const grandes=fs.filter(f=>f.size>max); if(grandes.length){ const el=$('recusa'); el.style.display='block'; el.innerHTML='Arquivo acima do limite de '+(max/1048576).toFixed(0)+ ' MB. A verificação de segurança ainda não consegue liberar arquivos maiores. '+ 'Divida ou compacte a arte antes de enviar.'; fs=fs.filter(f=>f.size<=max); } if(!fs.length) return; if(ehFolha()){ const auto=fs.filter(f=>AUTO.test(f.name)).length; const manual=fs.length-auto; if(caminho==='auto' && manual){ caminho='tabela'; avisoCam('Trocamos o caminho para você. Você marcou conferência automática, '+ 'mas '+(manual>1? manual+' arquivos vieram':'o arquivo veio')+' em formato que não '+ 'abrimos. O metro vai pela tabela, '+rs(TABELA[modo])+'.'); pintaCaminhos(); }else if(caminho==='tabela' && auto){ caminho='auto'; avisoCam('Boa notícia. Você marcou o caminho sem conferência, mas '+ (auto>1? 'os arquivos vieram':'o arquivo veio')+' em formato que a gente confere. '+ 'Vamos avaliar e o metro pode cair até '+rs(pisoEscada())+'.'); pintaCaminhos(); } const novas=fs.map(f=>({f, med:null, rep:1, m:0, semAnalise:null})); folhas=folhas.concat(novas); // soma, não substitui pintaFolha(); novas.forEach(x=>{ x.pct=5; pintaFolha(); medirFolha(x.f).then(md=>{ if(md && md.rejected){ x.measurementError=md.reason; x.pct=null; pintaFolha(); return; } if(md && md.dpiFolha!=null && md.dpiFolha{ if(img){ x.previewSrc=img.src; try{ x.an=analisarFolha(img, md.larg); if(x.an) x.an.fonteDpi='arquivo'; } catch(e){} } x.pct=null; pintaFolha(); }); }else if(md && /\.pdf$/i.test(x.f.name)){ x.pct=70; pintaFolha(); rasterizarPdf(x.f, md.larg, md.alt).then(r=>{ if(r && r.erro){ x.semAnalise = r.erro + (r.semWorker ? ' · este navegador não deixa o leitor rodar em segundo plano' : ''); } if(r && r.tela){ try{ x.an=analisarFolha(r.tela, md.larg); // vetor puro não tem resolução · nota máxima, e está certo x.an.dpi = r.dpi==null ? DPI_AVISA : r.dpi; x.an.vetor = r.dpi==null; x.an.fonteDpi = r.dpi==null ? 'vetor' : 'imagens'; x.an.res = r.res || null; }catch(e){} } x.pct=null; pintaFolha(); }); }else{ x.pct=null; pintaFolha(); } }); }); return; } const novos=fs.map(f=>({f,px:0,py:0,cm:0,q:1,prop:1,giro:0,esp:false})); artes=novos.concat(artes); // a mais recente fica no topo da fila recemChegada=novos[0]; pintaArtes(); $('lista').scrollIntoView({behavior:'smooth',block:'nearest'}); Promise.all(novos.map(medir)).then(pintaArtes); } function medir(a){ return carregarImagem(a.f).then(img=>{ if(img){ a.prop=img.height/img.width; a.px=img.width; a.py=img.height; a.src=img.src; } else a.decodeError=true; return a; }); } // A metragem sai do arquivo, nunca do peso em bytes. // imagem → proporção da imagem aplicada à largura do filme // PDF → página única lida pelo PDF.js, com boxes, rotação e UserUnit // TIFF, PSD, AI, CDR → o navegador não abre; o cliente informa o comprimento