perf(media): defer image/video decryption until near-viewport (P5-5)
Creates useNearViewport hook (IntersectionObserver, 200px rootMargin, one-shot disconnect after first trigger). ImageContent and VideoContent now gate loadSrc() on nearViewport — when autoPlay is enabled, encrypted media is not decrypted until the element is within 200px of the visible area, reducing initial page load cost on long timelines. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
import { RefObject, useEffect, useState } from 'react';
|
||||
|
||||
/**
|
||||
* Returns true once the observed element has come within `margin` pixels of
|
||||
* the viewport. Disconnects the observer after the first intersection so there
|
||||
* is no ongoing overhead.
|
||||
*/
|
||||
export function useNearViewport(ref: RefObject<Element | null>, margin = 200): boolean {
|
||||
const [triggered, setTriggered] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const el = ref.current;
|
||||
if (!el || triggered) return undefined;
|
||||
|
||||
const observer = new IntersectionObserver(
|
||||
(entries) => {
|
||||
if (entries[0]?.isIntersecting) {
|
||||
setTriggered(true);
|
||||
observer.disconnect();
|
||||
}
|
||||
},
|
||||
{ rootMargin: `${margin}px` },
|
||||
);
|
||||
|
||||
observer.observe(el);
|
||||
return () => observer.disconnect();
|
||||
}, [ref, margin, triggered]);
|
||||
|
||||
return triggered;
|
||||
}
|
||||
Reference in New Issue
Block a user