Files
cinny/src/app/hooks/useNearViewport.ts
T
jaredandClaude Sonnet 4.6 3df95adc52 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>
2026-06-18 17:56:34 -04:00

31 lines
843 B
TypeScript

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;
}