import { useEffect, useRef, useState } from "react"; interface HLSPlayerProps { src: string; title: string; onBack: () => void; } interface QualityLevel { height: number; width: number; bitrate: number; level: number; } interface AudioTrack { id: number; name: string; lang: string; } declare global { interface Window { Hls: any; } } export default function HLSPlayer({ src, title, onBack }: HLSPlayerProps) { const videoRef = useRef(null); const hlsRef = useRef(null); const [status, setStatus] = useState("جاري التحضير..."); const [isPlaying, setIsPlaying] = useState(false); const [qualityLevels, setQualityLevels] = useState([]); const [audioTracks, setAudioTracks] = useState([]); const [currentQuality, setCurrentQuality] = useState(-1); // -1 = auto const [currentAudio, setCurrentAudio] = useState(0); const [showControls, setShowControls] = useState(true); const [showQualityMenu, setShowQualityMenu] = useState(false); const [showAudioMenu, setShowAudioMenu] = useState(false); const controlsTimeoutRef = useRef(null); useEffect(() => { const loadHLS = async () => { try { // Load hls.js from CDN if (!window.Hls) { const script = document.createElement('script'); script.src = 'https://cdn.jsdelivr.net/npm/hls.js@latest'; script.onload = () => initializePlayer(); document.head.appendChild(script); } else { initializePlayer(); } } catch (error) { console.error('Error loading HLS.js:', error); setStatus('خطأ في تحميل المشغل'); } }; const initializePlayer = () => { const video = videoRef.current; if (!video) return; // Clean up previous instance if (hlsRef.current) { hlsRef.current.destroy(); hlsRef.current = null; } video.pause(); video.removeAttribute('src'); video.load(); // Check if browser supports HLS natively (Safari, iOS) if (video.canPlayType('application/vnd.apple.mpegURL')) { video.src = src; video.addEventListener('loadedmetadata', () => { video.play().catch(() => { setStatus('اضغط زر التشغيل للبدء'); }); }, { once: true }); setStatus('تشغيل مباشر عبر المتصفح (دعم HLS أصلي)'); } else if (window.Hls && window.Hls.isSupported()) { // Use hls.js for other browsers const hls = new window.Hls({ maxBufferLength: 30, maxBufferSize: 60 * 1000 * 1000, enableWorker: true, lowLatencyMode: true, }); hlsRef.current = hls; hls.on(window.Hls.Events.ERROR, (_e: any, data: any) => { console.warn('HLS error:', data); setStatus('خطأ في التشغيل: ' + (data?.details || data?.type || 'غير معروف')); }); hls.loadSource(src); hls.attachMedia(video); hls.on(window.Hls.Events.MANIFEST_PARSED, () => { // Get quality levels const levels = hls.levels.map((level: any, index: number) => ({ height: level.height, width: level.width, bitrate: level.bitrate, level: index })); setQualityLevels(levels); // Get audio tracks const tracks = hls.audioTracks.map((track: any, index: number) => ({ id: index, name: track.name || `Audio ${index + 1}`, lang: track.lang || 'unknown' })); setAudioTracks(tracks); video.play().catch((err) => { console.warn('Auto-play failed:', err); setStatus('اضغط زر التشغيل للبدء'); }); setStatus('تم تحميل القائمة وجاهز للتشغيل'); }); } else { setStatus('هذا المتصفح لا يدعم HLS'); } }; loadHLS(); // Cleanup return () => { if (hlsRef.current) { hlsRef.current.destroy(); hlsRef.current = null; } }; }, [src]); // Auto-hide controls useEffect(() => { const resetControlsTimeout = () => { if (controlsTimeoutRef.current) { clearTimeout(controlsTimeoutRef.current); } setShowControls(true); controlsTimeoutRef.current = setTimeout(() => { if (isPlaying) { setShowControls(false); } }, 3000); }; const handleMouseMove = () => resetControlsTimeout(); const handleTouchStart = () => resetControlsTimeout(); document.addEventListener('mousemove', handleMouseMove); document.addEventListener('touchstart', handleTouchStart); return () => { document.removeEventListener('mousemove', handleMouseMove); document.removeEventListener('touchstart', handleTouchStart); if (controlsTimeoutRef.current) { clearTimeout(controlsTimeoutRef.current); } }; }, [isPlaying]); const handlePlayPause = () => { const video = videoRef.current; if (!video) return; if (video.paused) { video.play(); setIsPlaying(true); } else { video.pause(); setIsPlaying(false); } }; const handleVideoPlay = () => setIsPlaying(true); const handleVideoPause = () => setIsPlaying(false); const selectQuality = (qualityLevel: number) => { const hls = hlsRef.current; if (!hls) return; if (qualityLevel === -1) { // Auto quality hls.currentLevel = -1; } else { hls.currentLevel = qualityLevel; } setCurrentQuality(qualityLevel); setShowQualityMenu(false); }; const selectAudioTrack = (trackId: number) => { const hls = hlsRef.current; if (!hls) return; hls.audioTrack = trackId; setCurrentAudio(trackId); setShowAudioMenu(false); }; const getQualityLabel = (level: QualityLevel) => { if (level.height >= 2160) return '4K'; if (level.height >= 1080) return 'FHD'; if (level.height >= 720) return 'HD'; if (level.height >= 480) return 'SD'; return `${level.height}p`; }; return (
{/* Header */}
{title}
{/* Video Container */}
{/* Status */}
{status}
); }