'use client'; import { useEffect, useRef, useState } from 'react'; import { useRouter } from 'next/navigation'; import LoadingSpinner from '../components/LoadingSpinner'; declare global { interface Window { YT: any; onYouTubeIframeAPIReady: () => void; } } interface YouTubePlayerProps { videoId: string; title?: string; autoplay?: boolean; onVideoEnd?: () => void; onVideoReady?: () => void; } function PlayerSkeleton() { return (
); } export default function YouTubePlayer({ videoId, title, autoplay = true, onVideoEnd, onVideoReady }: YouTubePlayerProps) { const playerRef = useRef(null); const playerInstanceRef = useRef(null); const [isApiReady, setIsApiReady] = useState(false); const [isPlayerReady, setIsPlayerReady] = useState(false); const [error, setError] = useState(null); const router = useRouter(); // Load YouTube IFrame API useEffect(() => { if (window.YT && window.YT.Player) { setIsApiReady(true); return; } // Check if script already exists const existingScript = document.querySelector('script[src*="youtube.com/iframe_api"]'); if (existingScript) { // Script exists, wait for it to load const checkYT = setInterval(() => { if (window.YT && window.YT.Player) { setIsApiReady(true); clearInterval(checkYT); } }, 100); return () => clearInterval(checkYT); } const tag = document.createElement('script'); tag.src = 'https://www.youtube.com/iframe_api'; tag.async = true; document.head.appendChild(tag); window.onYouTubeIframeAPIReady = () => { console.log('YouTube IFrame API ready'); setIsApiReady(true); }; return () => { // Clean up window.onYouTubeIframeAPIReady = () => {}; }; }, []); // Initialize player when API is ready useEffect(() => { if (!isApiReady || !playerRef.current || !videoId) return; // Destroy previous player instance if exists if (playerInstanceRef.current) { try { playerInstanceRef.current.destroy(); } catch (e) { console.log('Error destroying player:', e); } playerInstanceRef.current = null; } try { const player = new window.YT.Player(playerRef.current, { videoId: videoId, playerVars: { autoplay: autoplay ? 1 : 0, controls: 1, rel: 0, modestbranding: 0, playsinline: 1, enablejsapi: 1, origin: window.location.origin, widget_referrer: window.location.href, iv_load_policy: 3, fs: 0, disablekb: 0, color: 'white', }, events: { onReady: (event: any) => { console.log('YouTube Player ready for video:', videoId); setIsPlayerReady(true); if (onVideoReady) onVideoReady(); // Auto-play if enabled if (autoplay) { try { event.target.playVideo(); } catch (e) { console.log('Autoplay prevented:', e); } } }, onStateChange: (event: any) => { // Video ended if (event.data === window.YT.PlayerState.ENDED) { if (onVideoEnd) { onVideoEnd(); } } }, onError: (event: any) => { console.error('YouTube Player Error:', event.data); setError(`Failed to load video (Error ${event.data})`); }, }, }); playerInstanceRef.current = player; } catch (error) { console.error('Failed to create YouTube player:', error); setError('Failed to initialize video player'); } return () => { if (playerInstanceRef.current) { try { playerInstanceRef.current.destroy(); } catch (e) { console.log('Error cleaning up player:', e); } playerInstanceRef.current = null; } }; }, [isApiReady, videoId, autoplay]); // Handle video end useEffect(() => { if (!isPlayerReady || !onVideoEnd) return; const handleVideoEnd = () => { onVideoEnd(); }; // The onStateChange event handler already handles this }, [isPlayerReady, onVideoEnd]); if (error) { return (
{error}
); } return (
{!isPlayerReady && !error && }
); } // Utility function to play a video export function playVideo(videoId: string) { if (window.YT && window.YT.Player) { // Could create a new player instance or use existing one console.log('Playing video:', videoId); } } // Utility function to pause video export function pauseVideo() { // Would need to reference player instance }