try something different for stats scroll

This commit is contained in:
yohlo
2025-10-11 00:43:28 -05:00
parent f74d2daf9c
commit 46943b6971

View File

@@ -116,6 +116,9 @@ const PlayerListItem = memo(({ stat, onPlayerClick, mmr, onRegisterViewport, onU
viewport: { viewport: {
WebkitOverflowScrolling: 'touch', WebkitOverflowScrolling: 'touch',
scrollBehavior: 'auto', scrollBehavior: 'auto',
willChange: 'scroll-position',
transform: 'translateZ(0)',
backfaceVisibility: 'hidden',
}, },
}} }}
> >
@@ -150,33 +153,48 @@ const PlayerStatsTable = () => {
const viewportsRef = useRef<Set<HTMLDivElement>>(new Set()); const viewportsRef = useRef<Set<HTMLDivElement>>(new Set());
const scrollHandlersRef = useRef<Map<HTMLDivElement, (e: Event) => void>>(new Map()); const scrollHandlersRef = useRef<Map<HTMLDivElement, (e: Event) => void>>(new Map());
const isSyncingRef = useRef(false); const scrollLeaderRef = useRef<HTMLDivElement | null>(null);
const scrollTimeoutRef = useRef<number | null>(null);
const handleRegisterViewport = useCallback((viewport: HTMLDivElement) => { const handleRegisterViewport = useCallback((viewport: HTMLDivElement) => {
viewportsRef.current.add(viewport); viewportsRef.current.add(viewport);
const handleScrollStart = () => {
scrollLeaderRef.current = viewport;
};
const handleScroll = (e: Event) => { const handleScroll = (e: Event) => {
const target = e.target as HTMLDivElement; const target = e.target as HTMLDivElement;
// Prevent infinite loops if (scrollLeaderRef.current !== target) {
if (isSyncingRef.current) {
return; return;
} }
isSyncingRef.current = true;
const scrollLeft = target.scrollLeft; const scrollLeft = target.scrollLeft;
// Synchronize all other viewports immediately
viewportsRef.current.forEach((vp) => { viewportsRef.current.forEach((vp) => {
if (vp !== target) { if (vp !== target) {
if (Math.abs(vp.scrollLeft - scrollLeft) > 0.5) {
const wasLeader = scrollLeaderRef.current;
scrollLeaderRef.current = null;
vp.scrollLeft = scrollLeft; vp.scrollLeft = scrollLeft;
scrollLeaderRef.current = wasLeader;
}
} }
}); });
isSyncingRef.current = false; if (scrollTimeoutRef.current) {
clearTimeout(scrollTimeoutRef.current);
}
scrollTimeoutRef.current = window.setTimeout(() => {
scrollLeaderRef.current = null;
}, 150);
}; };
viewport.addEventListener('touchstart', handleScrollStart, { passive: true });
viewport.addEventListener('mousedown', handleScrollStart, { passive: true });
viewport.addEventListener('scroll', handleScroll, { passive: true }); viewport.addEventListener('scroll', handleScroll, { passive: true });
scrollHandlersRef.current.set(viewport, handleScroll); scrollHandlersRef.current.set(viewport, handleScroll);
}, []); }, []);
@@ -186,6 +204,8 @@ const PlayerStatsTable = () => {
const handler = scrollHandlersRef.current.get(viewport); const handler = scrollHandlersRef.current.get(viewport);
if (handler) { if (handler) {
viewport.removeEventListener('scroll', handler); viewport.removeEventListener('scroll', handler);
viewport.removeEventListener('touchstart', handler);
viewport.removeEventListener('mousedown', handler);
scrollHandlersRef.current.delete(viewport); scrollHandlersRef.current.delete(viewport);
} }
}, []); }, []);