Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | 5x 5x 5x 5x 39x 5x 47x 47x 47x 7x 7x 7x 7x 7x 47x 32x 19x 13x 13x 606x 606x 606x 606x 606x 6x 6x 606x 600x 600x 13x 13x 13x 6x 13x 13x 1x 47x 5x | import React, { useCallback, useEffect, useRef } from "react";
const scrollCache: Record<string, number> = {};
const MAX_SCROLL_RESTORE_FRAMES = 600;
export const getCachedScrollPosition = (cacheKey: string | undefined) =>
cacheKey ? scrollCache[cacheKey] : undefined;
const useCachedScroll = (
cacheKey: string | undefined,
scrollElement: HTMLDivElement | null,
restoreScroll = true,
) => {
const programmaticScrollPosition = useRef<number | null>(null);
const isUserScrolling = useRef(false);
const onScroll = useCallback<React.UIEventHandler<HTMLDivElement>>(
(e) => {
Iif (!cacheKey) {
return;
}
Iif (e.currentTarget.scrollTop === programmaticScrollPosition.current) {
programmaticScrollPosition.current = null;
return;
}
programmaticScrollPosition.current = null;
scrollCache[cacheKey] = e.currentTarget.scrollTop;
isUserScrolling.current = true;
},
[cacheKey],
);
useEffect(() => {
if (!cacheKey || !scrollElement || !restoreScroll) {
return;
}
let animationFrameId: number | undefined;
let restoreFrames = 0;
const checkScroll = () => {
const savedPosition = scrollCache[cacheKey] ?? 0;
Iif (isUserScrolling.current) {
return;
}
const maxScrollTop = Math.max(
0,
scrollElement.scrollHeight - scrollElement.clientHeight,
);
const targetScrollTop = Math.min(savedPosition, maxScrollTop);
if (scrollElement.scrollTop !== targetScrollTop) {
scrollElement.scrollTop = targetScrollTop;
programmaticScrollPosition.current = scrollElement.scrollTop;
}
if (
scrollElement.scrollTop < savedPosition &&
restoreFrames < MAX_SCROLL_RESTORE_FRAMES
) {
restoreFrames += 1;
animationFrameId = requestAnimationFrame(checkScroll);
}
};
const savedPosition = scrollCache[cacheKey] ?? 0;
isUserScrolling.current = false;
if (savedPosition > 0) {
checkScroll();
}
return () => {
if (animationFrameId !== undefined) {
cancelAnimationFrame(animationFrameId);
}
};
}, [cacheKey, restoreScroll, scrollElement]);
return { onScroll } as const;
};
export default useCachedScroll;
|