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:
2026-06-18 17:56:34 -04:00
parent a6bf4eb7e7
commit 3df95adc52
4 changed files with 47 additions and 7 deletions
+30
View File
@@ -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;
}