Demo con contador de pasos e icono de detener, horas de sesión coherentes, IDs de sesión sin choques, URLs bloqueadas inertes, recortes de importación contados y sesionAGuion con deshacer

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
urieljareth
2026-09-27 21:09:42 -06:00
co-authored by Claude Opus 5.5
parent 9a5f21badf
commit c0b7d0c2ce
4 changed files with 189 additions and 26 deletions
+56 -8
View File
@@ -27,7 +27,42 @@ window.WAM = window.WAM || {};
/* Mensajes de la sesión en curso (efímeros). */
WAM.sesion = [];
var contSesion = 0;
function idSesion() { contSesion++; return "s" + contSesion; }
/* IDs del guion (mensajes, respuestas, botones, filas, cards) para que un
ID de sesión nunca coincida con uno importado (p. ej. un guion con "s1"). */
function idsDelGuion() {
var usados = new Set();
(function recorrer(o) {
if (!o || typeof o !== "object") return;
if (Array.isArray(o)) { for (var i = 0; i < o.length; i++) recorrer(o[i]); return; }
if (typeof o.id === "string" && o.id) usados.add(o.id);
["mensajes", "respuestas", "botones", "secciones", "filas", "cards"].forEach(function (k) {
if (o[k] && typeof o[k] === "object") recorrer(o[k]);
});
})(WAM.estado);
return usados;
}
function idSesion() {
var usados = WAM.estado ? idsDelGuion() : null;
var id;
do { contSesion++; id = "s" + contSesion; } while (usados && usados.has(id));
return id;
}
/* Hora para los mensajes de un flujo: la del último mensaje visible + 1 min,
para que la línea temporal de la demo siga siendo coherente (si no hay
ninguna hora legible, el reloj real). */
function horaTras() {
var metas = document.querySelectorAll("#chat-cuerpo .wa-row .meta");
var t = null;
for (var i = metas.length - 1; i >= 0 && !t; i--) {
t = String(metas[i].textContent || "").match(/(\d{1,2}):(\d{2})/);
}
if (!t) return WAM.horaAhora();
var min = (Number(t[1]) * 60 + Number(t[2]) + 1) % 1440;
return ("0" + Math.floor(min / 60)).slice(-2) + ":" + ("0" + (min % 60)).slice(-2);
}
/* ————————————————— temporizadores cancelables por grupo ————————————————— */
@@ -215,12 +250,12 @@ window.WAM = window.WAM || {};
return pintar(msg);
}
function mensajeOut(texto, cita) {
function mensajeOut(texto, cita, hora) {
var msg = {
id: idSesion(),
dir: "out",
tipo: "text",
hora: WAM.horaAhora(),
hora: hora || WAM.horaAhora(),
estado: "sent",
texto: String(texto == null ? "" : texto)
};
@@ -243,7 +278,7 @@ window.WAM = window.WAM || {};
if (TIPOS_VALIDOS.indexOf(copia.tipo) === -1) copia.tipo = "text";
copia.id = idSesion();
copia.dir = "in";
copia.hora = WAM.horaAhora();
copia.hora = horaTras();
copia.estado = "sent";
delete copia.cita;
return copia;
@@ -413,7 +448,7 @@ window.WAM = window.WAM || {};
WAM.flujo = function (texto, respuestas, cita) {
var lista = Array.isArray(respuestas) ? respuestas : [];
var ctx = contexto("flujo");
var out = mensajeOut(texto, cita || null);
var out = mensajeOut(texto, cita || null, horaTras());
anadirSesion(out);
var tics = animarTics(out, ctx);
tics.catch(nada);
@@ -460,7 +495,8 @@ window.WAM = window.WAM || {};
if (ds.btn !== undefined) {
var n = parseInt(ds.btn, 10);
var boton = (msg.botones || [])[n];
if (!boton) return vacioR;
/* botón de enlace con URL bloqueada: inerte, nunca un quick reply */
if (!boton || boton.urlBloqueada) return vacioR;
return {
texto: vacio(boton.texto) ? "Botón " + (n + 1) : String(boton.texto),
respuestas: boton.respuestas || [],
@@ -472,7 +508,7 @@ window.WAM = window.WAM || {};
if (ds.card !== undefined) {
var c = parseInt(ds.card, 10);
var card = (msg.cards || [])[c];
if (!card) return vacioR;
if (!card || card.urlBloqueada) return vacioR;
return {
texto: vacio(card.textoBoton) ? "Ver más" : String(card.textoBoton),
respuestas: card.respuestas || [],
@@ -509,11 +545,13 @@ window.WAM = window.WAM || {};
return copia;
});
var n = nuevos.length;
if (typeof WAM.puntoDeshacer === "function") { try { WAM.puntoDeshacer(); } catch (e) { /* opcional */ } }
WAM.estado = WAM.normalizar ? WAM.normalizar({
version: WAM.estado.version, tema: WAM.estado.tema, cuenta: WAM.estado.cuenta,
mensajes: WAM.estado.mensajes.concat(nuevos)
}) : WAM.estado;
if (typeof WAM.guardar === "function") WAM.guardar();
if (typeof WAM.marcarEditado === "function") { try { WAM.marcarEditado(); } catch (e) { /* opcional */ } }
if (typeof WAM.render === "function") WAM.render();
if (typeof WAM.renderEditor === "function") WAM.renderEditor();
return n;
@@ -594,7 +632,7 @@ window.WAM = window.WAM || {};
async function flujoEnDemo(sel, ctx) {
if (!sel || !sel.msg) return;
var out = mensajeOut(sel.texto, sel.cita);
var out = mensajeOut(sel.texto, sel.cita, horaTras());
anadirSesion(out);
await animarTics(out, ctx);
await responder(Array.isArray(sel.respuestas) ? sel.respuestas : [], ctx, true);
@@ -609,6 +647,12 @@ window.WAM = window.WAM || {};
}
}
/* Progreso de la demo: mensajes del guion revelados / total. */
var progreso = { paso: 0, total: 0 };
WAM.progresoDemo = function () {
return demoAndando ? { paso: progreso.paso, total: progreso.total } : { paso: 0, total: 0 };
};
WAM.reproducirDemo = function () {
if (demoAndando) return;
/* aborta flujos, ticks y typing en curso: no se mezclan con la demo */
@@ -621,6 +665,8 @@ window.WAM = window.WAM || {};
vaciarChat();
var ctx = contexto("demo");
var secuencia = ((WAM.estado && WAM.estado.mensajes) || []).slice();
progreso.paso = 0;
progreso.total = secuencia.length;
(async function () {
try {
for (var i = 0; i < secuencia.length; i++) {
@@ -629,6 +675,8 @@ window.WAM = window.WAM || {};
if (msg.dir === "in") await escribirDurante(ctx, 700);
if (!ctx.vivo()) throw CANCELADO;
pintar(msg);
progreso.paso = i + 1;
avisarDemo();
await ctx.esperar(600);
await autoPulsar(msg, ctx);
}