"use client"; import Image from "next/image"; import { useEffect, useRef, useState } from "react"; import { useReducedMotion } from "@/app/hooks/useReducedMotion"; import type { ShowcaseAssets } from "@/lib/project-showcase"; import { useSaveData } from "./showcase/useShowcaseMedia"; /** * Vídeo de rolagem na capa do card. `video` já é a versão do aparelho (quem chama escolhe: celular abaixo de * 768 px; no servidor, nenhuma). Quem decide se ele toca é a vitrine (`active`: só um card por vez, o que está * sob o mouse ou o mais perto do centro da tela). Nada do vídeo é baixado antes da primeira vez que o card * fica ativo (`preload="metadata"`, sem fontes até lá); fora de cena ele pausa. Com prefers-reduced-motion ou * "economizar dados" só o pôster aparece. `showPoster` falso (seção longe da tela) não pede nem o pôster. * O pôster também fica por baixo (fundo da tela da moldura): o vídeo aparece em fade quando começa a tocar. */ export function ProjectVideo({ video, title, active, showPoster = true, }: { video: ShowcaseAssets; title: string; active: boolean; showPoster?: boolean; }) { const reducedMotion = useReducedMotion(); const saveData = useSaveData(); const ref = useRef(null); const [attached, setAttached] = useState(false); const [ready, setReady] = useState(false); const posterOnly = reducedMotion || saveData; const playing = active && !posterOnly; const firstSource = video.sources[0]?.src; useEffect(() => { if (playing) setAttached(true); }, [playing]); useEffect(() => { // as fontes entram depois do primeiro render (ou mudam com o aparelho): o elemento precisa ler a lista nova if (attached && firstSource) ref.current?.load(); }, [attached, firstSource]); useEffect(() => { const element = ref.current; if (!element || !attached) return; if (playing) { element.muted = true; // o React não reflete `muted` no DOM e o autoplay exige o valor real element.play().catch(() => {}); } else { element.pause(); // também cancela um autoplay que ainda esperava o arquivo chegar } }, [attached, playing]); if (posterOnly) { if (!showPoster) return null; return ( {`Captura ); } return ( ); }