add back scroll restoration

This commit is contained in:
bkellam 2025-11-27 16:38:14 -08:00
parent 4b7798a94e
commit 64e6350473
2 changed files with 44 additions and 40 deletions

View file

@ -189,47 +189,47 @@ export const ChatThread = ({
hasSubmittedInputMessage.current = true; hasSubmittedInputMessage.current = true;
}, [inputMessage, sendMessage]); }, [inputMessage, sendMessage]);
// @todo: this need to be optimized to avoid excessive re-renders
// Track scroll position changes. // Track scroll position changes.
// useEffect(() => { useEffect(() => {
// const scrollElement = scrollAreaRef.current?.querySelector('[data-radix-scroll-area-viewport]') as HTMLElement; const scrollElement = scrollAreaRef.current?.querySelector('[data-radix-scroll-area-viewport]') as HTMLElement;
// if (!scrollElement) return; if (!scrollElement) return;
// let timeout: NodeJS.Timeout | null = null; let timeout: NodeJS.Timeout | null = null;
// const handleScroll = () => { const handleScroll = () => {
// const scrollOffset = scrollElement.scrollTop; const scrollOffset = scrollElement.scrollTop;
// const threshold = 50; // pixels from bottom to consider "at bottom" const threshold = 50; // pixels from bottom to consider "at bottom"
// const { scrollHeight, clientHeight } = scrollElement; const { scrollHeight, clientHeight } = scrollElement;
// const isAtBottom = scrollHeight - scrollOffset - clientHeight <= threshold; const isAtBottom = scrollHeight - scrollOffset - clientHeight <= threshold;
// setIsAutoScrollEnabled(isAtBottom); setIsAutoScrollEnabled(isAtBottom);
// // Debounce the history state update // Debounce the history state update
// if (timeout) { if (timeout) {
// clearTimeout(timeout); clearTimeout(timeout);
// } }
// timeout = setTimeout(() => { timeout = setTimeout(() => {
// history.replaceState( console.log(`scrollOffset: ${scrollOffset}`);
// { history.replaceState(
// scrollOffset, {
// } satisfies ChatHistoryState, scrollOffset,
// '', } satisfies ChatHistoryState,
// window.location.href '',
// ); window.location.href
// }, 300); );
// }; }, 500);
};
// scrollElement.addEventListener('scroll', handleScroll, { passive: true }); scrollElement.addEventListener('scroll', handleScroll, { passive: true });
// return () => { return () => {
// scrollElement.removeEventListener('scroll', handleScroll); scrollElement.removeEventListener('scroll', handleScroll);
// if (timeout) { if (timeout) {
// clearTimeout(timeout); clearTimeout(timeout);
// } }
// }; };
// }, []); }, []);
useEffect(() => { useEffect(() => {
const scrollElement = scrollAreaRef.current?.querySelector('[data-radix-scroll-area-viewport]') as HTMLElement; const scrollElement = scrollAreaRef.current?.querySelector('[data-radix-scroll-area-viewport]') as HTMLElement;
@ -237,11 +237,17 @@ export const ChatThread = ({
return; return;
} }
// @hack: without this setTimeout, the scroll position would not be restored
// at the correct position (it was slightly too high). The theory is that the
// content hasn't fully rendered yet, so restoring the scroll position too
// early results in weirdness. Waiting 10ms seems to fix the issue.
setTimeout(() => {
const { scrollOffset } = (history.state ?? {}) as ChatHistoryState; const { scrollOffset } = (history.state ?? {}) as ChatHistoryState;
scrollElement.scrollTo({ scrollElement.scrollTo({
top: scrollOffset ?? 0, top: scrollOffset ?? 0,
behavior: 'instant', behavior: 'instant',
}); });
}, 10);
}, []); }, []);
// When messages are being streamed, scroll to the latest message // When messages are being streamed, scroll to the latest message

View file

@ -123,8 +123,6 @@ const ReferencedFileSourceListItem = ({
return createCodeFoldingExtension(references, 3); return createCodeFoldingExtension(references, 3);
}, [references]); }, [references]);
// console.log(`re-renderign for file ${fileName}`);
const extensions = useMemo(() => { const extensions = useMemo(() => {
return [ return [
languageExtension, languageExtension,