@@ -2328,7 +2339,9 @@
replyHtml = `
En respuesta a: ${window.escapeHtml(previewText)}
`;
}
const mediaPresent = (msg.local_thumb || msg.local_file || msg.media_url_external || msg.media_url);
- const content = mediaPresent ? (window.renderMediaMessage ? window.renderMediaMessage(msg) : (window.escapeHtml(msg.content || '[Mensaje]'))) : window.escapeHtml(msg.content || '[Mensaje vacío]');
+ const content = mediaPresent
+ ? (window.renderMediaMessage ? window.renderMediaMessage(msg) : (window.formatMessageContent ? window.formatMessageContent(msg.content || '[Mensaje]') : window.escapeHtml(msg.content || '[Mensaje]')))
+ : (window.formatMessageContent ? window.formatMessageContent(msg.content || '[Mensaje vacío]') : window.escapeHtml(msg.content || '[Mensaje vacío]'));
const time = msg.created_at ? new Date(msg.created_at).toLocaleTimeString('es-ES', { hour: '2-digit', minute: '2-digit' }) : '';
const statusIcon = this.getStatusIcon(msg.status);
const reactionHtml = msg.reaction_emoji ? `
${msg.reaction_emoji}
` : '';
@@ -3181,6 +3194,108 @@
}
}
+ // Helper para renderizar WhatsApp-like formatted text and interactive messages
+ function renderInteractiveMessage(obj) {
+ try {
+ const interactive = obj.interactive || obj;
+ const t = interactive.type || (interactive.header && 'button');
+ if (t === 'button' || interactive.button) {
+ const title = escapeHtml(interactive.title || interactive.body || '');
+ const buttons = interactive.buttons || interactive.button || [];
+ const html = [`
`, title ? `
${title}
` : ''];
+ html.push(`
`);
+ buttons.forEach(b => {
+ const label = escapeHtml(b.title || b.text || b.body || b.label || '');
+ html.push(``);
+ });
+ html.push(`
`);
+ return html.join('');
+ }
+ if (t === 'list' || interactive.sections) {
+ const title = escapeHtml(interactive.title || interactive.header || '');
+ const sections = interactive.sections || [];
+ const html = [`
`, title ? `
${title}
` : ''];
+ html.push(`
`);
+ sections.forEach(s => {
+ const secTitle = escapeHtml(s.title || '');
+ if (secTitle) html.push(`
${secTitle}
`);
+ (s.rows || []).forEach(r => {
+ const rowTitle = escapeHtml(r.title || r.name || r.id || '');
+ const rowDesc = escapeHtml(r.description || '');
+ html.push(`
${rowTitle}
${rowDesc?`
${rowDesc}
`:''}
`);
+ });
+ });
+ html.push(`
`);
+ return html.join('');
+ }
+ } catch (e) { console.warn('renderInteractiveMessage failed', e); }
+ return '';
+ }
+
+ function formatMessageInlineCode(s) {
+ return s.replace(/`([^`]+)`/g, (m, g1) => `
${escapeHtml(g1)}`);
+ }
+
+ function formatMessageContent(text) {
+ if (!text && text !== 0) return '';
+ try {
+ // If looks like JSON with interactive payload, render interactive UI
+ const t = String(text).trim();
+ if ((t.startsWith('{') && t.endsWith('}')) || (t.startsWith('[') && t.endsWith(']'))) {
+ try {
+ const parsed = JSON.parse(t);
+ if (parsed && (parsed.interactive || parsed.type === 'interactive')) {
+ return renderInteractiveMessage(parsed.interactive || parsed);
+ }
+ } catch (e) { /* not json */ }
+ }
+
+ // Escape HTML first
+ let s = escapeHtml(String(text));
+
+ // Code block (triple backticks) ->
+ s = s.replace(/```([\s\S]*?)```/g, (m, g1) => `${escapeHtml(g1)}
`);
+ // Inline code
+ s = formatMessageInlineCode(s);
+ // Bold *text*
+ s = s.replace(/\*([^*]+)\*/g, '$1');
+ // Italic _text_
+ s = s.replace(/_([^_]+)_/g, '$1');
+ // Strikethrough ~text~
+ s = s.replace(/~([^~]+)~/g, '$1');
+
+ // Auto-link URLs
+ s = s.replace(/(https?:\/\/[^\s]+)/g, '$1');
+
+ return s;
+ } catch (e) {
+ console.warn('formatMessageContent failed', e);
+ return escapeHtml(String(text));
+ }
+ }
+
+ window.formatMessageContent = formatMessageContent;
+
+ // Delegate clicks on interactive buttons/list items to send quick replies
+ document.addEventListener('click', (ev) => {
+ const btn = ev.target.closest('.wa-interactive-btn');
+ if (btn) {
+ ev.stopPropagation();
+ const v = btn.dataset.value;
+ if (v && window.chatApp && typeof window.chatApp.sendQuickReply === 'function') {
+ window.chatApp.sendQuickReply(v);
+ }
+ }
+ const item = ev.target.closest('.wa-list-item');
+ if (item) {
+ ev.stopPropagation();
+ const v = item.dataset.value;
+ if (v && window.chatApp && typeof window.chatApp.sendQuickReply === 'function') {
+ window.chatApp.sendQuickReply(v);
+ }
+ }
+ });
+
// Helper para iconos de archivos (copiado de chat_window)
function getFileIcon(filename) {
if (!filename) return 'fas fa-file text-muted';