From 11d6e48184a27e4b76d5ff6796b3f7527ac070d1 Mon Sep 17 00:00:00 2001 From: Lizandro Guarnizo <77708265+lizandrogd@users.noreply.github.com> Date: Sat, 24 Jan 2026 09:10:35 -0500 Subject: [PATCH] Update conversations.php --- conversations.php | 55 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/conversations.php b/conversations.php index 9ee1f01..6f57b13 100644 --- a/conversations.php +++ b/conversations.php @@ -2113,6 +2113,32 @@ messages = data; } + // Filtrar mensajes vacíos (sin texto y sin media) para evitar que aparezcan placeholders "[Mensaje vacío]" + if (Array.isArray(messages) && messages.length > 0) { + const beforeCount = messages.length; + messages = messages.filter(m => { + const content = (typeof m.content !== 'undefined' && m.content !== null) ? String(m.content).trim() : ''; + const hasContent = content.length > 0; + const hasMedia = !!(m.local_thumb || m.local_file || m.media_url_external || m.media_url); + const nonText = m.message_type && m.message_type !== 'text'; + if (!hasContent && !hasMedia && !nonText) { + // Drop purely empty text message + if (console && console.warn) console.warn('Dropping empty message in pagination:', m && (m.id || m.message_id), m && m.created_at); + return false; + } + return true; + }); + const dropped = beforeCount - messages.length; + if (dropped > 0) { + // Indicar de forma no intrusiva en caso de debug o visibilidad limitada + if (typeof showAlert === 'function') { + showAlert(dropped + ' mensajes vacíos omitidos', 'warning'); + } else { + if (console && console.info) console.info('Omitidos ' + dropped + ' mensajes vacíos durante paginación'); + } + } + } + // Guard: cuando paginamos (initial=false) y la respuesta no trae mensajes, // no reemplazar ni limpiar la conversación actual; solo indicar que no hay más. if (!initial && Array.isArray(messages) && messages.length === 0) { @@ -2127,6 +2153,25 @@ if (initial) { this.conversations = messages; } else { + // Evitar introducir duplicados que ya existen en la vista actual + try { + const existingKeys = new Set(this.conversations.map(m => this.messageKey(m))); + const beforeLen = messages.length; + messages = messages.filter(m => { + const k = this.messageKey(m); + const seen = existingKeys.has(k); + if (!seen) existingKeys.add(k); // mark as seen to avoid duplicates within the batch + else { + if (console && console.debug) console.debug('Skipping duplicate message from server (already in view)', m && (m.id || m.message_id), m && m.created_at); + } + return !seen; + }); + const dropped = beforeLen - messages.length; + if (dropped > 0) { + if (console && console.info) console.info(`Omitted ${dropped} messages because they already exist in view`); + } + } catch (e) { console.warn('duplicate filtering failed', e); } + // Prepend mensajes antiguos this.conversations = messages.concat(this.conversations); } @@ -2472,6 +2517,16 @@ } catch (e) { console.warn('removeNoMoreMessagesHint failed', e); } } + // Helper: generate stable key for a message to detect duplicates + messageKey(m) { + if (!m) return ''; + const mid = m.message_id || m.id || ''; + if (mid) return String(mid); + const partMedia = m.media_url || m.media_url_external || m.local_file || m.local_thumb || (m.content || ''); + const ts = m.created_at ? String(Math.floor(new Date(m.created_at).getTime() / 1000)) : ''; + return `${m.direction||'?'}|${m.message_type||m.media_type||'text'}|${partMedia}|${ts}`; + } + // Initialize recording handlers (so mic works before openConversation) and helper to manage recording state initRecordingHandlers() { if (this._recordingHandlersInitialized) return;