mirror of
https://github.com/kilyabin/psysonic.git
synced 2026-07-22 22:45:41 +00:00
Perf/UI performance (#473)
* perf(ui): defer off-screen Artist grid paint + rAF overlay scrollbar Apply content-visibility to artist tiles in .album-grid-wrap (aligned with album cards). Coalesce OverlayScrollArea thumb updates to one requestAnimationFrame per scroll burst. * perf(css): content-visibility on horizontal artist rails Apply the same off-screen deferral as album cards to `.album-grid .artist-card` (ArtistRow, Favorites, etc.).
This commit is contained in:
@@ -60,6 +60,8 @@ export default function OverlayScrollArea({
|
|||||||
const perfFlags = usePerfProbeFlags();
|
const perfFlags = usePerfProbeFlags();
|
||||||
const wrapRef = useRef<HTMLDivElement | null>(null);
|
const wrapRef = useRef<HTMLDivElement | null>(null);
|
||||||
const viewportRef = useRef<HTMLDivElement | null>(null);
|
const viewportRef = useRef<HTMLDivElement | null>(null);
|
||||||
|
/** Coalesce burst scroll events to one thumb update per animation frame. */
|
||||||
|
const scrollRecomputeRafRef = useRef(0);
|
||||||
const [meta, setMeta] = useState({ thumbH: 0, thumbT: 0, visible: false });
|
const [meta, setMeta] = useState({ thumbH: 0, thumbT: 0, visible: false });
|
||||||
|
|
||||||
const recompute = useCallback(() => {
|
const recompute = useCallback(() => {
|
||||||
@@ -71,6 +73,21 @@ export default function OverlayScrollArea({
|
|||||||
setMeta(computeOverlayScrollbarThumbMeta(vp, trackH));
|
setMeta(computeOverlayScrollbarThumbMeta(vp, trackH));
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const scheduleScrollRecompute = useCallback(() => {
|
||||||
|
if (scrollRecomputeRafRef.current !== 0) return;
|
||||||
|
scrollRecomputeRafRef.current = requestAnimationFrame(() => {
|
||||||
|
scrollRecomputeRafRef.current = 0;
|
||||||
|
recompute();
|
||||||
|
});
|
||||||
|
}, [recompute]);
|
||||||
|
|
||||||
|
useEffect(() => () => {
|
||||||
|
if (scrollRecomputeRafRef.current !== 0) {
|
||||||
|
cancelAnimationFrame(scrollRecomputeRafRef.current);
|
||||||
|
scrollRecomputeRafRef.current = 0;
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
const measureKey = JSON.stringify(measureDeps ?? []);
|
const measureKey = JSON.stringify(measureDeps ?? []);
|
||||||
|
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
@@ -138,7 +155,7 @@ export default function OverlayScrollArea({
|
|||||||
id={viewportId}
|
id={viewportId}
|
||||||
ref={setViewportNode}
|
ref={setViewportNode}
|
||||||
className={viewportClass}
|
className={viewportClass}
|
||||||
onScroll={perfFlags.disableOverlayScrollbars ? undefined : recompute}
|
onScroll={perfFlags.disableOverlayScrollbars ? undefined : scheduleScrollRecompute}
|
||||||
onWheel={viewportOnWheel}
|
onWheel={viewportOnWheel}
|
||||||
onTouchMove={viewportOnTouchMove}
|
onTouchMove={viewportOnTouchMove}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -401,6 +401,12 @@
|
|||||||
contain-intrinsic-size: 0 220px;
|
contain-intrinsic-size: 0 220px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Same wrap as Albums grid; defer layout/paint for off-screen artist tiles (helps scroll on WebKit/Linux). */
|
||||||
|
.album-grid-wrap > .artist-card {
|
||||||
|
content-visibility: auto;
|
||||||
|
contain-intrinsic-size: 0 220px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@media (min-width: 1024px) {
|
@media (min-width: 1024px) {
|
||||||
.album-grid-wrap {
|
.album-grid-wrap {
|
||||||
@@ -420,6 +426,11 @@
|
|||||||
contain-intrinsic-size: 0 240px;
|
contain-intrinsic-size: 0 240px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.album-grid .artist-card {
|
||||||
|
content-visibility: auto;
|
||||||
|
contain-intrinsic-size: 0 240px;
|
||||||
|
}
|
||||||
|
|
||||||
.album-card-more {
|
.album-card-more {
|
||||||
flex: 0 0 clamp(140px, 15vw, 180px);
|
flex: 0 0 clamp(140px, 15vw, 180px);
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
Reference in New Issue
Block a user