Scrolling backwards through a long conversation is one of the hardest screens in any chat-style app — a few small promises that compound into something genuinely difficult.
Scrolling backwards through a personal forest longer than fits
in memory is the hard problem every chat-style app eventually
has to solve.
The promise is small but inflexible:
Newest message at the bottom when you open the screen.
Scrolling up loads older messages without anything jumping.
New messages arrive, but never push what you’re looking at out
of view.
A message you find via search lands in the right place — not
under the chrome, not behind the keyboard.
Each one is straightforward on its own. Holding all of them at
once, while the user is actively scrolling, is the hard part.
Why it cascades
Variable-height messages change the scroll math. The scroll math
changes which message sits at the visible bottom. Which message
sits at the visible bottom decides whether a new arrival is
welcome or intrusive. Whether the arrival is welcome decides
whether you snap, queue, or do nothing. Whether you snap depends
on whether anything else just snapped.
A bug in one layer manifests in another. The chat screen is the
cascading-renders problem most apps eventually face.
What we ended up with
A bounded window of messages in memory. Scrolling backwards
fetches older pages and evicts the newest; scrolling forward
fetches the other direction. Real-time arrivals while you’re
scrolled away wait behind a small “new messages” cue. The anchor
— what sits at the bottom, where a search lands — is derived
from the chrome’s actual size each render, not a hand-picked
number.
None of these are individually clever. The clever part is making
them hold together while you’re using the screen.