Skip to content

Commit

Permalink
fix: player bugs
Browse files Browse the repository at this point in the history
  • Loading branch information
ricardocasares committed Oct 28, 2020
1 parent edd4b95 commit 46f0015
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 63 deletions.
4 changes: 3 additions & 1 deletion src/components/Layout/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import styled from "@emotion/styled";

export const Layout = styled.div`
height: 100vh;
width: 100%;
height: 100%;
display: grid;
position: fixed;
grid-template-rows: auto 1fr auto;
`;
37 changes: 16 additions & 21 deletions src/components/Player/index.tsx
Original file line number Diff line number Diff line change
@@ -1,41 +1,36 @@
import { useContext } from "react";
import { Play, Pause, Square } from "@geist-ui/react-icons";
import { Play, Pause, Square, AlertCircle } from "@geist-ui/react-icons";
import { LineSkeleton } from "@/components/Skeleton";
import { PlayerContext } from "@/lib/context/player";
import { Container, Controls, Title, Button } from "./style";
import { Container, Controls, Title, ErrorNotification, Button } from "./style";

export const Player = () => {
const {
station,
play,
pause,
stop,
error,
paused,
playing,
stopped,
loading,
} = useContext(PlayerContext);
const { station, play, pause, stop, error, playing, loading } = useContext(
PlayerContext
);

if (!station) return null;

const showPlay = playing && !error;
const showPause = paused && !error;
const showStation = (playing || paused) && !error;
if (error) {
return (
<ErrorNotification>
<AlertCircle /> <p>Oops, can't play this station :(</p>
</ErrorNotification>
);
}

return (
<Container>
{error && <Title>Error</Title>}
{loading && <LineSkeleton />}
{showStation && <Title>{station.name}</Title>}
{!loading && <Title>{station.name}</Title>}
<Controls>
{showPlay && (
{playing && (
<Button onClick={() => pause()}>
<Pause />
</Button>
)}
{showPause && (
<Button onClick={() => play(station)}>
{!playing && (
<Button onClick={() => play()}>
<Play />
</Button>
)}
Expand Down
17 changes: 16 additions & 1 deletion src/components/Player/style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,23 @@ export const Container = styled.footer`
export const Title = styled.div`
font-weight: 500;
text-align: center;
font-size: var(--sz3);
font-size: var(--sz4);
color: var(--foreground);
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
`;

export const ErrorNotification = styled.div`
font-weight: 500;
display: grid;
grid-gap: var(--sz4);
grid-template-columns: auto 1fr;
align-items: center;
color: var(--error-lighter);
background: var(--error);
font-size: var(--sz4);
padding: var(--sz5) var(--sz4);
`;

export const Controls = styled.section`
Expand Down
4 changes: 2 additions & 2 deletions src/components/StationCardList/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const Loader = noSSR(Placeholder);

export const GQLStations: FC<StationSearchInput> = graphql(
({ children: _, ...search }) => {
const { play } = useContext(PlayerContext);
const { load } = useContext(PlayerContext);

return (
<AutoGrid gridGap={["var(--sz4)"]}>
Expand All @@ -30,7 +30,7 @@ export const GQLStations: FC<StationSearchInput> = graphql(
key={[station.stationuuid, station.url].join("-")}
title={station.name}
subtitle={station.country}
onClick={() => play(station)}
onClick={() => load(station)}
/>
))}
</AutoGrid>
Expand Down
5 changes: 5 additions & 0 deletions src/css/global.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ export const styles = css`
${reset}
${theme}
html {
height: 100vh;
min-height: 100%;
}
body {
color: var(--foreground);
background: var(--background);
Expand Down
74 changes: 36 additions & 38 deletions src/lib/context/player.tsx
Original file line number Diff line number Diff line change
@@ -1,63 +1,63 @@
import { useState, useEffect, createContext, useRef } from "react";
import { Station } from "@/lib/graphql/gqless";
import styled from "@emotion/styled";

const Audio = styled.audio`
display: none;
`;

export type PlayerContext = {
play: (station: Station) => void;
play: () => void;
stop: () => void;
load: (s: Station) => void;
pause: () => void;
station?: Station | null;
error: boolean;
paused: boolean;
playing: boolean;
stopped: boolean;
loading: boolean;
};

export const PlayerContext = createContext<PlayerContext>({
station: null,
load: () => {},
play: () => {},
pause: () => {},
stop: () => {},
pause: () => {},
error: false,
paused: false,
playing: false,
stopped: false,
loading: false,
});

// @TODO: This is very messy
export const PlayerProvider = ({ children }) => {
const audio = useRef<HTMLAudioElement>(null);
const [station, setStation] = useState<Station>(null);

const [error, setError] = useState(false);
const [paused, setPaused] = useState(false);
const [station, setStation] = useState<Station>(null);
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 || error) {
const load = (s: Station) => {
if (audio.current.src !== s.url) {
// setLoading(true);
audio.current.src = s.url;
setStation(s);
setError(false);
setLoading(true);
setPlaying(false);
audio.current.play();
}

if (paused) {
audio.current.play();
}
};

const play = () => audio.current.play();
const pause = () => audio.current.pause();

const stop = () => {
audio.current.src = "";
audio.current.src =
"data:audio/wav;base64,UklGRiQAAABXQVZFZm10IBAAAAABAAEAVFYAAFRWAAABAAgAZGF0YQAAAAA=";
setError(false);
setStation(null);
setPaused(false);
setStopped(true);
setStation(null);
setLoading(false);
setPlaying(false);
};

Expand All @@ -66,71 +66,69 @@ export const PlayerProvider = ({ children }) => {
setPlaying(true);
setPaused(false);
setLoading(false);
setStopped(false);
};

const onCanPlay = () => {
setError(false);
setPaused(false);
setPlaying(true);
setLoading(false);
setStopped(false);
};

const onLoad = () => {
setError(false);
setPaused(false);
setLoading(true);
setPlaying(false);
setStopped(false);
setPaused(false);
};

const onPause = () => {
setPlaying(false);
setStopped(false);
setPaused(true);
setPlaying(false);
};

const onError = () => {
const onError = (e) => {
setError(true);
setPaused(false);
setPlaying(false);
setStopped(false);
setLoading(false);
};

const onEnded = () => {
setStation(null);
setPaused(false);
};

useEffect(() => {
audio.current.addEventListener("load", onLoad);
audio.current.addEventListener("error", onError);
audio.current.addEventListener("playing", onPlaying);
audio.current.addEventListener("canplay", onCanPlay);
audio.current.addEventListener("ended", onEnded);
audio.current.addEventListener("pause", onPause);
audio.current.addEventListener("loadstart", onLoad);
audio.current.addEventListener("playing", onPlaying);
audio.current.addEventListener("canplaythrough", onCanPlay);

return () => {
audio.current.removeEventListener("load", onLoad);
audio.current.removeEventListener("error", onError);
audio.current.removeEventListener("pause", onPause);
audio.current.removeEventListener("loadstart", onLoad);
audio.current.removeEventListener("playing", onPlaying);
audio.current.removeEventListener("canplay", onCanPlay);
audio.current.removeEventListener("canplaythrough", onCanPlay);
};
}, []);

return (
<PlayerContext.Provider
value={{
load,
play,
stop,
error,
pause,
paused,
loading,
playing,
stopped,
station,
}}
>
{children}
<audio ref={audio} style={{ display: "none" }} />
<Audio ref={audio} autoPlay={true} />
</PlayerContext.Provider>
);
};

0 comments on commit 46f0015

Please sign in to comment.