Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- "use client";
- import usePlayer from "@/hooks/usePlayer";
- import { Song } from "@/types";
- import { useEffect, useRef, useState } from "react";
- import toast from "react-hot-toast";
- import { BsPauseFill, BsPlayFill } from "react-icons/bs";
- import { HiSpeakerWave, HiSpeakerXMark } from "react-icons/hi2";
- import { LuRepeat, LuRepeat1, LuShuffle, LuStepBack, LuStepForward } from "react-icons/lu";
- import useSound from "use-sound";
- import FavoriteButton from "./FavoriteButton";
- import MediaItem from "./MediaItem";
- import Slider from "./Slider";
- interface PlayerContentProps {
- song: Song;
- songUrl: string;
- }
- const PlayerContent: React.FC<PlayerContentProps> = ({
- song,
- songUrl
- }) => {
- const player = usePlayer();
- const [volume, setVolume] = useState(1);
- const [isPlaying, setIsPlaying] = useState(false);
- const [isRepeating, setIsRepeating] = useState(false);
- const isRepeatingRef = useRef(isRepeating);
- const Icon = isPlaying ? BsPauseFill : BsPlayFill;
- const VolumeIcon = volume === 0 ? HiSpeakerXMark : HiSpeakerWave;
- const RepeatIcon = isRepeating ? LuRepeat1 : LuRepeat;
- const onPlayNext = () => {
- if (player.ids.length === 0) { return; }
- const currentIndex = player.ids.findIndex((id) => id === player.activeId);
- const nextSong = player.ids[currentIndex + 1];
- if (!nextSong) { return player.setId(player.ids[0]); }
- player.setId(nextSong);
- }
- const onPlayPrevious = () => {
- if (player.ids.length === 0) { return; }
- const currentIndex = player.ids.findIndex((id) => id === player.activeId);
- const previousSong = player.ids[currentIndex - 1];
- if (!previousSong) { return player.setId(player.ids[player.ids.length - 1]); }
- player.setId(previousSong);
- }
- const [play, { pause, sound }] = useSound(
- songUrl,
- {
- volume: volume,
- onplay: () => setIsPlaying(true),
- onend: () => {
- setIsPlaying(false);
- toast("Song ended");
- if (isRepeatingRef.current) {
- toast("Repeating song...");
- sound?.pause().then(() => {
- toast("Song paused, now playing...");
- sound?.play();
- });
- } else {
- onPlayNext();
- }
- },
- onpause: () => setIsPlaying(false),
- format: ['mp3'],
- loop: isRepeating
- }
- );
- const handlePlay = () => {
- !isPlaying ? play() : pause();
- }
- const toggleMute = () => {
- setVolume(volume === 0 ? 1 : 0);
- }
- const handleShuffling = () => {
- toast.error('Shuffle mode is coming soon...')
- }
- useEffect(() => {
- isRepeatingRef.current = isRepeating
- }, [isRepeating])
- const handleRepeating = () => {
- setIsRepeating(!isRepeating)
- if (!isRepeating) {
- toast.success('Repeat mode enabled')
- } else {
- toast.success('Repeat mode disabled')
- }
- }
- useEffect(() => {
- sound?.play();
- return () => { sound?.unload(); }
- }, [sound]);
- return (
- <div className="grid grid-cols-2 md:grid-cols-3 h-full">
- <div className="flex w-full justify-start">
- <div className="flex items-center gap-x-4">
- <MediaItem data={song} />
- <FavoriteButton songId={song.id} />
- </div>
- </div>
- <div className="flex md:hidden col-auto w-full justify-end items-center">
- <div onClick={handlePlay} className="size-10 flex items-center justify-center rounded-full bg-white p-1 cursor-pointer">
- <Icon size={30} className="text-black" />
- </div>
- </div>
- <div className="hidden h-full md:flex justify-center items-center w-full max-w-[722px] gap-x-6">
- <LuShuffle onClick={handleShuffling} size={25} className="text-neutral-400 cursor-pointer hover:text-white transition" />
- <LuStepBack onClick={onPlayPrevious} size={30} className="text-neutral-400 cursor-pointer hover:text-white transition" />
- <div onClick={handlePlay} className="flex items-center justify-center size-10 rounded-full bg-white p-1 cursor-pointer">
- <Icon size={30} className="text-black" />
- </div>
- <LuStepForward onClick={onPlayNext} size={30} className="text-neutral-400 cursor-pointer hover:text-white transition" />
- <RepeatIcon onClick={handleRepeating} size={25} className={`cursor-pointer hover:text-white transition ${isRepeating ? 'text-white' : 'text-neutral-400'}`} />
- </div>
- <div className="hidden md:flex w-full justify-end pr-2">
- <div className="flex items-center gap-x-2 w-[120px]">
- <VolumeIcon onClick={toggleMute} className="cursor-pointer" size={34} />
- <Slider value={volume} onChange={(value) => setVolume(value)} />
- </div>
- </div>
- </div>
- );
- }
- export default PlayerContent;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement