/* ==========================================================================
js/render.js — dueño B: pinta el chat de WhatsApp dentro del iPhone.
API (SPEC §2): WAM.render / renderHeader / renderMensaje / anadirMensajeDOM /
setTema / setEscribiendo / scrollAbajo / abrirSheet / cerrarSheet / tick.
Campos por tipo: SPEC §1. Colores, geometría y tipografía: docs/research-ui.md.
Cero listeners de flujo (los clics los resuelve js/interactivity.js con los
data-* estampados aquí; main.js abre el sheet del list con el data-flujo
"plano" del botón). Listeners propios: cierre en #sheet-fondo (elemento
creado por B), scroll de puntos del carousel y despliegue del plegado
">3 botones". No toca DOM al cargar.
========================================================================== */
(function () {
"use strict";
window.WAM = window.WAM || {};
/* ------------------------------ helpers ------------------------------ */
function byId(id) { return document.getElementById(id); }
function esc(s) {
return String(s == null ? "" : s).replace(/[&<>"']/g, function (c) {
return { "&": "&", "<": "<", ">": ">", '"': """, "'": "'" }[c];
});
}
function vacio(s) { return s == null || String(s) === ""; }
function estado() { return WAM.estado || { cuenta: {}, mensajes: [] }; }
var ESCRIBIENDO = false;
/* Placeholder local; en la práctica usa WAM.svgPlaceholder (js/store.js). */
function placeholder(texto) {
if (typeof WAM.svgPlaceholder === "function") {
try {
var u = WAM.svgPlaceholder(String(texto == null ? "" : texto));
if (u) return u;
} catch (e) { /* fallback abajo */ }
}
var t = esc(String(texto == null ? "" : texto).slice(0, 42));
var svg = '";
return "data:image/svg+xml," + encodeURIComponent(svg);
}
/* ------------------------------ iconos SVG inline ------------------------------ */
function svgChevronAtras() {
return '';
}
function svgChevronDer(px) {
var s = px || 14;
return '';
}
function svgVideoLlamada() {
return '';
}
function svgLlamada(px) {
var s = px || 23;
return '';
}
function svgVerificado() {
return '';
}
function svgPlay(px) {
var s = px || 18;
return '';
}
function svgMicrofono(px) {
var s = px || 19;
return '';
}
function svgMusica(px) {
var s = px || 19;
return '';
}
function svgDescarga(px) {
var s = px || 15;
return '';
}
function svgEnlace(px) {
var s = px || 18;
return '';
}
function svgCorreo(px) {
var s = px || 15;
return '';
}
function svgEmpresa(px) {
var s = px || 15;
return '';
}
/* Icono de página coloreado por extensión (research-ui §6.6) */
var COLORES_DOC = {
pdf: "#e2574c", doc: "#4577e0", docx: "#4577e0",
xls: "#2f9e5b", xlsx: "#2f9e5b", csv: "#2f9e5b",
ppt: "#e5813d", pptx: "#e5813d",
txt: "#8592a0", zip: "#a5855e", rar: "#a5855e"
};
function extDe(nombre) {
var n = String(nombre == null ? "" : nombre);
var partes = n.split(".");
return partes.length > 1 ? partes.pop().toLowerCase() : "doc";
}
function docIcon(ext, px) {
var w = px || 30;
var h = Math.round(w * 36 / 30);
var color = COLORES_DOC[ext] || "#7c8894";
var etiqueta = ext.length <= 4 ? ext.toUpperCase() : "DOC";
return '";
}
/* Mapa estático con pin rojo (research-ui §6.8, data-URI sin red) */
function svgMapa() {
var svg = '";
return "data:image/svg+xml," + encodeURIComponent(svg);
}
/* ------------------------------ texto enriquecido ------------------------------ */
/* Formato WhatsApp (research-api §2): *negrita* _cursiva_ ~tachado~ ```mono```
+ URLs hipervinculadas (color --wa-link, sin subrayado). */
function formatear(txt) {
var partes = String(txt == null ? "" : txt).split(/(https?:\/\/[^\s<>"]+)/g);
var html = "";
for (var i = 0; i < partes.length; i++) {
var p = partes[i];
if (p === "") continue;
if (/^https?:\/\//.test(p)) {
html += '' + esc(p) + "";
} else {
var t = esc(p);
t = t.replace(/```([\s\S]+?)```/g, "$1");
t = t.replace(/\*([^*\n]+)\*/g, "$1");
t = t.replace(/(^|[^\w])_([^_\n]+)_(?=[^\w]|$)/g, "$1$2");
t = t.replace(/(^|[^\w])~([^~\n]+)~(?=[^\w]|$)/g, "$1$2");
html += t;
}
}
return html;
}
/* ------------------------------ ticks y meta ------------------------------ */
/* ✓ enviado (gris) / ✓✓ entregado (gris) / ✓✓ leído (celeste #53bdeb) */
var TRAZO_TICK = '';
WAM.tick = function (estadoTick) {
var uno = '";
var dos = '';
if (estadoTick === "read") return dos.replace('class="tick"', 'class="tick tick-read"');
if (estadoTick === "delivered") return dos;
return uno;
};
/* Hora (+ ticks solo en OUT) dentro de la burbuja */
function metaHTML(m, extra) {
var mm = m || {};
var html = '' + esc(vacio(mm.hora) ? "" : mm.hora);
if (mm.dir === "out") html += WAM.tick(mm.estado || "sent");
return html + "";
}
/* ------------------------------ piezas de burbujas ------------------------------ */
function insigniaPlay(px) {
return '' + svgPlay(px || 26) + "";
}
function burbujaTexto(m) {
return '
' + formatear(m.texto) + metaHTML(m) + "
";
}
/* image / video: media full-bleed; caption debajo; hora encima o en caption.
El placeholder SVG (data:image/svg+xml) solo lo decodifican los : un