Cuando un canal o un mensaje directo (DM) tiene más mensajes no leídos que los que carga la primera página, y alguien publica mientras estás desplazándote por ese historial, se omiten todos los mensajes entre el final de la página cargada y el nuevo mensaje en vivo. La lista salta de los mensajes antiguos directamente al mensaje en vivo (a menudo horas después), y nada indica que falte algo. Recargar el canal rellena el hueco de una página en una, por lo que un hueco grande requiere varias recargas.
Esto ocurre independientemente del navegador o del tipo de dispositivo (probado en Firefox para escritorio y Android, y PWA de Chrome para Android).
Pasos para reproducir:
- El usuario A y el usuario B comparten un DM o un canal. El usuario A lo lee hasta el último mensaje y luego se va.
- El usuario B publica más de 60 mensajes.
- El usuario A abre el DM. Carga alrededor de su último mensaje leído (con unos 25 mensajes nuevos más abajo).
- Antes de desplazarse hasta el final de esa página cargada, el usuario B publica un mensaje más.
- El usuario A se desplaza hacia abajo.
Esperado: la siguiente página de 25 mensajes se carga debajo, y así sucesivamente hasta llegar al mensaje en vivo.
Real: el mensaje en vivo aparece directamente después de la página cargada. Al llegar al final, se solicitan mensajes posteriores al mensaje en vivo, la respuesta está vacía, can_load_more_future pasa a ser falso y los más de 35 mensajes intermedios nunca se muestran. Como el mensaje en vivo ya es visible, last_read_message_id avanza más allá del hueco, por lo que también desaparece el indicador de no leído.
Aquí está mi mejor intento por entender por qué ocurre esto:
Desde un commit alrededor de diciembre de 2025 («FEATURE: respect user presence when chat is on screen», #36652), ChatChannel#onNewMessage siempre enruta el mensaje a través de ChatPaneState#handleIncomingMessage, que llama a addMessage cuando hay auto-desplazamiento y, de lo contrario, a través de maintainScrollPosition.
ChatMessagesLoader#computeNextTargetMessage utiliza el último mensaje no provisional de la lista como cursor para una página FUTURE (futuro). Una vez que un mensaje en vivo está al final de una lista parcialmente cargada, ese cursor salta por encima de todo el historial no cargado.
Además, Chat::MessagesQuery.query_paginated_messages solo establece can_load_more_future para páginas FUTURE y can_load_more_past para páginas PAST (pasado). El otro valor es nil. ChatMessagesLoader#loadMore asigna ambos desde result.meta incondicionalmente, por lo que una sola página PAST (desplazarse un poco hacia arriba después de abrir en el último mensaje leído) establece canLoadMoreFuture en null aunque aún haya historial sin cargar debajo. La paginación adicional sigue funcionando porque loadMore comprueba === false.
Además de esto, hay un error separado y más antiguo donde #sendNewMessage coloca el mensaje de forma provisional al final de la lista sin cargar la última página cuando canLoadMoreFuture es true. Una vez confirmado, se convierte en el cursor FUTURE, por lo que ocurre el mismo salto si respondes a mensajes antiguos en el historial que estás leyendo.
Nuestra comunidad no está centrada principalmente en el chat, pero nuestros usuarios sí hacen lectura retroactiva frecuentemente, por lo que que falten mensajes en una conversación en curso en la que no estuvieron presentes es un problema. Me imagino que será un problema mayor para las comunidades centradas principalmente en el chat, especialmente dada la nueva capacidad de establecer el chat como página de inicio.