import { useState, useEffect, useRef } from 'react'; import { ChevronLeft, Maximize, Volume2, VolumeX, Radio, Menu, X, Search } from 'lucide-react'; import { Link } from 'wouter'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { useQuery } from '@tanstack/react-query'; import VideoCard from '@/components/video-card'; import AdSenseAd from '@/components/adsense-ad'; declare global { interface Window { Hls: any; } } export default function LivePage() { const videoRef = useRef(null); const hlsRef = useRef(null); const [isLoading, setIsLoading] = useState(true); const [isPlaying, setIsPlaying] = useState(false); const [volume, setVolume] = useState(1); const [isMuted, setIsMuted] = useState(false); const [error, setError] = useState(null); const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false); const [searchQuery, setSearchQuery] = useState(""); // HLS stream URL const streamUrl = 'https://cdne.folxplay.tv/fxt/streams/ch-4/master.m3u8'; // Fetch suggested videos const { data: videosData } = useQuery({ queryKey: ['/api/videos'], staleTime: 5 * 60 * 1000, // 5 minutes }); const videos = (videosData && Array.isArray((videosData as any).videos)) ? (videosData as any).videos : []; useEffect(() => { // Set page meta tags document.title = 'LIVE Stream | video.folx.tv'; const metaDescription = document.querySelector('meta[name="description"]'); if (metaDescription) { metaDescription.setAttribute('content', 'Live stream on video.folx.tv - watch exclusive content in real time.'); } const updateMetaTag = (property: string, content: string) => { let meta = document.querySelector(`meta[property="${property}"]`); if (!meta) { meta = document.createElement('meta'); meta.setAttribute('property', property); document.head.appendChild(meta); } meta.setAttribute('content', content); }; updateMetaTag('og:title', 'LIVE Stream - video.folx.tv'); updateMetaTag('og:description', 'Live stream on video.folx.tv - watch exclusive content in real time.'); updateMetaTag('og:type', 'video.other'); }, []); // Initialize player immediately on mount useEffect(() => { initializePlayer(); return () => { if (hlsRef.current) { hlsRef.current.destroy(); } if (videoRef.current) { videoRef.current.src = ''; } }; }, []); const initializePlayer = async () => { console.log('πŸ”΄ LivePage: Starting to initialize player...'); if (!videoRef.current) { console.error('🚨 Video ref not available!'); return; } console.log('πŸ”΄ Video element found, continuing...'); try { // Load HLS.js if not already loaded console.log('πŸ”΄ Checking if HLS.js is loaded...'); if (!window.Hls) { console.log('πŸ”΄ Loading HLS.js script...'); const script = document.createElement('script'); script.src = 'https://cdn.jsdelivr.net/npm/hls.js@1.5.8'; script.async = true; document.head.appendChild(script); await new Promise((resolve, reject) => { script.onload = () => { console.log('βœ… HLS.js script loaded successfully'); resolve(null); }; script.onerror = (e) => { console.error('❌ Failed to load HLS.js script:', e); reject(e); }; }); } else { console.log('βœ… HLS.js already available'); } const video = videoRef.current; console.log('πŸ”΄ Stream URL:', streamUrl); if (window.Hls && window.Hls.isSupported()) { console.log('πŸ”΄ HLS.js is supported, initializing...'); const hls = new window.Hls({ debug: true, enableWorker: false, lowLatencyMode: true, backBufferLength: 90, maxBufferLength: 30, maxMaxBufferLength: 600, maxBufferSize: 60 * 1000 * 1000, maxBufferHole: 0.5 }); console.log('πŸ”΄ Loading source:', streamUrl); hls.loadSource(streamUrl); hls.attachMedia(video); hls.on(window.Hls.Events.MEDIA_ATTACHED, () => { console.log('βœ… HLS media attached successfully'); }); hls.on(window.Hls.Events.MANIFEST_PARSED, (event: any, data: any) => { console.log('βœ… HLS manifest parsed successfully:', data); console.log('Available levels:', data.levels); setIsLoading(false); // Try auto-play video.play().then(() => { console.log('βœ… Auto-play started successfully'); }).catch((e) => { console.log('⚠️ Auto-play blocked, user interaction required:', e); setError('Kliknite play za zagon streama'); }); }); hls.on(window.Hls.Events.LEVEL_LOADED, (event: any, data: any) => { console.log('πŸ“Š Level loaded:', data); }); hls.on(window.Hls.Events.FRAG_LOADED, (event: any, data: any) => { console.log('πŸ“¦ Fragment loaded:', data.frag.url); }); hls.on(window.Hls.Events.ERROR, (event: any, data: any) => { console.error('🚨 HLS Error occurred:', { type: data.type, details: data.details, fatal: data.fatal, error: data.error, event, data }); if (data.fatal) { switch (data.type) { case window.Hls.ErrorTypes.NETWORK_ERROR: console.log('πŸ”„ Network error, attempting recovery...'); setError('Napaka pri povezavi s streamom - poskuΕ‘am znova...'); hls.startLoad(); break; case window.Hls.ErrorTypes.MEDIA_ERROR: console.log('πŸ”„ Media error, attempting recovery...'); setError('Napaka pri predvajanju - poskuΕ‘am znova...'); hls.recoverMediaError(); break; default: console.error('πŸ’₯ Fatal error, cannot recover:', data); setError(`Napaka pri streamingu: ${data.details}`); break; } } }); hlsRef.current = hls; } else if (video.canPlayType('application/vnd.apple.mpegurl')) { // Native HLS support (Safari) console.log('🍎 Using native HLS support (Safari)'); video.src = streamUrl; video.addEventListener('loadedmetadata', () => { console.log('βœ… Native HLS metadata loaded'); setIsLoading(false); }); video.addEventListener('error', (e) => { console.error('❌ Native video error:', e); setError('Napaka pri nalaganju streama'); }); } else { console.error('❌ HLS not supported in this browser'); setError('HLS ni podprt v tem brskalniku'); setIsLoading(false); } // Add comprehensive video event listeners video.addEventListener('play', () => { console.log('▢️ Video started playing'); setIsPlaying(true); }); video.addEventListener('pause', () => { console.log('⏸️ Video paused'); setIsPlaying(false); }); video.addEventListener('volumechange', () => { setVolume(video.volume); setIsMuted(video.muted); }); video.addEventListener('loadstart', () => { console.log('πŸ”„ Video load started'); }); video.addEventListener('loadeddata', () => { console.log('πŸ“Š Video data loaded'); }); video.addEventListener('canplay', () => { console.log('βœ… Video can start playing'); }); video.addEventListener('error', (e) => { console.error('❌ Video element error:', e); setError('Napaka video elementa'); }); } catch (error) { console.error('πŸ’₯ Failed to initialize live stream player:', error); setError('Napaka pri inicializaciji playerja'); setIsLoading(false); } }; const togglePlayPause = () => { if (videoRef.current) { if (isPlaying) { videoRef.current.pause(); } else { videoRef.current.play().catch((e) => { console.log('Play failed:', e); setError('Napaka pri predvajanju'); }); } } }; const toggleMute = () => { if (videoRef.current) { videoRef.current.muted = !isMuted; } }; const toggleFullscreen = () => { if (videoRef.current) { if (videoRef.current.requestFullscreen) { videoRef.current.requestFullscreen(); } } }; return (
{/* Header */}
{/* Left side - Logo */}

