From 2e24935464c06376aa2706deba01c200ba7d4aa5 Mon Sep 17 00:00:00 2001 From: Larry <627498bd4bd1f281a16431e3c6cce3b5c25b6692798c78672298aefbf2f8f8b5@buzz.block.builderlab.xyz> Date: Fri, 25 Sep 2026 11:58:11 -0400 Subject: [PATCH] perf(channels): keep timeline link and media callbacks stable across navigation Each channel switch presents its navigation request in two steps: first without a request, then with it. ChannelsPage built openLink and openMediaReview from the current channel and request, so they changed on the second step. By then the warm timeline rows were already mounted, and every memoized MessageRow rendered again for the new callbacks. Read the shown channel and request from a ref at call time instead, as link panel context already does. With 4x CPU throttling, the median warm switch in channel-opening.spec falls from 193ms to 165ms in the same run (24 samples each). Signed-off-by: Larry <627498bd4bd1f281a16431e3c6cce3b5c25b6692798c78672298aefbf2f8f8b5@buzz.block.builderlab.xyz> --- src/bundled/channels/ChannelsPage.tsx | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/src/bundled/channels/ChannelsPage.tsx b/src/bundled/channels/ChannelsPage.tsx index a9291f1d1..d31eece61 100644 --- a/src/bundled/channels/ChannelsPage.tsx +++ b/src/bundled/channels/ChannelsPage.tsx @@ -632,8 +632,15 @@ function ChannelWorkspace({ useEffect(() => { if (mediaReview && !showingMediaReview) setMediaReview(undefined); }, [mediaReview, showingMediaReview]); + // Timeline rows are memoized; their callbacks read the shown destination at + // call time so a new navigation request does not rerender every row. + const destination = useRef({ current, navigation }); + useLayoutEffect(() => { + destination.current = { current, navigation }; + }, [current, navigation]); const openMediaReview = useCallback( (messageId: string, attachment: Attachment, initialTime: number) => { + const { current, navigation } = destination.current; if (!current) return; setSettings(undefined); mediaReviewTrigger.current = @@ -650,7 +657,7 @@ function ChannelWorkspace({ ...(navigation ? { entryId: navigation.entryId } : {}), }); }, - [current, navigation], + [], ); useEffect(() => { if ( @@ -700,6 +707,7 @@ function ChannelWorkspace({ }, [currentId, showingThread?.navigation]); const openLink = useCallback( (url: string) => { + const { current, navigation } = destination.current; const connection = relay.snapshot(); if ( !mounted.current || @@ -747,18 +755,7 @@ function ChannelWorkspace({ } return false; }, - [ - panels, - current, - open, - relay, - queries, - navigation, - select, - navigator, - viewer, - scope, - ], + [panels, open, relay, queries, select, navigator, viewer, scope], ); const panelActive = () => { const connection = relay.snapshot();