Two skeleton flashes made switching feel clunky:
- Every switch: the deferred timeline snapshot lags the live one for a
frame or two, and that gap painted the full skeleton to mask the
previous channel's rows — a visible skeleton flash on every switch.
The gap is a render-pipeline artifact, not a loading state: it now
renders plain background (new "blank" body surface). Blank blocks the
same behaviors as the skeleton (autoscroll, jumps, unread pill,
scrollback), only the visual differs. Cold loads keep the skeleton.
- Stale revisits: the loading latch reset on every switch, so re-entering
a channel past the messages staleTime refetched on mount with the
unsettled skeleton branch active — a skeleton over a fully cached
timeline for the whole relay round-trip. Channels that settled once
this session now render their cached rows stale-while-revalidate
(session registry, reset via resetCommunityState like every other
community-scoped singleton).
The revisit spec forces staleness by shifting Date.now past the 5-minute
window and asserts the skeleton never mounts over cached rows; the
switch-gap behavior is covered by the timelineSnapshot unit suite.
Signed-off-by: Max Lampert <maxwell@squareup.com>