Created
October 24, 2024 14:43
-
-
Save lilpolymath/0d690f9fbdc58debd4cbb08e2a27f1c6 to your computer and use it in GitHub Desktop.
Sample demo on how to use now-playing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// all wrapped inside <SpotifyContextProvider> | |
const Hero = () => { | |
const playingDetails = useSpotify(); | |
const [playing, setPlaying] = useState(false); | |
const playerRef = useRef < HTMLAudioElement > null; | |
const statusText = playingDetails.isPlaying ? "NOW PLAYING" : "LAST PLAYED"; | |
const handlePlayPause = () => { | |
if (!playingDetails.previewUrl) { | |
return; | |
} | |
if (playing) { | |
playerRef.current?.pause(); | |
setPlaying(false); | |
} else { | |
playerRef.current?.play(); | |
setPlaying(true); | |
} | |
}; | |
useEffect(() => { | |
if (playingDetails.previewUrl && playerRef.current) { | |
setPlaying(false); | |
playerRef.current.src = playingDetails.previewUrl; | |
playerRef.current.load(); | |
} | |
}, [JSON.stringify(playingDetails.previewUrl)]); | |
return ( | |
<div> | |
{playingDetails.previewUrl && ( | |
<audio | |
ref={playerRef} | |
src={playingDetails.previewUrl} | |
preload="auto" | |
onEnded={() => setPlaying(false)} | |
/> | |
)} | |
<button className="now-playing" onClick={() => handlePlayPause()}> | |
<span className="now-playing__status">{playing ? "yes" : "no"}</span> | |
</button> | |
<span className="sr-only"> | |
{statusText}: {playingDetails.songName} BY {playingDetails.artistName} | |
</span> | |
</div> | |
); | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// app/api/spotify/route.ts | |
import { NowPlaying, Providers } from "@bolajiolajide/now-playing"; | |
export const dynamic = 'force-dynamic' | |
export const GET = async () => { | |
try { | |
if (process.env.NODE_ENV !== 'production') { | |
return new Response(JSON.stringify({ | |
title: 'Test Song (Non-production env)', | |
artiste: 'Chronixx', | |
image_url: 'https://i.scdn.co/image/ab67616d0000b273fb3d081418a02919fb1bb58f', | |
is_playing: true, | |
preview_url: 'https://p.scdn.co/mp3-preview/2d7798a99d7c4091da509418b6b752463d569547?cid=98dee14da74049fdbc531633fec2f9ae', | |
url: '' | |
}), { | |
status: 200, | |
headers: { "Content-Type": "application/json" }, | |
}); | |
} | |
const nowPlaying = new NowPlaying(Providers.SPOTIFY, { | |
streamerArgs: { | |
clientId: process.env.SPOTIFY_CLIENT_ID!, | |
clientSecret: process.env.SPOTIFY_CLIENT_SECRET!, | |
refreshToken: process.env.SPOTIFY_REFRESH_TOKEN!, | |
}, | |
}); | |
const playingDetails = await nowPlaying.fetchCurrentlyPlayingOrLastPlayed(); | |
return new Response(JSON.stringify(playingDetails), { | |
status: 200, | |
headers: { "Content-Type": "application/json" }, | |
}); | |
} catch (error) { | |
return new Response(JSON.stringify({ error: error.message }), { | |
status: 500, | |
headers: { "Content-Type": "application/json" }, | |
}); | |
} | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"use client"; | |
import { createContext, useState, useEffect, useContext } from "react"; | |
export type SpotifyPlayingDetails = { | |
url: string; | |
artistName: string; | |
songName: string; | |
previewUrl: string; | |
coverImageUrl: string; | |
isPlaying: boolean; | |
loading: boolean; | |
}; | |
const SpotifyContext = createContext({ | |
url: "", | |
artistName: "", | |
songName: "", | |
previewUrl: "", | |
isPlaying: false, | |
coverImageUrl: "", | |
loading: false, | |
}); | |
export const useSpotify = () => | |
useContext<SpotifyPlayingDetails>(SpotifyContext); | |
export const SpotifyProvider = ({ children }) => { | |
const [playingDetails, setPlayingDetails] = useState<SpotifyPlayingDetails>({ | |
url: "", | |
artistName: "", | |
songName: "", | |
previewUrl: "", | |
isPlaying: false, | |
coverImageUrl: "", | |
loading: true | |
}); | |
useEffect(() => { | |
const fetchPlayingDetails = () => { | |
fetch("/api/spotify") | |
.then((res) => res.json()) | |
.then((data) => { | |
setPlayingDetails({ | |
url: data.url, | |
artistName: data.artiste, | |
songName: data.title, | |
previewUrl: data.preview_url, | |
coverImageUrl: data.image_url, | |
isPlaying: data.is_playing, | |
loading: false, | |
}); | |
}) | |
.catch((error) => { | |
setPlayingDetails((prev) => ({...prev, loading: false })); | |
console.error("Error fetching playing details:", error); | |
}); | |
}; | |
setPlayingDetails((prev) => ({...prev, loading: true })); | |
fetchPlayingDetails(); | |
const intervalId = setInterval(fetchPlayingDetails, 30000); | |
return () => clearInterval(intervalId); | |
}, []); | |
return ( | |
<SpotifyContext.Provider value={playingDetails}> | |
{children} | |
</SpotifyContext.Provider> | |
); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment