feat: auto-scroll al fondo del chat + badge de mensajes nuevos
- Al cargar, baja automáticamente al último mensaje - Después de cada actualización Livewire, baja si el usuario está al fondo - Si el usuario subió a leer historial, muestra badge "N mensaje nuevo" en lugar de forzar scroll - Click en badge baja suavemente al fondo y lo oculta Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
e804831e15
commit
4b856f6a43
@@ -602,3 +602,88 @@
|
|||||||
@endif
|
@endif
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
(function () {
|
||||||
|
function initChatScroll() {
|
||||||
|
const container = document.getElementById('pub-messages');
|
||||||
|
const badge = document.getElementById('new-msg-badge');
|
||||||
|
const badgeBtn = document.getElementById('new-msg-badge-btn');
|
||||||
|
const countEl = document.getElementById('new-msg-count');
|
||||||
|
if (!container) return;
|
||||||
|
|
||||||
|
let userScrolledUp = false;
|
||||||
|
let newMsgCount = 0;
|
||||||
|
let lastHeight = 0;
|
||||||
|
|
||||||
|
function atBottom() {
|
||||||
|
return container.scrollHeight - container.scrollTop - container.clientHeight < 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
function scrollToBottom(smooth) {
|
||||||
|
container.scrollTo({ top: container.scrollHeight, behavior: smooth ? 'smooth' : 'auto' });
|
||||||
|
}
|
||||||
|
|
||||||
|
function showBadge(n) {
|
||||||
|
if (!badge || !countEl) return;
|
||||||
|
countEl.textContent = n;
|
||||||
|
badge.classList.remove('hidden');
|
||||||
|
badge.classList.add('flex');
|
||||||
|
}
|
||||||
|
|
||||||
|
function hideBadge() {
|
||||||
|
if (!badge) return;
|
||||||
|
badge.classList.add('hidden');
|
||||||
|
badge.classList.remove('flex');
|
||||||
|
newMsgCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bajar al fondo al hacer click en el badge
|
||||||
|
if (badgeBtn) {
|
||||||
|
badgeBtn.addEventListener('click', function () {
|
||||||
|
scrollToBottom(true);
|
||||||
|
hideBadge();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Detectar scroll manual
|
||||||
|
container.addEventListener('scroll', function () {
|
||||||
|
if (atBottom()) {
|
||||||
|
userScrolledUp = false;
|
||||||
|
hideBadge();
|
||||||
|
} else {
|
||||||
|
userScrolledUp = true;
|
||||||
|
}
|
||||||
|
}, { passive: true });
|
||||||
|
|
||||||
|
// Scroll inicial al fondo
|
||||||
|
scrollToBottom(false);
|
||||||
|
lastHeight = container.scrollHeight;
|
||||||
|
|
||||||
|
// Después de cada actualización de Livewire
|
||||||
|
document.addEventListener('livewire:update', function () {
|
||||||
|
setTimeout(function () {
|
||||||
|
const newHeight = container.scrollHeight;
|
||||||
|
const grew = newHeight > lastHeight;
|
||||||
|
lastHeight = newHeight;
|
||||||
|
|
||||||
|
if (!userScrolledUp) {
|
||||||
|
scrollToBottom(false);
|
||||||
|
} else if (grew) {
|
||||||
|
newMsgCount++;
|
||||||
|
showBadge(newMsgCount);
|
||||||
|
}
|
||||||
|
}, 30);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (document.readyState === 'loading') {
|
||||||
|
document.addEventListener('DOMContentLoaded', initChatScroll);
|
||||||
|
} else {
|
||||||
|
initChatScroll();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Re-inicializar si Livewire monta el componente dinámicamente
|
||||||
|
document.addEventListener('livewire:load', initChatScroll);
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
|||||||
Reference in New Issue
Block a user