diff --git a/src/components/Player/index.tsx b/src/components/Player/index.tsx index dc5d7f64..a0621827 100644 --- a/src/components/Player/index.tsx +++ b/src/components/Player/index.tsx @@ -1,29 +1,45 @@ import { useContext } from "react"; import { Play, Pause, Square } from "@geist-ui/react-icons"; +import { LineSkeleton } from "@/components/Skeleton"; import { PlayerContext } from "@/lib/context/player"; import { Container, Controls, Title, Button } from "./style"; export const Player = () => { - const { station, play, pause, stop, paused, playing } = useContext( - PlayerContext - ); + const { + station, + play, + pause, + stop, + error, + paused, + playing, + stopped, + loading, + } = useContext(PlayerContext); + + // if (!station) return null; - if (!station) return null; + const showPlay = playing && !error; + const showPause = paused && !error; + const showStation = playing && !error; return ( - {station.name} + {error && Error} + {loading && } + {showStation && {station.name}} - {playing && ( + {showPlay && ( )} - {paused && ( + {showPause && ( )} + diff --git a/src/components/Player/style.ts b/src/components/Player/style.ts index 0f47171f..7fda2935 100644 --- a/src/components/Player/style.ts +++ b/src/components/Player/style.ts @@ -2,7 +2,8 @@ import styled from "@emotion/styled"; export const Container = styled.footer` display: grid; - padding: var(--sz3); + padding: var(--sz4); + grid-gap: var(--sz4); align-items: center; grid-template-columns: 1fr auto; background: var(--background); @@ -18,7 +19,6 @@ export const Title = styled.div` export const Controls = styled.section` display: grid; - padding: var(--sz1); grid-gap: var(--sz4); grid-auto-flow: column; justify-content: center; @@ -26,6 +26,7 @@ export const Controls = styled.section` export const Button = styled.button` margin: 0; + padding: 0; border: none; appearance: none; background: none; diff --git a/src/components/Skeleton/index.tsx b/src/components/Skeleton/index.tsx index 4376f2e7..01b21064 100644 --- a/src/components/Skeleton/index.tsx +++ b/src/components/Skeleton/index.tsx @@ -13,3 +13,15 @@ export const CardSkeleton = () => ( ); + +export const LineSkeleton = () => ( + + + +); diff --git a/src/components/StationCardList/index.tsx b/src/components/StationCardList/index.tsx index 085f5374..d1a759e6 100644 --- a/src/components/StationCardList/index.tsx +++ b/src/components/StationCardList/index.tsx @@ -24,7 +24,7 @@ export const GQLStations: FC = graphql( const { play } = useContext(PlayerContext); return ( - + {query.stations({ search }).map((station) => ( void; pause: () => void; station?: Station | null; + error: boolean; paused: boolean; playing: boolean; stopped: boolean; + loading: boolean; }; export const PlayerContext = createContext({ @@ -16,9 +18,11 @@ export const PlayerContext = createContext({ play: () => {}, pause: () => {}, stop: () => {}, + error: false, paused: false, playing: false, stopped: false, + loading: false, }); // @TODO: This is very messy @@ -28,11 +32,17 @@ export const PlayerProvider = ({ children }) => { const [paused, setPaused] = useState(false); const [playing, setPlaying] = useState(false); const [stopped, setStopped] = useState(false); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(false); const play = (s: Station) => { - if (audio.current.src !== s.url) { + if (audio.current.src !== s.url || error) { audio.current.src = s.url; - audio.current.play().then(() => setStation(s)); + setStation(s); + setError(false); + setLoading(true); + setPlaying(false); + audio.current.play(); } if (paused) { @@ -40,30 +50,68 @@ export const PlayerProvider = ({ children }) => { } }; - const pause = () => { - audio.current.pause(); - setPaused(true); - setPlaying(false); - setStopped(false); - }; + const pause = () => audio.current.pause(); const stop = () => { audio.current.src = ""; + setError(false); setStation(null); setPaused(false); setStopped(true); setPlaying(false); }; + const onPlaying = () => { + setError(false); + setPlaying(true); + setPaused(false); + setLoading(false); + setStopped(false); + }; + + const onCanPlay = () => { + setError(false); + setPaused(false); + setPlaying(true); + setLoading(false); + setStopped(false); + }; + + const onLoad = () => { + setError(false); + setLoading(true); + setPlaying(false); + setStopped(false); + setPaused(false); + }; + + const onPause = () => { + setPlaying(false); + setStopped(false); + setPaused(true); + }; + + const onError = () => { + setError(true); + setPaused(false); + setPlaying(false); + setStopped(false); + setLoading(false); + }; + useEffect(() => { - audio.current.addEventListener("playing", () => { - setPlaying(true); - setStopped(false); - setPaused(false); - }); + audio.current.addEventListener("load", onLoad); + audio.current.addEventListener("error", onError); + audio.current.addEventListener("playing", onPlaying); + audio.current.addEventListener("canplay", onCanPlay); + audio.current.addEventListener("pause", onPause); return () => { - audio.current.removeEventListener("playing", () => setPlaying(true)); + audio.current.removeEventListener("load", onLoad); + audio.current.removeEventListener("error", onError); + audio.current.removeEventListener("pause", onPause); + audio.current.removeEventListener("playing", onPlaying); + audio.current.removeEventListener("canplay", onCanPlay); }; }, []); @@ -72,8 +120,10 @@ export const PlayerProvider = ({ children }) => { value={{ play, stop, + error, pause, paused, + loading, playing, stopped, station,