Wenn ein Kanal oder eine DM mehr ungelesene Nachrichten enthält, als die erste Seite lädt, und jemand postet, während du durch den Verlauf scrollst, werden alle Nachrichten zwischen dem Ende der geladenen Seite und der neuen Live-Nachricht übersprungen. Die Liste springt von den älteren Nachrichten direkt zur Live-Nachricht (oft Stunden später), und nichts deutet darauf hin, dass etwas fehlt. Ein Neuladen des Kanals füllt die Lücke seitenweise wieder auf, sodass eine große Lücke mehrere Neuladungen erfordert.
Dies tritt unabhängig vom Browser oder Gerätetyp auf (getestet auf Firefox Desktop und Android sowie Chrome Android PWA).
Schritte zur Reproduktion:
- Benutzer A und Benutzer B teilen sich eine DM oder einen Kanal. Benutzer A liest bis zur neuesten Nachricht und verlässt dann den Chat.
- Benutzer B postet 60+ Nachrichten.
- Benutzer A öffnet die DM. Sie lädt etwa bei seiner zuletzt gelesenen Nachricht (25 neuere Nachrichten darunter).
- Bevor zum Ende der geladenen Seite gescrollt wird, postet Benutzer B eine weitere Nachricht.
- Benutzer A scrollt nach unten.
Erwartet: Die nächste Seite mit 25 Nachrichten wird darunter geladen, und so weiter, bis zur Live-Nachricht.
Ist-Zustand: Die Live-Nachricht erscheint direkt nach der geladenen Seite. Beim Erreichen des unteren Endes werden Nachrichten nach der Live-Nachricht angefragt, die Antwort ist leer, can_load_more_future wird auf false gesetzt, und die 35+ dazwischenliegenden Nachrichten werden nie angezeigt. Da die Live-Nachricht nun sichtbar ist, rückt last_read_message_id über die Lücke hinaus, sodass auch die Ungelesen-Markierung verschwindet.
Hier ist mein bester Versuch herauszufinden, warum dies passiert:
Seit einem Commit um Dezember 2025 („FEATURE: respect user presence when chat is on screen“, #36652) leitet ChatChannel#onNewMessage die Nachricht immer über ChatPaneState#handleIncomingMessage, was addMessage aufruft, wenn automatisch gescrollt wird, und andernfalls über maintainScrollPosition.
ChatMessagesLoader#computeNextTargetMessage verwendet die letzte nicht-stagierte Nachricht in der Liste als Cursor für eine FUTURE-Seite. Sobald eine Live-Nachricht am Ende einer teilweise geladenen Liste steht, springt dieser Cursor über die gesamte ungeladene Historie hinweg.
Dann setzt Chat::MessagesQuery.query_paginated_messages can_load_more_future nur für FUTURE-Seiten und can_load_more_past nur für PAST-Seiten. Der andere Wert ist nil. ChatMessagesLoader#loadMore weist beide Werte bedingungslos aus result.meta zu, sodass eine einzelne PAST-Seite (ein kleines Scrollen nach oben nach dem Öffnen bei der zuletzt gelesenen Nachricht) canLoadMoreFuture auf null setzt, während die Historie darunter noch nicht geladen ist. Die weitere Paginierung funktioniert weiterhin, da loadMore auf === false prüft.
Darüber hinaus gibt es einen separaten, älteren Fehler, bei dem #sendNewMessage die Nachricht am Ende der Liste staged, ohne die neueste Seite zu laden, wenn canLoadMoreFuture true ist. Sobald sie bestätigt ist, wird sie zum FUTURE-Cursor, sodass derselbe Sprung auftritt, wenn du in der Historie, die du liest, auf ältere Nachrichten antwortest.
Unsere Community konzentriert sich nicht primär auf Chat, aber unsere Nutzer lesen oft alte Nachrichten nach, daher ist das Fehlen von Nachrichten in einem laufenden Gespräch, bei dem man nicht dabei war, ein Problem. Ich kann mir vorstellen, dass es für Communities, die primär auf Chat setzen, ein noch größeres Problem sein wird, besonders angesichts der neuen Möglichkeit, die Startseite als Chat zu festzulegen.