import React, { useState, useEffect, useMemo, useRef } from 'react'; import { getYouTubeEmbedUrl } from '../utils/youtube'; interface VideoCellProps { cellId: string; initialUrl: string; onUrlChange: (newUrl: string) => void; cellNumber: number; isBorderless: boolean; isAudioActive: boolean; setPlayerInstance: (cellId: string, player: YT.Player | null) => void; isApiReady: boolean; } export const VideoCell: React.FC = ({ cellId, initialUrl, onUrlChange, cellNumber, isBorderless, isAudioActive, setPlayerInstance, isApiReady, }) => { const [inputValue, setInputValue] = useState(initialUrl); const playerRef = useRef(null); const iframeContainerRef = useRef(null); const embedUrl = useMemo(() => getYouTubeEmbedUrl(initialUrl), [initialUrl]); useEffect(() => { if (initialUrl !== inputValue) { setInputValue(initialUrl); } }, [initialUrl]); const handleSubmit = () => { if (inputValue !== initialUrl) { if (playerRef.current) { playerRef.current.destroy(); playerRef.current = null; setPlayerInstance(cellId, null); } onUrlChange(inputValue); } }; const handleInputChange = (event: React.ChangeEvent) => { setInputValue(event.target.value); }; const handleKeyDown = (event: React.KeyboardEvent) => { if (event.key === 'Enter') { handleSubmit(); event.currentTarget.blur(); } }; useEffect(() => { if (!isApiReady || !embedUrl || !window.YT || !iframeContainerRef.current) { if (playerRef.current) { playerRef.current.destroy(); playerRef.current = null; setPlayerInstance(cellId, null); } return; } const videoId = embedUrl.split('/embed/')[1]?.split('?')[0]; if (!videoId) return; if (playerRef.current) { playerRef.current.destroy(); playerRef.current = null; } const playerElementId = `ytplayer-${cellId}`; let playerHostDiv = document.getElementById(playerElementId); if (!playerHostDiv && iframeContainerRef.current) { playerHostDiv = document.createElement('div'); playerHostDiv.id = playerElementId; iframeContainerRef.current.innerHTML = ''; iframeContainerRef.current.appendChild(playerHostDiv); } if (!playerHostDiv) return; const player = new window.YT.Player(playerElementId, { height: '100%', // Player fills its container (playerHostDiv which is appended to iframeContainerRef) width: '100%', // Player fills its container videoId: videoId, playerVars: { autoplay: 1, mute: 1, controls: isBorderless ? 0 : 1, playsinline: 1, modestbranding: 1, rel: 0, iv_load_policy: 3, origin: window.location.origin, }, events: { onReady: (event) => { playerRef.current = event.target; setPlayerInstance(cellId, event.target); if (isAudioActive) { event.target.unMute(); } else { event.target.mute(); } }, onError: (event) => { console.error(`YouTube Player Error for ${cellId}:`, event.data); } }, }); return () => { if (playerRef.current) { // Check if destroy method exists before calling, good practice with external APIs if (typeof playerRef.current.destroy === 'function') { playerRef.current.destroy(); } playerRef.current = null; setPlayerInstance(cellId, null); } }; // eslint-disable-next-line react-hooks/exhaustive-deps }, [isApiReady, embedUrl, cellId, setPlayerInstance, isBorderless]); // isAudioActive removed as onReady handles initial mute based on it. Mute control is separate effect. useEffect(() => { if (playerRef.current && typeof playerRef.current.isMuted === 'function') { if (isAudioActive) { if (playerRef.current.isMuted()) { playerRef.current.unMute(); } } else { if (!playerRef.current.isMuted()) { playerRef.current.mute(); } } } }, [isAudioActive, cellId]); return (
{!isBorderless && ( <>

Video Cell {cellNumber}

)}
{(!isApiReady && embedUrl) &&

YouTube API loading...

} {!embedUrl && !isBorderless && (
Paste a YouTube URL above and press Enter or click away.
)} {embedUrl && !isApiReady && isBorderless && (
Loading video...
)} {(initialUrl && !embedUrl && !isBorderless) && (
Invalid or unsupported YouTube URL.
)}
); };