fix(desktop): remove chat-switch reveal flicker (decouple from reactions)
The residual flicker on chat switch was a loading/reveal artifact, not scroll. listReady gated the MessageList reveal on reactionsReady OR a 300ms timeout, so on a cache-hit switch (messages already present from the first render) the list sat at opacity:0 for up to 300ms and then popped in. Drop the reactions/timeout gate: reveal as soon as messages exist. Reaction chips stream in a beat later; because the list is pinned to the bottom their height growth re-pins with no visible jump, and MessageList still defers its own reveal a few frames until the row-height measurement settles so it appears already at the final bottom. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -144,21 +144,18 @@ export function ConversationPage() {
|
|||||||
byMessage: reactionsByMessage,
|
byMessage: reactionsByMessage,
|
||||||
toggle: toggleReaction,
|
toggle: toggleReaction,
|
||||||
voteExclusive: votePoll,
|
voteExclusive: votePoll,
|
||||||
ready: reactionsReady,
|
|
||||||
} = useMessageReactions(messageIds, session?.user.id);
|
} = useMessageReactions(messageIds, session?.user.id);
|
||||||
|
|
||||||
// Deferred-reveal gate for MessageList: keep the list hidden until messages
|
// Reveal gate for MessageList: as soon as messages exist (cache hit = first
|
||||||
// AND their reactions (the main post-paint height changer) are loaded, so the
|
// render, so no spinner and no wait), let the list reveal. We deliberately do
|
||||||
// chat opens already-stable instead of flickering through the load cascade.
|
// NOT gate on reactions readiness: on a cache-hit chat switch the messages are
|
||||||
// A 300 ms max-timeout ensures a slow/empty reactions fetch never hangs it.
|
// already present, and gating on the async reactions fetch held the list at
|
||||||
const [revealTimedOut, setRevealTimedOut] = useState(false);
|
// opacity:0 for up to 300ms and then "popped" it in — that was the residual
|
||||||
useEffect(() => {
|
// chat-switch flicker. Reaction chips stream in a beat later; because the list
|
||||||
setRevealTimedOut(false);
|
// is pinned to the bottom, their height growth re-pins with no visible jump.
|
||||||
if (!id || loading || messages.length === 0) return;
|
// MessageList still defers its own reveal a few frames until the row-height
|
||||||
const tmo = window.setTimeout(() => setRevealTimedOut(true), 300);
|
// measurement settles, so the list still appears already at the final bottom.
|
||||||
return () => window.clearTimeout(tmo);
|
const listReady = !loading && messages.length > 0;
|
||||||
}, [id, loading, messages.length]);
|
|
||||||
const listReady = !loading && messages.length > 0 && (reactionsReady || revealTimedOut);
|
|
||||||
|
|
||||||
const myId = session?.user.id;
|
const myId = session?.user.id;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user