fix image and screen issue

This commit is contained in:
2026-08-03 14:56:30 +05:30
parent 65ea0640f8
commit ab7540c757
7 changed files with 188 additions and 18 deletions

View File

@@ -342,6 +342,65 @@ function DashboardPanel({
);
}
/**
* LazyVideo
* ---------------------------------------------------------------------------
* The workflow videos sit thousands of pixels below the fold (e.g. /miletruth
* renders one at document y≈9978), but a plain `<video autoPlay muted loop>`
* makes Chrome buffer the ENTIRE file at page load even while it is off-screen
* and still paused — and `preload="none"` does not stop it, because the browser
* keeps buffering to satisfy the pending autoplay. Measured on /miletruth that
* was 80.7 MB of mp4 pulled before the user scrolled at all (the 40 MB
* Doormile-quantum-video3.mp4 fetched twice over restarted byte ranges).
* On localhost that is free; on a deployed site it saturates the connection and
* the media pipeline exactly while the user is scrolling.
*
* Attaching the source only once the element nears the viewport defers all of
* it. Playback then starts exactly as before — `.evnd__video` is sized purely
* by CSS (width/height 100%), so an empty <video> occupies the identical box
* and nothing shifts.
*/
function LazyVideo({ src, ariaLabel }: { src: string; ariaLabel: string }) {
const ref = useRef<HTMLVideoElement>(null);
const [shouldLoad, setShouldLoad] = useState(false);
useEffect(() => {
const el = ref.current;
if (!el || shouldLoad) return;
const io = new IntersectionObserver(
(entries) => {
if (entries.some((e) => e.isIntersecting)) {
setShouldLoad(true);
io.disconnect();
}
},
// ~1.3 viewports of lead time: enough for the fetch to be well under way
// before the section arrives, without paying for it at page load.
{ rootMargin: "1200px 0px" },
);
io.observe(el);
return () => io.disconnect();
}, [shouldLoad]);
useEffect(() => {
if (shouldLoad) ref.current?.load();
}, [shouldLoad]);
return (
<video
ref={ref}
className="evnd__video"
autoPlay
muted
loop
playsInline
preload="none"
aria-label={ariaLabel}
src={shouldLoad ? src : undefined}
/>
);
}
export default function EVSection({
bannerImage = "/images/ev.webp",
cardNumber = "",
@@ -1449,23 +1508,19 @@ export default function EVSection({
{mediaSlot ? (
mediaSlot
) : isVideo ? (
<video
className="evnd__video"
autoPlay
muted
loop
playsInline
aria-label={imageAlt}
>
<source src={image} type="video/mp4" />
</video>
<LazyVideo src={image} ariaLabel={imageAlt} />
) : (
/* Same reason as LazyVideo: these stills are multi-MB raw
PNGs (e.g. /solutions' "ev section1.png" is 2.6 MB at
document y≈6793) and were being fetched and decoded
eagerly while far below the fold. */
/* eslint-disable-next-line @next/next/no-img-element */
<img
className="evnd__img"
src={image}
alt={imageAlt}
decoding="async"
loading="lazy"
/>
)}
{badges[0] && (