import React, { useEffect, useState, useCallback } from 'react' import { PlayerProvider, usePlayerContext } from '../contexts/PlayerContext' import { VideoElement } from './VideoElement' import { ControlsLayer } from './ControlsLayer' import type { VideoPlayerProps, AudioTrack, VideoQuality } from '../types' import '../styles/variables.css' import './VideoPlayer.css' // Lazy load polyfills only if needed let polyfillsInitialized = false const initializePolyfillsIfNeeded = async () => { if (polyfillsInitialized) return // Check if polyfills are needed const needsFullscreenPolyfill = !document.fullscreenEnabled && !(document as any).webkitFullscreenEnabled const needsPIPPolyfill = !('pictureInPictureEnabled' in document) if (needsFullscreenPolyfill || needsPIPPolyfill) { const { initializePolyfills } = await import('../utils/polyfills') initializePolyfills() polyfillsInitialized = true } } // Initialize polyfills asynchronously initializePolyfillsIfNeeded() const VideoPlayerContent: React.FC< VideoPlayerProps & { audioTracks: AudioTrack[] onAudioTracksLoadedInternal: (tracks: AudioTrack[]) => void qualities: VideoQuality[] onQualityLevelsLoadedInternal: (qualities: VideoQuality[]) => void } > = ({ src, poster, autoplay = false, loop = false, muted = false, controls = true, subtitles = [], keyboardShortcuts = true, pictureInPicture = true, className = '', style, onPlay, onPause, onEnded, onTimeUpdate, onVolumeChange, onError, onLoadedMetadata, onSeeking, onSeeked, audioTracks, onAudioTracksLoadedInternal, qualities, onQualityLevelsLoadedInternal, }) => { const { containerRef, uiState } = usePlayerContext() const controlsHiddenClass = !uiState.controlsVisible ? 'controls-hidden' : '' return (
{controls && ( )}
) } export const VideoPlayer: React.FC = ({ src, poster, autoplay = false, loop = false, muted = false, controls = true, subtitles = [], theme, language, keyboardShortcuts = true, pictureInPicture = true, className = '', style, onPlay, onPause, onEnded, onTimeUpdate, onVolumeChange, onError, onLoadedMetadata, onSeeking, onSeeked, }) => { const [audioTracks, setAudioTracks] = useState([]) const [qualities, setQualities] = useState([]) // Apply theme CSS variables useEffect(() => { if (theme) { const root = document.documentElement if (theme.primaryColor) root.style.setProperty('--player-primary', theme.primaryColor) if (theme.accentColor) root.style.setProperty('--player-primary-hover', theme.accentColor) if (theme.backgroundColor) root.style.setProperty('--player-bg', theme.backgroundColor) if (theme.textColor) root.style.setProperty('--player-text', theme.textColor) } }, [theme]) const handleAudioTracksLoaded = useCallback((tracks: AudioTrack[]) => { setAudioTracks(tracks) }, []) const handleQualityLevelsLoaded = useCallback((levels: VideoQuality[]) => { setQualities(levels) }, []) return ( ) }