Pular para o conteúdo principal

VideoViewerContext

O VideoViewerContext é um Contexto React projetado para fornecer uma solução global e desacoplada para visualização de vídeos em um modal. Ele abstrai toda a complexidade de gerenciamento de estado, renderização do player e interações do usuário, permitindo que qualquer componente na aplicação possa solicitar a abertura de um vídeo com uma única chamada de função.

Propósito e Arquitetura

O principal objetivo é evitar que componentes de baixo nível (como itens de um carrossel) precisem gerenciar o estado de um modal de alta ordem. Ao centralizar essa lógica, garantimos consistência visual e de comportamento em toda a aplicação.

A arquitetura consiste em:

  • VideoViewerContextProvider: O provedor que contém a lógica do modal e o estado. Ele deve ser instanciado no topo da árvore de componentes da aplicação (em _app.tsx).
  • useVideoViewerModal: Um hook customizado que atua como a API pública do contexto, expondo apenas as funções necessárias para os componentes consumidores, como openVideoViewer.

VideoViewerContextProvider

Este componente é o núcleo da funcionalidade.

  • Estado Interno:

    • isOpen: boolean: Controla a visibilidade do modal.
    • video: VideoData | null: Armazena os dados do vídeo a ser reproduzido (URL, nome do arquivo, blob, etc.).
  • Renderização:

    • Utiliza o componente <Modal> do Material-UI, que ocupa a tela inteira e centraliza seu conteúdo via classes do Tailwind CSS (flex items-center justify-center).
    • O contêiner do vídeo agora possui um tamanho fixo e proporcional, ocupando 90vw (90% da largura da tela) e mantendo um aspect-ratio de vídeo (16:9), independentemente da orientação original do vídeo.
    • Renderiza o player de vídeo <MediaPlayer> da biblioteca @vidstack/react.
    • O player é configurado para autoplay e inclui o layout padrão DefaultVideoLayout, que oferece controles de reprodução, volume, tela cheia, etc.

Componente Customizado: DownloadButton

Para atender à necessidade de permitir que os usuários salvem os vídeos, um botão de download customizado foi adicionado à barra de controles do player.

  • Ele é injetado no layout do Vidstack através do slot beforeSettingsMenu.
  • Ao ser clicado, cria um elemento <a> dinamicamente, atribui a URL do blob do vídeo ao href e o nome do arquivo ao download, e simula um clique para iniciar o download.
const DownloadButton: React.FC<{ video: VideoData }> = ({ video }) => {
const handleDownload = () => {
if (!video.url) return;
const a = document.createElement("a");
a.href = video.url;
a.download = video.filename || "video.mp4";
a.click();
};

return (
<button
className="vds-button vds-tooltip-trigger"
aria-label="Download"
onClick={handleDownload}
>
<DownloadSimple size={24} />
</button>
);
};

useVideoViewerModal

Este hook é a forma recomendada e segura de interagir com o contexto.

  • Ele utiliza o useContext do React para acessar os dados do videoViewerContext.
  • Verifica se o hook está sendo usado dentro de um VideoViewerContextProvider e lança um erro caso contrário, prevenindo bugs em tempo de desenvolvimento.
  • Retorna um objeto contendo a função openVideoViewer.

openVideoViewer(videoData: VideoData)

Esta função é chamada para abrir o modal com um vídeo específico.

  • Parâmetros:
    • videoData: Um objeto contendo:
      • url: A URL do vídeo. Pode ser uma URL de objeto (blob:...) gerada a partir de um arquivo local, ou uma URL direta para uma fonte externa (ex: YouTube).
      • filename?: O nome do arquivo (opcional), usado para o título do player e para o nome do arquivo no download.
      • file?: O objeto Blob do vídeo (opcional). Se fornecido, habilita o botão de download e otimiza o player.

Exemplo de Uso Completo:

import { useVideoViewerModal } from "src/context/video-viewer-context";

function MyComponentWithVideoButtons() {
const { openVideoViewer } = useVideoViewerModal();

// Exemplo 1: Abrindo um vídeo a partir de um Blob de arquivo local
const handlePlayLocalVideo = (videoBlob, fileName) => {
const videoUrl = URL.createObjectURL(videoBlob);
openVideoViewer({
url: videoUrl,
filename: fileName,
file: videoBlob,
});
};

// Exemplo 2: Abrindo um vídeo a partir de uma URL externa
const handlePlayExternalVideo = () => {
openVideoViewer({
url: "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
filename: "Vídeo Externo de Exemplo",
});
};

return (
<>
{/* Supondo que você tenha o blob e o nome do arquivo */}
<button onClick={() => handlePlayLocalVideo(myBlob, myFileName)}>
Abrir Vídeo Local
</button>
<button onClick={handlePlayExternalVideo}>Abrir Vídeo Externo</button>
</>
);
}