1.6.2: manifiesto firmado, tiempo estimado en tareas, pruebas automáticas
- firma.py: RSA-2048 PKCS#1 v1.5 SHA-256 sin dependencias; empaquetar.py firma el manifiesto y actualizador.py exige la firma (CLAVE_PUBLICA incrustada). - Barra de tareas: tiempo restante estimado a partir del avance. - Corregido: APLICANDO nunca llegaba al total y «Moviendo» quedaba fijo, bloqueando desconectar la carpeta. - probar.py: reglas, firma y recorrido completo sobre una copia temporal. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Este commit está contenido en:
@@ -228,6 +228,7 @@
|
||||
.tarea .b i{display:block;height:100%;background:var(--acc);min-width:2px;transition:width .3s}
|
||||
.tarea .b.ind i{width:30%!important;animation:ind 1.2s infinite linear}
|
||||
.tarea .pct{font-variant-numeric:tabular-nums;color:var(--mut);white-space:nowrap}
|
||||
.tarea .pct small{display:block;font-size:11px;color:var(--mut);font-weight:500;text-align:right}
|
||||
.tarea button{padding:3px 8px;font-size:11.5px}
|
||||
/* avisos */
|
||||
#avisos{position:fixed;right:18px;bottom:60px;display:flex;flex-direction:column;gap:8px;z-index:30;max-width:420px}
|
||||
@@ -558,10 +559,22 @@ function tareasDe(E){
|
||||
const act = E.actualizacion || {}; if (act.estado === 'descargando' || act.estado === 'verificando') T.push({q: 'Descargando versión nueva', d: `${(act.bytes / 1e6).toFixed(0)} de ${(act.total / 1e6).toFixed(0)} MB`, pct: act.pct});
|
||||
return T;
|
||||
}
|
||||
// tiempo restante estimado: se recuerda cuándo se vio cada tarea por primera vez y a qué % iba; con eso se extrapola
|
||||
const ETA = {};
|
||||
function etaDe(t){
|
||||
if (t.pct == null) return '';
|
||||
const k = t.q + '|' + (t.raiz || ''); const ahora = Date.now();
|
||||
const h = ETA[k] && ETA[k].pct <= t.pct ? ETA[k] : (ETA[k] = {t0: ahora, pct: t.pct});
|
||||
const avance = t.pct - h.pct, seg = (ahora - h.t0) / 1000;
|
||||
if (avance < 2 || seg < 8) return '';
|
||||
const resta = seg * (100 - t.pct) / avance;
|
||||
return resta < 60 ? '≈ ' + Math.max(5, Math.round(resta / 5) * 5) + ' s' : resta < 3600 ? '≈ ' + Math.round(resta / 60) + ' min' : '≈ ' + (resta / 3600).toFixed(1) + ' h';
|
||||
}
|
||||
function pintarTareas(){
|
||||
const T = tareasDe(ESTADO);
|
||||
const vivas = new Set(T.map(t => t.q + '|' + (t.raiz || ''))); Object.keys(ETA).forEach(k => { if (!vivas.has(k)) delete ETA[k]; });
|
||||
const caja = $('#tareas'); caja.classList.toggle('on', T.length > 0);
|
||||
caja.innerHTML = '<span class="tit">En curso</span>' + T.map((t, i) => `<div class="tarea run"><div class="w"><div class="q">${esc(t.q)}</div><div class="d" title="${esc(t.d)}">${esc(t.d)}</div><div class="b ${t.pct == null ? 'ind' : ''}"><i style="width:${t.pct == null ? 30 : t.pct}%"></i></div></div>${t.pct != null ? `<span class="pct">${t.pct} %</span>` : ''}${t.cancelar ? `<button data-i="${i}">Detener</button>` : ''}</div>`).join('');
|
||||
caja.innerHTML = '<span class="tit">En curso</span>' + T.map((t, i) => `<div class="tarea run"><div class="w"><div class="q">${esc(t.q)}</div><div class="d" title="${esc(t.d)}">${esc(t.d)}</div><div class="b ${t.pct == null ? 'ind' : ''}"><i style="width:${t.pct == null ? 30 : t.pct}%"></i></div></div>${t.pct != null ? `<span class="pct">${t.pct} %<small>${etaDe(t)}</small></span>` : ''}${t.cancelar ? `<button data-i="${i}">Detener</button>` : ''}</div>`).join('');
|
||||
$$('#tareas button').forEach(b => b.onclick = () => accion(b, async () => { await T[+b.dataset.i].cancelar(); await cargarEstado(); }));
|
||||
}
|
||||
|
||||
|
||||
Referencia en una nueva incidencia
Block a user