import React, { useRef, useState, useEffect } from 'react'; import { Play, Pause, RotateCcw, Volume2, Maximize, CheckCircle, ExternalLink } from 'lucide-react'; interface VideoPlayerProps { videoUrl: string; videoType: 'youtube' | 'direct'; lessonId: string; onProgressUpdate: (percentage: number) => void; initialProgress?: number; } export default function VideoPlayer({ videoUrl, videoType, lessonId, onProgressUpdate, initialProgress = 0 }: VideoPlayerProps) { const videoRef = useRef(null); const [isPlaying, setIsPlaying] = useState(false); const [currentTime, setCurrentTime] = useState(0); const [duration, setDuration] = useState(0); const [volume, setVolume] = useState(1); const [isCompleted, setIsCompleted] = useState(initialProgress >= 90); const [manualProgress, setManualProgress] = useState(initialProgress); // Sync state when lesson changes useEffect(() => { setIsCompleted(initialProgress >= 90); setManualProgress(initialProgress); setIsPlaying(false); setCurrentTime(0); }, [lessonId, initialProgress]); // For Direct HTML5 Video Player const handleTimeUpdate = () => { if (!videoRef.current) return; const current = videoRef.current.currentTime; const dur = videoRef.current.duration; setCurrentTime(current); if (dur > 0) { const percentage = Math.round((current / dur) * 100); setManualProgress(percentage); if (percentage >= 90 && !isCompleted) { setIsCompleted(true); onProgressUpdate(100); } else { // Debounce progress updates or update periodically onProgressUpdate(percentage); } } }; const togglePlay = () => { if (!videoRef.current) return; if (isPlaying) { videoRef.current.pause(); } else { videoRef.current.play().catch(e => console.log('Autoplay blocked')); } setIsPlaying(!isPlaying); }; const handleLoadedMetadata = () => { if (!videoRef.current) return; setDuration(videoRef.current.duration); }; const handleVolumeChange = (e: React.ChangeEvent) => { const newVol = parseFloat(e.target.value); setVolume(newVol); if (videoRef.current) { videoRef.current.volume = newVol; } }; const handleProgressSlider = (e: React.ChangeEvent) => { const pct = parseInt(e.target.value); setManualProgress(pct); onProgressUpdate(pct); if (pct >= 90) { setIsCompleted(true); } else { setIsCompleted(false); } }; const triggerManualCompletion = () => { setIsCompleted(true); setManualProgress(100); onProgressUpdate(100); }; const formatTime = (timeInSeconds: number) => { const minutes = Math.floor(timeInSeconds / 60); const seconds = Math.floor(timeInSeconds % 60); return `${minutes}:${seconds < 10 ? '0' : ''}${seconds}`; }; // YouTube embed parser const getYoutubeEmbedUrl = (url: string) => { let videoId = ''; // Handle watch?v= format if (url.includes('youtube.com/watch?v=')) { videoId = url.split('v=')[1]?.split('&')[0] || ''; } // Handle embed format else if (url.includes('youtube.com/embed/')) { videoId = url.split('embed/')[1]?.split('?')[0] || ''; } // Handle share format youtu.be/ else if (url.includes('youtu.be/')) { videoId = url.split('youtu.be/')[1]?.split('?')[0] || ''; } else { videoId = url; // assume id was passed directly } return `https://www.youtube.com/embed/${videoId}?modestbranding=1&rel=0&showinfo=0&controls=1&iv_load_policy=3&disablekb=1&fs=1`; }; return (
{/* Player Frame Container */}
{videoType === 'youtube' ? (