La chat salta un blocco di messaggi quando qualcuno pubblica mentre stai leggendo la cronologia non letta

Quando un canale o un DM ha più messaggi non letti di quelli caricati nella prima pagina e qualcuno pubblica mentre stai scorrendo la cronologia, ogni messaggio tra la fine della pagina caricata e il nuovo messaggio in diretta viene saltato. L’elenco salta dai messaggi più vecchi direttamente al messaggio in diretta (spesso ore dopo) e non c’è nulla che indichi che manchi qualcosa. Ricaricare il canale colma la lacuna una pagina alla volta, quindi una lacuna ampia richiede diverse ricariche.

Questo si verifica indipendentemente dal tipo di browser o dispositivo (testato su Firefox Desktop e Android e Chrome Android PWA).

Passaggi per riprodurre:

  1. L’utente A e l’utente B condividono un DM o un canale. L’utente A lo legge fino all’ultimo messaggio, poi esce.
  2. L’utente B pubblica 60+ messaggi.
  3. L’utente A apre il DM. Questo si carica intorno all’ultimo messaggio letto (25 messaggi più recenti in basso).
  4. Prima di scorrere fino al fondo della pagina caricata, l’utente B pubblica un altro messaggio.
  5. L’utente A scorre verso il basso.

Atteso: la pagina successiva di 25 messaggi si carica in basso, e così via fino al messaggio in diretta.

Effettivo: il messaggio in diretta appare direttamente dopo la pagina caricata. Raggiungendo il fondo, vengono richiesti messaggi dopo il messaggio in diretta, la risposta è vuota, can_load_more_future diventa false e i 35+ messaggi tra loro non vengono mai mostrati. Poiché il messaggio in diretta è ora visibile, last_read_message_id avanza oltre la lacuna, quindi anche l’indicatore dei messaggi non letti si cancella.

Ecco il mio miglior tentativo di capire perché questo sta accadendo:

Da un commit intorno a dicembre 2025 (“FEATURE: respect user presence when chat is on screen”, #36652), ChatChannel#onNewMessage instrada sempre il messaggio attraverso ChatPaneState#handleIncomingMessage, che chiama addMessage quando lo scorrimento è automatico e tramite maintainScrollPosition in caso contrario.

ChatMessagesLoader#computeNextTargetMessage usa l’ultimo messaggio non-staged nell’elenco come cursore per una pagina FUTURE. Una volta che un messaggio in diretta si trova alla fine di un elenco parzialmente caricato, quel cursore salta oltre tutta la cronologia non caricata.

In seguito, Chat::MessagesQuery.query_paginated_messages imposta can_load_more_future solo per le pagine FUTURE e can_load_more_past solo per le pagine PAST. L’altra è nil. ChatMessagesLoader#loadMore assegna entrambi incondizionatamente da result.meta, quindi una singola pagina PAST (scorrere leggermente verso l’alto dopo l’apertura all’ultimo messaggio letto) imposta canLoadMoreFuture su null mentre la cronologia in basso non è ancora stata caricata. La paginazione successiva continua a funzionare perché loadMore verifica === false.

Inoltre, c’è un bug separato e più vecchio in cui #sendNewMessage inserisce il messaggio in fondo all’elenco come staged senza caricare l’ultima pagina quando canLoadMoreFuture è true. Una volta confermato, diventa il cursore FUTURE, quindi si verifica lo stesso salto se si risponde a messaggi più vecchi nella cronologia che si sta leggendo.

La nostra community non è principalmente focalizzata sulla chat, ma i nostri utenti leggono spesso messaggi arretrati, quindi perdere messaggi in una conversazione in corso a cui non si era presenti è un problema. Immagino che sarà un problema più grande per le community dove la chat è il focus primario, specialmente data la nuova possibilità di impostare la chat come homepage.