import { useState, useEffect, useRef } from "react"; import "./MusicPlayer.css"; import { useMusicPlayer } from "@/context/MusicPlayerContext"; import { IoPlayOutline, IoPauseOutline } from "react-icons/io5"; import { IoIosArrowDown, IoIosArrowUp } from "react-icons/io"; import { TbRewindBackward5, TbRewindForward5, TbPlayerStop, TbVolumeOff, TbVolume, TbPlayerSkipBack, TbPlayerSkipForward, TbPlaylist, TbPlaylistOff, } from "react-icons/tb"; import { RiFullscreenLine, RiFullscreenExitLine } from "react-icons/ri"; import { formatTime } from "./utils"; export default function MusicPlayer() { const { videoRef, isPlayerVisible, src, isPlayerMaximized, togglePlayerSize, setIsPlayerVisible, initializePlayer, title, setNowPlaying, nowPlaying, didDestroy, setDidDestroy, playNext, playPrevious, canPlayPrevious, canPlayNext, isPlayEueOpen, setIsPlayEueOpen, } = useMusicPlayer(); const [currentSrc, setCurrentSrc] = useState(src); const [currentTime, setCurrentTime] = useState(0); const [duration, setDuration] = useState(0); const [progress, setProgress] = useState(0); const [bufferProgress, setBufferProgress] = useState(0); const [isPlaying, setIsPlaying] = useState(false); const [showControls, setShowControls] = useState(true); const [isBuffering, setIsBuffering] = useState(true); const [volume, setVolume] = useState(1); const [isMuted, setIsMuted] = useState(false); const [isFullscreen, setIsFullscreen] = useState(false); const overlayTimeout = useRef(null); const seekTime = 5; const poster = "https://dlcdnwebimgs.asus.com/gain/4BB18AEF-347E-4DB6-B78C-C0FFE1F20385/w750/h470" // Event Handlers const handleTimeUpdate = (videoElement) => { if (videoElement) { setCurrentTime(videoElement.currentTime); setProgress((videoElement.currentTime / videoElement.duration) * 100); } }; const handleLoadedMetadata = (videoElement) => { if (videoElement) { setDuration(videoElement.duration); setProgress(0); setCurrentTime(0); videoElement.play(); } }; const handleProgress = (videoElement) => { if (videoElement && videoElement.buffered.length > 0) { const bufferEnd = videoElement.buffered.end( videoElement.buffered.length - 1 ); const bufferValue = (bufferEnd / videoElement.duration) * 100; setBufferProgress(bufferValue); } }; const handlePlay = () => { setIsPlaying(true); setNowPlaying(title); }; const handlePause = () => { setIsPlaying(false); setNowPlaying(""); }; const attachEventListeners = (videoElement) => { if (videoElement) { videoElement.addEventListener("timeupdate", () => handleTimeUpdate(videoElement) ); videoElement.addEventListener("loadedmetadata", () => handleLoadedMetadata(videoElement) ); videoElement.addEventListener("progress", () => handleProgress(videoElement) ); videoElement.addEventListener("play", handlePlay); videoElement.addEventListener("pause", handlePause); } }; const detachEventListeners = (videoElement) => { if (videoElement) { videoElement.removeEventListener("timeupdate", () => handleTimeUpdate(videoElement) ); videoElement.removeEventListener("loadedmetadata", () => handleLoadedMetadata(videoElement) ); videoElement.removeEventListener("progress", () => handleProgress(videoElement) ); videoElement.removeEventListener("play", handlePlay); videoElement.removeEventListener("pause", handlePause); } }; useEffect(() => { const videoElement = videoRef.current; // Attach event listeners attachEventListeners(videoElement); return () => { // Detach event listeners detachEventListeners(videoElement); }; }, [videoRef, currentSrc, nowPlaying, didDestroy]); useEffect(() => { if (src !== currentSrc) { setCurrentSrc(src); } }, [src, currentSrc]); useEffect(() => { if ('mediaSession' in navigator) { navigator.mediaSession.metadata = new MediaMetadata({ title: title, artwork: [ { src: poster } // Ensure 'poster' is defined in your component ] }); navigator.mediaSession.setActionHandler('play', () => { videoRef.current.play(); }); navigator.mediaSession.setActionHandler('pause', () => { videoRef.current.pause(); }); navigator.mediaSession.setActionHandler('seekbackward', (details) => { videoRef.current.currentTime = Math.max(videoRef.current.currentTime - (details.seekOffset || 10), 0); }); navigator.mediaSession.setActionHandler('seekforward', (details) => { videoRef.current.currentTime = Math.min(videoRef.current.currentTime + (details.seekOffset || 10), videoRef.current.duration); }); navigator.mediaSession.setActionHandler('stop', () => { destroyPlayer(); }); // New action handlers for previous and next navigator.mediaSession.setActionHandler('previoustrack', () => { playPrevious(); // Assuming playPrevious is a function that plays the previous track }); navigator.mediaSession.setActionHandler('nexttrack', () => { playNext(); // Assuming playNext is a function that plays the next track }); } // Cleanup function to reset media session when component unmounts return () => { if ('mediaSession' in navigator) { navigator.mediaSession.metadata = null; navigator.mediaSession.setActionHandler('play', null); navigator.mediaSession.setActionHandler('pause', null); navigator.mediaSession.setActionHandler('seekbackward', null); navigator.mediaSession.setActionHandler('seekforward', null); navigator.mediaSession.setActionHandler('stop', null); navigator.mediaSession.setActionHandler('previoustrack', null); navigator.mediaSession.setActionHandler('nexttrack', null); } }; }, [title, poster, playPrevious, playNext]); useEffect(() => { if (showControls) { if (overlayTimeout.current) { clearTimeout(overlayTimeout.current); } overlayTimeout.current = setTimeout(() => setShowControls(false), 3000); } return () => clearTimeout(overlayTimeout.current); }, [showControls]); const togglePlayPause = () => { if (videoRef.current) { if (isPlaying) { videoRef.current.pause(); } else { videoRef.current.play(); } setIsPlaying(!isPlaying); } }; const handleVolumeChange = (event) => { let volumeValue = parseFloat(event.target.value); // Ensure the volume is a finite number between 0 and 1 volumeValue = Math.max(0, Math.min(1, volumeValue)); setVolume(volumeValue); if (videoRef.current) { videoRef.current.volume = volumeValue; } setIsMuted(volumeValue === 0); }; const toggleMute = () => { if (isMuted) { videoRef.current.volume = volume; setIsMuted(false); } else { videoRef.current.volume = 0; setIsMuted(true); } }; const toggleFullscreen = () => { const doc = window.document; const docEl = doc.documentElement; const requestFullscreen = docEl.requestFullscreen || docEl.mozRequestFullScreen || docEl.webkitRequestFullscreen || docEl.msRequestFullscreen; const exitFullscreen = doc.exitFullscreen || doc.mozCancelFullScreen || docEl.webkitExitFullscreen || doc.msExitFullscreen; if (!isFullscreen) { requestFullscreen.call(docEl); } else { exitFullscreen.call(doc); } setIsFullscreen(!isFullscreen); }; const destroyPlayer = () => { if (videoRef.current) { videoRef.current.pause(); videoRef.current.currentTime = 0; videoRef.current.removeAttribute("src"); // Clear the source videoRef.current.load(); // Reload to reset duration/currentTime setNowPlaying(""); setCurrentSrc("/reset"); setCurrentTime(0); setDuration(0); setProgress(0); setBufferProgress(0); setIsPlaying(false); setIsPlayerVisible(false); setDidDestroy(true); console.log("setting didDestroy to true"); } }; const handleProgressClick = (e) => { const progressBar = e.currentTarget; const rect = progressBar.getBoundingClientRect(); const clickX = e.clientX - rect.left; const newTime = (clickX / rect.width) * duration; if (videoRef.current) { videoRef.current.currentTime = newTime; setCurrentTime(newTime); } }; const handleFastForward = () => { if (videoRef.current) { videoRef.current.currentTime = Math.min( videoRef.current.duration, videoRef.current.currentTime + seekTime ); } }; const handleRewind = () => { if (videoRef.current) { videoRef.current.currentTime = Math.max( 0, videoRef.current.currentTime - seekTime ); } }; const handleMouseMove = () => { setShowControls(true); }; const handleIsPlayQueueOpen = () =>{ setIsPlayEueOpen(!isPlayEueOpen); }; if (!isPlayerVisible || !currentSrc) return null; return (