Skip to content

Commit

Permalink
Podcast 💬
Browse files Browse the repository at this point in the history
  • Loading branch information
EvanderInacio committed Sep 7, 2022
1 parent 979db6c commit ec2e868
Show file tree
Hide file tree
Showing 11 changed files with 523 additions and 142 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"axios": "^0.27.2",
"date-fns": "^2.29.2",
"next": "12.2.5",
"rc-slider": "^10.0.1",
"react": "18.2.0",
"react-dom": "18.2.0",
"sass": "^1.54.8"
Expand Down
158 changes: 136 additions & 22 deletions src/components/Player/index.tsx
Original file line number Diff line number Diff line change
@@ -1,48 +1,162 @@
/* eslint-disable jsx-a11y/alt-text */
/* eslint-disable @next/next/no-img-element */
import React from "react"
import Image from 'next/image'
import React, { useEffect, useRef, useState } from 'react'
import { usePlayer } from '../../contexts/PlayerContext'

import Slider from 'rc-slider'
import 'rc-slider/assets/index.css'

import { convertDurationToTimeString } from '../../utils/convertDurationToTimeSting';
import styles from './styles.module.scss'

export function Player() {
return(
const audioRef = useRef<HTMLAudioElement>(null);
const [progress, setProgress] = useState(0)

const { episodeList,
currentEpisodeIndex,
isPlaying,
isLooping,
isShuffling,
togglePlay,
toggleLoop,
toggleShuffle,
setPlayingState,
playNext,
playPrevious,
hasNext,
hasPrevious,
clearPlayerState
} = usePlayer()

useEffect(() => {
if(!audioRef.current) return;

if(isPlaying) {
audioRef.current.play()
} else {
audioRef.current.pause()
}
}, [isPlaying])

function setupProgressListener() {
audioRef.current.currentTime = 0;

audioRef.current.addEventListener('timeupdate', () => {
setProgress(Math.floor(audioRef.current.currentTime))
})
}

function handleSeek(amount: number) {
audioRef.current.currentTime = amount;
setProgress(amount);
}

function handleEpisodeEnded() {
if(hasNext) {
playNext()
} else {
clearPlayerState()
}
}

const episode = episodeList[currentEpisodeIndex];

return (
<div className={styles.playerContainer}>
<header>
<img src="/playing.svg" alt="tocando agora" />
<strong>Tocando agora</strong>
</header>

<div className={styles.emptyPlayer}>
<strong>Selecione um podcast para ouvir.</strong>
</div>
{episode ? (
<div className={styles.currentEpisode}>
<div className={styles.imageThumbnail}>
<Image
width={592}
height={592}
src={episode.thumbnail}
objectFit="cover"
/>
</div>
<strong>{episode.title}</strong>
</div>
) : (
<div className={styles.emptyPlayer}>
<strong>Selecione um podcast para ouvir</strong>
</div>
)}

<footer className={styles.empty}>
<footer className={!episode ? styles.empty : ''}>
<div className={styles.progress}>
<span>00:00</span>
<span>{convertDurationToTimeString(progress)}</span>
<div className={styles.slider}>
<div className={styles.emptySlider} />
{ episode ? (
<Slider
max={episode.duration}
value={progress}
onChange={handleSeek}
trackStyle={{ backgroundColor: '#04d361'}}
railStyle={{ background: '#9f75ff' }}
handleStyle={{ borderColor: '#04d361', borderWidth: 4 }}
/>
) : (
<div className={styles.emptySlider} />
)}
</div>
<span>00:00</span>
<span>{convertDurationToTimeString(episode?.duration ?? 0)}</span>
</div>

{ episode && (
<audio
src={episode.url}
ref={audioRef}
loop={isLooping}
autoPlay
onEnded={handleEpisodeEnded}
onPlay={() => setPlayingState(true)}
onPause={() => setPlayingState(false)}
onLoadedMetadata={setupProgressListener}
/>
)}

<div className={styles.buttons}>
<button type="button">
<img src="/shuffle.svg" alt="Embaralhar" />
<button
type="button"
disabled={!episode || episodeList.length === 1}
onClick={toggleShuffle}
className={isShuffling ? styles.isActive : ''}
>
<img src="/shuffle.svg" alt="Embaralhar"/>
</button>
<button type="button">
<img src="/play-previous.svg" alt="Tocar anterior" />
<button type="button" onClick={playPrevious} disabled={!episode || !hasPrevious}>
<img src="/play-previous.svg" alt="Tocar anterior"/>
</button>
<button type="button" className={styles.playButton}>
<img src="/play.svg" alt="Tocar" />
<button
type="button"
className={styles.playButton}
disabled={!episode}
onClick={togglePlay}
>
{ isPlaying
? <img src="/pause.svg" alt="Tocar"/>
: <img src="/play.svg" alt="Tocar"/>
}
</button>
<button type="button">
<img src="/play-next.svg" alt="Tocar proxima" />
</button>
<button type="button">
<img src="/repeat.svg" alt="Repetir" />
<button type="button" onClick={playNext} disabled={!episode || !hasNext} >
<img src="/play-next.svg" alt="Tocar próxima"/>
</button>
<button
type="button"
disabled={!episode}
onClick={toggleLoop}
className={isLooping ? styles.isActive : ''}
>
<img src="/repeat.svg" alt="Repetir" />
</button>
</div>
</footer>

</div>
)
}
}
64 changes: 61 additions & 3 deletions src/components/Player/styles.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,33 @@
opacity: 0.5;
}
}

}

.currentEpisode {
text-align: center;

img {
border-radius: 1.5rem;
}

strong {
display: block;
margin-top: 1rem;
font: 600 1rem Lexend, sans-serif;
line-height: 1.20rem;
}

span {
display: block;
opacity: 0.6;
line-height: 1.5rem
}
}

.emptyPlayer {
width: 100%;
height: 20rem;

border: 1.5px dashed var(--purple-300);
border-radius: 1.5rem ;
background: linear-gradient(143.8deg, rgba(145, 100, 250, 0.8) 0%, rgba(0, 0, 0, 0) 100% );
Expand Down Expand Up @@ -83,20 +104,43 @@
border: 0;
font-size: 0;

transition: filter 0.2s;

&:disabled {
cursor: default;
opacity: 0.5;
}

&:hover:not(:disabled) {
filter: brightness(0.7);
}

&.isActive {
filter: invert(0.35) sepia(1) saturate(3) hue-rotate(100deg)
}

&.isActive:hover {
filter: brightness(0.6) invert(0.35) sepia(1) saturate(3) hue-rotate(100deg)
}

&.playButton {
width: 4rem;
height: 4rem;
border-radius: 1rem;
background: var(--purple-400);

&:hover:not(:disabled) {
filter: brightness(0.95);
}
}
}
}


@media (max-width: 768px) {
.playerContainer {
width: 100vw;
height: 10rem;
height: 11.5rem;
position: fixed;
bottom: 0;
z-index: 100;
Expand All @@ -110,5 +154,19 @@
margin-top: -1.5rem;
}
}


.currentEpisode {
.imageThumbnail{
display: none;
}

strong {
margin-top: -2.2rem;
margin-bottom: 2rem;
}
}

.buttons {
margin-top: 1rem;
}
}
Loading

0 comments on commit ec2e868

Please sign in to comment.