parch-cast/components/podcast-player.tsx

137 lines
4.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client";
import { Button } from "@/components/ui/button";
import { Slider } from "@/components/ui/slider";
import {
FastForward,
Pause,
Play,
Rewind,
SkipBack,
SkipForward,
Volume2,
} from "lucide-react";
import Image from "next/image";
import { useRef, useState, useEffect } from "react";
export function PodcastPlayer() {
const audioRef = useRef<HTMLAudioElement>(null);
const [isPlaying, setIsPlaying] = useState(false);
const [currentTime, setCurrentTime] = useState(0);
const [duration, setDuration] = useState(0); // Add duration state
// Update current time and duration as the audio plays
useEffect(() => {
const audio = audioRef.current;
if (!audio) return;
const updateTime = () => setCurrentTime(audio.currentTime);
const updateDuration = () => setDuration(audio.duration);
audio.addEventListener("timeupdate", updateTime);
audio.addEventListener("loadedmetadata", updateDuration);
return () => {
audio.removeEventListener("timeupdate", updateTime);
audio.removeEventListener("loadedmetadata", updateDuration);
};
}, []);
const handlePlaying = () => {
if (isPlaying) {
audioRef.current?.pause();
} else {
audioRef.current?.play();
}
setIsPlaying(!isPlaying);
};
const formatTime = (time: number) => {
if (isNaN(time)) return "0:00"; // Handle NaN case
const minutes = Math.floor(time / 60);
const seconds = Math.floor(time % 60);
return `${minutes}:${seconds.toString().padStart(2, "0")}`;
};
return (
<div className="fixed bottom-0 left-0 right-0 border-t bg-background p-4">
<audio
src="http://webaudioapi.com/samples/audio-tag/chrono.mp3"
className="hidden"
ref={audioRef}
/>
<div className="mx-auto flex container items-center justify-between">
<div className="flex items-center gap-4">
<Image
src="https://picsum.photos/48"
alt="Episode Cover"
width={48}
height={48}
className="rounded-md"
/>
<div>
<h4 className="text-sm font-medium">قسمت اول: داستان پارچ</h4>
<p className="text-xs text-muted-foreground">Efoux</p>
</div>
</div>
<div className="flex flex-col items-center gap-1 md:w-1/2">
<div className="flex items-center gap-2">
<Button variant="ghost" size="icon" className="h-8 w-8">
<SkipForward className="h-4 w-4" />
<span className="sr-only">Next</span>
</Button>
<Button variant="ghost" size="icon" className="h-8 w-8">
<FastForward className="h-4 w-4" />
<span className="sr-only">Fast Forward</span>
</Button>
<Button
variant="outline"
size="icon"
className="h-10 w-10 rounded-full"
onClick={handlePlaying}
>
{isPlaying ? (
<Pause className="h-5 w-5" />
) : (
<Play className="h-5 w-5" />
)}
<span className="sr-only">{isPlaying ? "Pause" : "Play"}</span>
</Button>
<Button variant="ghost" size="icon" className="h-8 w-8">
<Rewind className="h-4 w-4" />
<span className="sr-only">Rewind</span>
</Button>
<Button variant="ghost" size="icon" className="h-8 w-8">
<SkipBack className="h-4 w-4" />
<span className="sr-only">Previous</span>
</Button>
</div>
<div className="flex w-full items-center gap-2">
<div className="text-xs tabular-nums text-muted-foreground">
{formatTime(duration)} {/* Use duration state */}
</div>
<Slider
value={[currentTime]}
max={duration}
step={1}
className="w-full"
onValueChange={(value) => {
if (audioRef.current) {
audioRef.current.currentTime = value[0];
setCurrentTime(value[0]);
}
}}
/>
<div className="text-xs tabular-nums text-muted-foreground">
{formatTime(currentTime)}
</div>
</div>
</div>
<div className="hidden items-center gap-2 md:flex">
<Volume2 className="h-4 w-4 text-muted-foreground" />
<Slider defaultValue={[70]} max={100} step={1} className="w-20" />
</div>
</div>
</div>
);
}