"use client"; import React, { useState, useRef, useEffect } from 'react'; import { Play, Pause, Volume2, VolumeX, SkipBack, SkipForward, Maximize, Settings, Music, Video, FileText, Search } from 'lucide-react'; import Footer from '../footer'; import { ResizableHandle, ResizablePanel, ResizablePanelGroup, } from "@/components/ui/resizable"; // Media type detection const getMediaType = (url) => { const extension = url.split('.').pop()?.toLowerCase(); if (['mp4', 'webm', 'ogg', 'mov', 'avi'].includes(extension || '')) return 'video'; if (['mp3', 'wav', 'flac', 'aac', 'm4a'].includes(extension || '')) return 'audio'; if (['pdf', 'ppt', 'pptx'].includes(extension || '')) return 'slides'; return 'video'; // default }; import './style.css'; // Ensure you have a styles.css file for custom styles // Waveform Component (Winamp inspired) const WaveformVisualizer = ({ isPlaying, currentTime = 0 }) => { const canvasRef = useRef(null); useEffect(() => { const canvas = canvasRef.current; if (!canvas) return; const ctx = canvas.getContext('2d'); const width = canvas.width; const height = canvas.height; // Generate mock waveform data const bars = 100; const barWidth = width / bars; const animate = () => { ctx.clearRect(0, 0, width, height); for (let i = 0; i < bars; i++) { const barHeight = isPlaying ? Math.random() * height * 0.7 + height * 0.1 : height * 0.2; const x = i * barWidth; const progress = currentTime * bars; // Gradient effect const gradient = ctx.createLinearGradient(0, 0, 0, height); if (i < progress) { gradient.addColorStop(0, 'hsl(207, 90%, 54%)'); // accent color gradient.addColorStop(1, 'hsl(207, 90%, 64%)'); } else { gradient.addColorStop(0, 'hsl(0, 0%, 85%)'); // muted color gradient.addColorStop(1, 'hsl(0, 0%, 75%)'); } ctx.fillStyle = gradient; ctx.fillRect(x, height - barHeight, barWidth - 1, barHeight); } if (isPlaying) { requestAnimationFrame(animate); } }; animate(); }, [isPlaying, currentTime]); return (
); }; // Media Player Component const MediaPlayer = ({ media }) => { const [isPlaying, setIsPlaying] = useState(false); const [volume, setVolume] = useState(0.7); const [currentTime, setCurrentTime] = useState(0); const [duration, setDuration] = useState(0); const [isMuted, setIsMuted] = useState(false); const [playbackSpeed, setPlaybackSpeed] = useState(1); const videoRef = useRef(null); const playerContainerRef = useRef(null); const mediaType = getMediaType(media.url); const formatTime = (time) => { const minutes = Math.floor(time / 60); const seconds = Math.floor(time % 60); return `${minutes}:${seconds.toString().padStart(2, '0')}`; }; const handlePlayPause = () => { if (videoRef.current) { if (isPlaying) { videoRef.current.pause(); } else { videoRef.current.play(); } setIsPlaying(!isPlaying); } }; const handleVolumeChange = (e) => { const newVolume = parseFloat(e.target.value); setVolume(newVolume); if (videoRef.current) { videoRef.current.volume = newVolume; } }; const handleProgressChange = (e) => { const newTime = (parseFloat(e.target.value) / 100) * duration; setCurrentTime(newTime); if (videoRef.current) { videoRef.current.currentTime = newTime; } }; const toggleMute = () => { setIsMuted(!isMuted); if (videoRef.current) { videoRef.current.muted = !isMuted; } }; const toggleFullscreen = () => { if (!document.fullscreenElement) { playerContainerRef.current?.requestFullscreen(); } else { document.exitFullscreen(); } }; const skipTime = (seconds) => { if (videoRef.current) { videoRef.current.currentTime += seconds; } }; return (
{/* Media Display Area */}
{mediaType === 'video' && ( )} {mediaType === 'audio' && (

{media.title}

{media.artist || 'Unknown Artist'}

)} {mediaType === 'slides' && (

{media.title}

Presentation Slides

)} {/* Overlay Controls */}
{/* Waveform for Audio */} {mediaType === 'audio' && (
)} {/* Controls */}
{/* Progress Bar */}
{formatTime(currentTime)} {formatTime(duration)}
{/* Control Buttons */}
); }; // Media Library Component const MediaLibrary = ({ mediaList, onSelectMedia, selectedMedia }) => { const [searchQuery, setSearchQuery] = useState(''); const filteredMedia = mediaList.filter(media => media.title.toLowerCase().includes(searchQuery.toLowerCase()) || (media.artist && media.artist.toLowerCase().includes(searchQuery.toLowerCase())) ); const getMediaIcon = (url) => { const type = getMediaType(url); switch (type) { case 'video': return