Skip to content

Commit 64e6350

Browse files
add back scroll restoration
1 parent 4b7798a commit 64e6350

2 files changed

Lines changed: 51 additions & 47 deletions

File tree

packages/web/src/features/chat/components/chatThread/chatThread.tsx

Lines changed: 51 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -189,59 +189,65 @@ export const ChatThread = ({
189189
hasSubmittedInputMessage.current = true;
190190
}, [inputMessage, sendMessage]);
191191

192-
// @todo: this need to be optimized to avoid excessive re-renders
193192
// Track scroll position changes.
194-
// useEffect(() => {
195-
// const scrollElement = scrollAreaRef.current?.querySelector('[data-radix-scroll-area-viewport]') as HTMLElement;
196-
// if (!scrollElement) return;
197-
198-
// let timeout: NodeJS.Timeout | null = null;
199-
200-
// const handleScroll = () => {
201-
// const scrollOffset = scrollElement.scrollTop;
202-
203-
// const threshold = 50; // pixels from bottom to consider "at bottom"
204-
// const { scrollHeight, clientHeight } = scrollElement;
205-
// const isAtBottom = scrollHeight - scrollOffset - clientHeight <= threshold;
206-
// setIsAutoScrollEnabled(isAtBottom);
207-
208-
// // Debounce the history state update
209-
// if (timeout) {
210-
// clearTimeout(timeout);
211-
// }
212-
213-
// timeout = setTimeout(() => {
214-
// history.replaceState(
215-
// {
216-
// scrollOffset,
217-
// } satisfies ChatHistoryState,
218-
// '',
219-
// window.location.href
220-
// );
221-
// }, 300);
222-
// };
223-
224-
// scrollElement.addEventListener('scroll', handleScroll, { passive: true });
225-
226-
// return () => {
227-
// scrollElement.removeEventListener('scroll', handleScroll);
228-
// if (timeout) {
229-
// clearTimeout(timeout);
230-
// }
231-
// };
232-
// }, []);
193+
useEffect(() => {
194+
const scrollElement = scrollAreaRef.current?.querySelector('[data-radix-scroll-area-viewport]') as HTMLElement;
195+
if (!scrollElement) return;
196+
197+
let timeout: NodeJS.Timeout | null = null;
198+
199+
const handleScroll = () => {
200+
const scrollOffset = scrollElement.scrollTop;
201+
202+
const threshold = 50; // pixels from bottom to consider "at bottom"
203+
const { scrollHeight, clientHeight } = scrollElement;
204+
const isAtBottom = scrollHeight - scrollOffset - clientHeight <= threshold;
205+
setIsAutoScrollEnabled(isAtBottom);
206+
207+
// Debounce the history state update
208+
if (timeout) {
209+
clearTimeout(timeout);
210+
}
211+
212+
timeout = setTimeout(() => {
213+
console.log(`scrollOffset: ${scrollOffset}`);
214+
history.replaceState(
215+
{
216+
scrollOffset,
217+
} satisfies ChatHistoryState,
218+
'',
219+
window.location.href
220+
);
221+
}, 500);
222+
};
223+
224+
scrollElement.addEventListener('scroll', handleScroll, { passive: true });
225+
226+
return () => {
227+
scrollElement.removeEventListener('scroll', handleScroll);
228+
if (timeout) {
229+
clearTimeout(timeout);
230+
}
231+
};
232+
}, []);
233233

234234
useEffect(() => {
235235
const scrollElement = scrollAreaRef.current?.querySelector('[data-radix-scroll-area-viewport]') as HTMLElement;
236236
if (!scrollElement) {
237237
return;
238238
}
239239

240-
const { scrollOffset } = (history.state ?? {}) as ChatHistoryState;
241-
scrollElement.scrollTo({
242-
top: scrollOffset ?? 0,
243-
behavior: 'instant',
244-
});
240+
// @hack: without this setTimeout, the scroll position would not be restored
241+
// at the correct position (it was slightly too high). The theory is that the
242+
// content hasn't fully rendered yet, so restoring the scroll position too
243+
// early results in weirdness. Waiting 10ms seems to fix the issue.
244+
setTimeout(() => {
245+
const { scrollOffset } = (history.state ?? {}) as ChatHistoryState;
246+
scrollElement.scrollTo({
247+
top: scrollOffset ?? 0,
248+
behavior: 'instant',
249+
});
250+
}, 10);
245251
}, []);
246252

247253
// When messages are being streamed, scroll to the latest message

packages/web/src/features/chat/components/chatThread/referencedFileSourceListItem.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,8 +123,6 @@ const ReferencedFileSourceListItem = ({
123123
return createCodeFoldingExtension(references, 3);
124124
}, [references]);
125125

126-
// console.log(`re-renderign for file ${fileName}`);
127-
128126
const extensions = useMemo(() => {
129127
return [
130128
languageExtension,

0 commit comments

Comments
 (0)