fix: reemplazar livewire:update con MutationObserver para scroll en Android

livewire:update no es un evento DOM válido en Livewire 2.
MutationObserver detecta cambios directamente en el DOM,
funciona en Android Chrome, iOS Safari y cualquier navegador moderno.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Lizandro
2026-07-19 22:10:56 +00:00
co-authored by Claude Sonnet 4.6
parent 4b856f6a43
commit d77eabc272
@@ -614,14 +614,14 @@
let userScrolledUp = false; let userScrolledUp = false;
let newMsgCount = 0; let newMsgCount = 0;
let lastHeight = 0; let lastScrollHeight = container.scrollHeight;
function atBottom() { function atBottom() {
return container.scrollHeight - container.scrollTop - container.clientHeight < 100; return container.scrollHeight - container.scrollTop - container.clientHeight < 120;
} }
function scrollToBottom(smooth) { function scrollToBottom() {
container.scrollTo({ top: container.scrollHeight, behavior: smooth ? 'smooth' : 'auto' }); container.scrollTop = container.scrollHeight;
} }
function showBadge(n) { function showBadge(n) {
@@ -638,15 +638,13 @@
newMsgCount = 0; newMsgCount = 0;
} }
// Bajar al fondo al hacer click en el badge
if (badgeBtn) { if (badgeBtn) {
badgeBtn.addEventListener('click', function () { badgeBtn.addEventListener('click', function () {
scrollToBottom(true); container.scrollTo({ top: container.scrollHeight, behavior: 'smooth' });
hideBadge(); hideBadge();
}); });
} }
// Detectar scroll manual
container.addEventListener('scroll', function () { container.addEventListener('scroll', function () {
if (atBottom()) { if (atBottom()) {
userScrolledUp = false; userScrolledUp = false;
@@ -657,24 +655,23 @@
}, { passive: true }); }, { passive: true });
// Scroll inicial al fondo // Scroll inicial al fondo
scrollToBottom(false); scrollToBottom();
lastHeight = container.scrollHeight;
// Después de cada actualización de Livewire // MutationObserver: detecta cuando Livewire agrega/modifica nodos en el contenedor
document.addEventListener('livewire:update', function () { const observer = new MutationObserver(function () {
setTimeout(function () { const newHeight = container.scrollHeight;
const newHeight = container.scrollHeight; if (newHeight === lastScrollHeight) return;
const grew = newHeight > lastHeight; lastScrollHeight = newHeight;
lastHeight = newHeight;
if (!userScrolledUp) { if (!userScrolledUp) {
scrollToBottom(false); scrollToBottom();
} else if (grew) { } else {
newMsgCount++; newMsgCount++;
showBadge(newMsgCount); showBadge(newMsgCount);
} }
}, 30);
}); });
observer.observe(container, { childList: true, subtree: true });
} }
if (document.readyState === 'loading') { if (document.readyState === 'loading') {
@@ -683,7 +680,6 @@
initChatScroll(); initChatScroll();
} }
// Re-inicializar si Livewire monta el componente dinámicamente
document.addEventListener('livewire:load', initChatScroll); document.addEventListener('livewire:load', initChatScroll);
})(); })();
</script> </script>