video.folx.tv

{/* Right side - Navigation + Search */}
{/* Desktop navigation */}
setSearchQuery(e.target.value)} className="bg-white border border-gray-300 rounded-lg px-4 py-1.5 pl-10 text-sm text-gray-900 placeholder-gray-500 focus:outline-none focus:border-[#da234d] transition-colors w-56" />
{/* Mobile menu button */}
{/* Mobile menu dropdown */} {isMobileMenuOpen && (
{/* Navigation Section */}

Navigation

{/* Separator */}
{/* Search Section */}

Suchen

setSearchQuery(e.target.value)} className="bg-white/10 border border-white/20 rounded-lg px-4 py-2.5 pl-10 text-sm text-white placeholder-white/60 focus:outline-none focus:border-[#da234d] focus:bg-white/15 transition-all w-full" />
)}
{/* Main Video Player */}
{error && (

Stream Error

{error}

)}
{/* AdSense Ad under video stream */}
{/* Sidebar - Empfohlene Videos */}
{/* Sidebar Ad */}

Empfohlene Videos

{videos.slice(0, 10).map((video: any) => (
{ const shortId = video.id.replace(/-/g, '').substring(0, 8); window.location.href = `/video/${shortId}`; }} className="flex gap-3 p-2 bg-bunny-gray/30 hover:bg-bunny-gray/50 rounded-lg cursor-pointer transition-colors" >
{video.title} { const target = e.target as HTMLImageElement; target.style.display = 'none'; if (target.parentElement && !target.parentElement.querySelector('.thumbnail-placeholder')) { target.parentElement.style.background = 'linear-gradient(135deg, #1f2937, #374151)'; const placeholder = document.createElement('div'); placeholder.className = 'thumbnail-placeholder absolute inset-0 flex items-center justify-center text-white text-xs'; placeholder.innerHTML = '
🎬
'; target.parentElement.appendChild(placeholder); } }} />
{video.duration ? Math.floor(video.duration / 60) + ':' + String(video.duration % 60).padStart(2, '0') : '0:00'}

{video.title}

{video.views ? (video.views >= 1000 ? Math.floor(video.views / 1000) + 'K' : video.views) : '0'} views β€’ {video.createdAt ? new Date(video.createdAt).toLocaleDateString('de-DE') : 'Unknown date'}
))}
{/* Bottom Sidebar Ad */}
); }