Skip to content

Commit

Permalink
chore: make audio player prettier remove some functionaliy
Browse files Browse the repository at this point in the history
  • Loading branch information
okanisildar committed Dec 17, 2023
1 parent 2e1f28e commit 89b1720
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 102 deletions.
13 changes: 1 addition & 12 deletions components/audio-player.module.css
Original file line number Diff line number Diff line change
@@ -1,14 +1,3 @@
.RatingsSelect {
appearance: none;
border: 0;
text-align: center;
font-size: 0.8rem;
.IconButton:hover {
background-color: transparent;
cursor: pointer;
width: 32px;
}

.RatingsSelect:focus-visible {
border: 0;
outline: 0;
}
184 changes: 98 additions & 86 deletions components/audio-player.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
/* eslint-disable jsx-a11y/media-has-caption -- we don't have any captions for our audio. */
'use client';
import type { ChangeEvent } from 'react';

import { Flex, IconButton, Slider, Text } from '@radix-ui/themes';
import { Box, Button, Flex, IconButton, Slider, Text } from '@radix-ui/themes';
import formatDuration from 'format-duration';
import { useRef, useState } from 'react';
import { FaPauseCircle } from 'react-icons/fa';
import { FaPauseCircle, FaPlay } from 'react-icons/fa';
import { FaCirclePlay } from 'react-icons/fa6';
import { IoVolumeMuteOutline } from 'react-icons/io5';
import { RiForward15Line, RiReplay15Fill } from 'react-icons/ri';
import { MdForward30, MdReplay30 } from 'react-icons/md';

import styles from './audio-player.module.css';

Expand All @@ -18,68 +16,60 @@ type Props = {
};

function AudioPlayerControls({
muted,
onFastForward,
onPlayPause,
onRewind,
onSetPlaybackRate,
playbackRate,
playerRef,
playing,
setMuted,
setPlaybackRate,
}: {
muted: boolean;
onFastForward: () => void;
onPlayPause: () => void;
onRewind: () => void;
onSetPlaybackRate: (rate: number) => void;
playbackRate: number;
playerRef: { current: HTMLAudioElement | null };
playing: boolean;
setMuted: (muted: boolean) => void;
setPlaybackRate: (rate: number) => void;
}) {
if (!playerRef.current) {
return (
<Flex align="center" direction="row" gap="3">
<Button highContrast onClick={onPlayPause} size="1">
<FaPlay />
Play
</Button>
</Flex>
);
}

return (
<Flex align="center" direction="row" gap="4">
<Flex align="center" direction="row" gap="3">
<IconButton
className={styles.IconButton}
highContrast
onClick={() => {
setMuted(!muted);
}}
onClick={onRewind}
variant="ghost"
>
<IoVolumeMuteOutline style={{ height: 30, width: 30 }} />
<MdReplay30 style={{ height: 28, width: 28 }} />
</IconButton>
<IconButton highContrast onClick={onRewind} variant="ghost">
<RiReplay15Fill style={{ height: 30, width: 30 }} />
</IconButton>
<IconButton highContrast onClick={onPlayPause} variant="ghost">
<IconButton
className={styles.IconButton}
highContrast
onClick={onPlayPause}
variant="ghost"
>
{playing ? (
<FaPauseCircle style={{ height: 30, width: 30 }} />
<FaPauseCircle style={{ height: 28, width: 28 }} />
) : (
<FaCirclePlay style={{ height: 30, width: 30 }} />
<FaCirclePlay style={{ height: 28, width: 28 }} />
)}
</IconButton>
<IconButton highContrast onClick={onFastForward} variant="ghost">
<RiForward15Line style={{ height: 30, width: 30 }} />
</IconButton>

<select
className={styles.RatingsSelect}
id="rating-select"
name="ratings"
onChange={(e: ChangeEvent<HTMLSelectElement>) => {
onSetPlaybackRate(Number(e.target.value));
setPlaybackRate(Number(e.target.value));
}}
value={playbackRate}
<IconButton
className={styles.IconButton}
highContrast
onClick={onFastForward}
variant="ghost"
>
<option value="0.5">0.5x</option>
<option value="0.75">0.75x</option>
<option value="1">1x</option>
<option value="1.25">1.25x</option>
<option value="1.5">1.50x</option>
<option value="2">2x</option>
</select>
<MdForward30 style={{ height: 28, width: 28 }} />
</IconButton>
</Flex>
);
}
Expand Down Expand Up @@ -107,33 +97,63 @@ function PlayerBar({
sm: '4',
}}
>
<Slider
defaultValue={[sliderPosition]}
max={duration}
onValueChange={(value) => {
if (typeof value[0] !== 'number' || !playerRef.current) {
return;
}
const position = Math.floor(value[0]);
setSliderPosition(position);
playerRef.current.currentTime = position;
<Box
style={{
minWidth: 50,
textAlign: 'center',
}}
size="2"
>
<Text
color="gray"
highContrast
size={{
initial: '1',
xs: '2',
}}
>
{formatDuration((playerRef.current?.currentTime ?? 0) * 1000)}
</Text>
</Box>
<Box
style={{
width: 300,
maxWidth: 240,
}}
value={[sliderPosition]}
/>
<Text
color="gray"
highContrast
size={{
initial: '1',
xs: '2',
>
<Slider
defaultValue={[sliderPosition]}
max={duration}
onValueChange={(value) => {
if (typeof value[0] !== 'number' || !playerRef.current) {
return;
}
const position = Math.floor(value[0]);
setSliderPosition(position);
playerRef.current.currentTime = position;
}}
size="1"
style={{
width: 240,
}}
value={[sliderPosition]}
/>
</Box>
<Box
style={{
minWidth: 50,
textAlign: 'center',
}}
>
{formatDuration((duration - sliderPosition) * 1000)} left
</Text>
<Text
color="gray"
highContrast
size={{
initial: '1',
xs: '2',
}}
>
-{formatDuration((duration - sliderPosition) * 1000)}
</Text>
</Box>
</Flex>
);
}
Expand All @@ -143,15 +163,14 @@ export default function AudioPlayer({ audioUrl, duration }: Props) {
const playerRef = useRef<HTMLAudioElement | null>(null);
const [sliderPosition, setSliderPosition] = useState(0);
const [playbackRate, setPlaybackRate] = useState<number>(1);
const [muted, setMuted] = useState(false);

const onRewind = () => {
if (!playerRef.current) return;
playerRef.current.currentTime = playerRef.current.currentTime - 15;
playerRef.current.currentTime = playerRef.current.currentTime - 30;
};
const onFastForward = () => {
if (!playerRef.current) return;
playerRef.current.currentTime = playerRef.current.currentTime + 15;
playerRef.current.currentTime = playerRef.current.currentTime + 30;
};
const onPlayPause = async () => {
if (!playerRef.current) return;
Expand All @@ -162,11 +181,6 @@ export default function AudioPlayer({ audioUrl, duration }: Props) {
}
};

const onSetPlaybackRate = (value: number) => {
if (!playerRef.current) return;
playerRef.current.playbackRate = value;
};

return (
<Flex
align={{
Expand All @@ -187,7 +201,6 @@ export default function AudioPlayer({ audioUrl, duration }: Props) {
}}
>
<audio
muted={muted}
onEnded={() => {
setPlaying(false);
}}
Expand Down Expand Up @@ -215,22 +228,21 @@ export default function AudioPlayer({ audioUrl, duration }: Props) {
src={audioUrl}
/>
<AudioPlayerControls
muted={muted}
onFastForward={onFastForward}
onPlayPause={onPlayPause}
onRewind={onRewind}
onSetPlaybackRate={onSetPlaybackRate}
playbackRate={playbackRate}
playing={playing}
setMuted={setMuted}
setPlaybackRate={setPlaybackRate}
/>
<PlayerBar
duration={duration}
playerRef={playerRef}
setSliderPosition={setSliderPosition}
sliderPosition={sliderPosition}
playing={playing}
/>
{playerRef.current ? (
<PlayerBar
duration={playerRef.current.duration}
playerRef={playerRef}
setSliderPosition={setSliderPosition}
sliderPosition={sliderPosition}
/>
) : null}
</Flex>
);
}
20 changes: 16 additions & 4 deletions components/episode-detail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ function EpisodeDetailContent(
sm: 'row',
}}
gap={{
initial: '4',
xs: '5',
initial: '6',
sm: '6',
}}
>
<Avatar
Expand All @@ -59,10 +59,19 @@ function EpisodeDetailContent(
src={props.image ?? ''}
/>

<Flex direction="column" gap="3" justify="end">
<Flex
align={{
initial: 'center',
sm: 'start',
}}
direction="column"
gap="3"
justify="end"
width="100%"
>
<Heading
size={{
initial: '2',
initial: '1',
xs: '3',
}}
>
Expand All @@ -84,6 +93,9 @@ function EpisodeDetailContent(
initial: '9',
sm: '5',
}}
style={{
marginBottom: 10,
}}
>
<AudioPlayer audioUrl={props.audio_url} duration={props.duration} />
</Box>
Expand Down

0 comments on commit 89b1720

Please sign in to comment.