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, comoopenVideoViewer.
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 umaspect-ratiode 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.
- Utiliza o componente
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
slotbeforeSettingsMenu. - Ao ser clicado, cria um elemento
<a>dinamicamente, atribui a URL do blob do vídeo aohrefe o nome do arquivo aodownload, 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
useContextdo React para acessar os dados dovideoViewerContext. - Verifica se o hook está sendo usado dentro de um
VideoViewerContextProvidere 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 objetoBlobdo 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>
</>
);
}