try something different for stats scroll

This commit is contained in:
yohlo
2025-10-11 00:40:18 -05:00
parent 26c6343a89
commit f74d2daf9c

View File

@@ -112,6 +112,12 @@ const PlayerListItem = memo(({ stat, onPlayerClick, mmr, onRegisterViewport, onU
<ScrollArea <ScrollArea
viewportRef={viewportRef} viewportRef={viewportRef}
type="never" type="never"
styles={{
viewport: {
WebkitOverflowScrolling: 'touch',
scrollBehavior: 'auto',
},
}}
> >
<Group gap='xs' wrap="nowrap"> <Group gap='xs' wrap="nowrap">
<StatCell label="MMR" value={mmr.toFixed(1)} /> <StatCell label="MMR" value={mmr.toFixed(1)} />
@@ -120,7 +126,7 @@ const PlayerListItem = memo(({ stat, onPlayerClick, mmr, onRegisterViewport, onU
<StatCell label="W%" value={`${stat.win_percentage.toFixed(1)}%`} /> <StatCell label="W%" value={`${stat.win_percentage.toFixed(1)}%`} />
<StatCell label="AWM" value={stat.margin_of_victory?.toFixed(1) || 0} /> <StatCell label="AWM" value={stat.margin_of_victory?.toFixed(1) || 0} />
<StatCell label="ALM" value={stat.margin_of_loss?.toFixed(1) || 0} /> <StatCell label="ALM" value={stat.margin_of_loss?.toFixed(1) || 0} />
<StatCell label="ACPM" value={stat.avg_cups_per_match.toFixed(1)} /> <StatCell label="AC" value={stat.avg_cups_per_match.toFixed(1)} />
<StatCell label="ACA" value={avg_cups_against?.toFixed(1) || 0} /> <StatCell label="ACA" value={avg_cups_against?.toFixed(1) || 0} />
<StatCell label="CF" value={stat.total_cups_made} /> <StatCell label="CF" value={stat.total_cups_made} />
<StatCell label="CA" value={stat.total_cups_against} /> <StatCell label="CA" value={stat.total_cups_against} />
@@ -143,34 +149,45 @@ const PlayerStatsTable = () => {
}); });
const viewportsRef = useRef<Set<HTMLDivElement>>(new Set()); const viewportsRef = useRef<Set<HTMLDivElement>>(new Set());
const isScrollingRef = useRef(false); const scrollHandlersRef = useRef<Map<HTMLDivElement, (e: Event) => void>>(new Map());
const isSyncingRef = useRef(false);
const handleRegisterViewport = useCallback((viewport: HTMLDivElement) => { const handleRegisterViewport = useCallback((viewport: HTMLDivElement) => {
viewportsRef.current.add(viewport); viewportsRef.current.add(viewport);
const handleScroll = (e: Event) => { const handleScroll = (e: Event) => {
if (isScrollingRef.current) return; const target = e.target as HTMLDivElement;
isScrollingRef.current = true; // Prevent infinite loops
const scrollLeft = (e.target as HTMLDivElement).scrollLeft; if (isSyncingRef.current) {
return;
}
isSyncingRef.current = true;
const scrollLeft = target.scrollLeft;
// Synchronize all other viewports immediately
viewportsRef.current.forEach((vp) => { viewportsRef.current.forEach((vp) => {
if (vp !== e.target) { if (vp !== target) {
vp.scrollLeft = scrollLeft; vp.scrollLeft = scrollLeft;
} }
}); });
requestAnimationFrame(() => { isSyncingRef.current = false;
isScrollingRef.current = false;
});
}; };
viewport.addEventListener('scroll', handleScroll); viewport.addEventListener('scroll', handleScroll, { passive: true });
viewport.dataset.scrollHandler = 'attached'; scrollHandlersRef.current.set(viewport, handleScroll);
}, []); }, []);
const handleUnregisterViewport = useCallback((viewport: HTMLDivElement) => { const handleUnregisterViewport = useCallback((viewport: HTMLDivElement) => {
viewportsRef.current.delete(viewport); viewportsRef.current.delete(viewport);
const handler = scrollHandlersRef.current.get(viewport);
if (handler) {
viewport.removeEventListener('scroll', handler);
scrollHandlersRef.current.delete(viewport);
}
}, []); }, []);
const calculateMMR = (stat: PlayerStats): number => { const calculateMMR = (stat: PlayerStats): number => {