diff --git a/src/app.tsx b/src/app.tsx index 39f0c45d..62e5ce4b 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -4,12 +4,13 @@ import { QIcon, QKeyEvent, QMainWindow, QMainWindowSignals, WidgetEventTypes, Wi import nodeguiIcon from "../assets/nodegui.jpg"; import { MemoryRouter } from "react-router"; import Routes from "./routes"; -import SpotifyWebApi from "spotify-web-api-node"; import { LocalStorage } from "node-localstorage"; import authContext from "./context/authContext"; import playerContext, { CurrentPlaylist, CurrentTrack } from "./context/playerContext"; import Player, { audioPlayer } from "./components/Player"; -import { redirectURI } from "./conf"; +import express from "express"; +import open from "open"; +import spotifyApi from "./initializations/spotifyApi"; export enum CredentialKeys { credentials = "credentials", @@ -31,32 +32,30 @@ function RootApp() { const windowEvents = useEventHandler( { - async KeyRelease(nativeEv) { - try { - - if (nativeEv) { - const event = new QKeyEvent(nativeEv); - const eventKey = event.key(); - console.log('eventKey:', eventKey) - if(audioPlayer.isRunning() && currentTrack) - switch (eventKey) { - case 32: //space - await audioPlayer.isPaused() ? - await audioPlayer.play() : await audioPlayer.pause(); - break; - case 16777236: //arrow-right - await audioPlayer.isSeekable() && await audioPlayer.seek(+5); - break; - case 16777234: //arrow-left - await audioPlayer.isSeekable() && await audioPlayer.seek(-5); - break; - default: - break; + async KeyRelease(nativeEv) { + try { + if (nativeEv) { + const event = new QKeyEvent(nativeEv); + const eventKey = event.key(); + console.log("eventKey:", eventKey); + if (audioPlayer.isRunning() && currentTrack) + switch (eventKey) { + case 32: //space + (await audioPlayer.isPaused()) ? await audioPlayer.play() : await audioPlayer.pause(); + break; + case 16777236: //arrow-right + (await audioPlayer.isSeekable()) && (await audioPlayer.seek(+5)); + break; + case 16777234: //arrow-left + (await audioPlayer.isSeekable()) && (await audioPlayer.seek(-5)); + break; + default: + break; + } } + } catch (error) { + console.error("Error in window events: ", error); } - } catch (error) { - console.error("Error in window events: ", error) - } }, }, [currentTrack] @@ -68,7 +67,6 @@ function RootApp() { const [access_token, setAccess_token] = useState(""); const [currentPlaylist, setCurrentPlaylist] = useState(); - const spotifyApi = new SpotifyWebApi({ redirectUri: redirectURI, ...credentials }); const cachedCredentials = localStorage.getItem(CredentialKeys.credentials); const setExpireTime = (expirationDuration: number) => setExpires_in(Date.now() + expirationDuration); @@ -89,18 +87,37 @@ function RootApp() { windowRef.current?.removeEventListener(WidgetEventTypes.Close, onWindowClose); }; }); + // for user code login + useEffect(() => { + if (isLoggedIn && credentials && !localStorage.getItem(CredentialKeys.refresh_token)) { + const app = express(); + app.use(express.json()); + + app.get("/auth/spotify/callback", async (req, res) => { + try { + spotifyApi.setClientId(credentials.clientId); + spotifyApi.setClientSecret(credentials.clientSecret); + const { body: authRes } = await spotifyApi.authorizationCodeGrant(req.query.code); + setAccess_token(authRes.access_token); + setExpireTime(authRes.expires_in); + localStorage.setItem(CredentialKeys.refresh_token, authRes.refresh_token); + return res.end(); + } catch (error) { + console.error("Failed to fullfil code grant flow: ", error); + } + }); + + const server = app.listen(4304, () => { + console.log("Server is running"); + open(spotifyApi.createAuthorizeURL(["user-library-read", "user-library-modify"], "xxxyyysssddd")).catch((e) => console.error("Opening IPC connection with browser failed: ", e)); + }); + return () => { + server.close(() => console.log("Closed server")); + }; + } + }, [isLoggedIn, credentials]); useEffect(() => { - if (isLoggedIn) { - spotifyApi - .clientCredentialsGrant() - .then(({ body: { access_token } }) => { - setAccess_token(access_token); - }) - .catch((error) => { - console.error("Spotify Client Credential not granted for: ", error); - }); - } if (cachedCredentials) { setCredentials(JSON.parse(cachedCredentials)); } @@ -110,7 +127,7 @@ function RootApp() { - + {isLoggedIn && } diff --git a/src/components/Home.tsx b/src/components/Home.tsx index 28249659..2f850d41 100644 --- a/src/components/Home.tsx +++ b/src/components/Home.tsx @@ -5,34 +5,34 @@ import authContext from "../context/authContext"; import { useHistory } from "react-router"; import CachedImage from "./shared/CachedImage"; import { CursorShape } from "@nodegui/nodegui"; +import useSpotifyApi from "../hooks/useSpotifyApi"; function Home() { - const { spotifyApi, currentPlaylist } = useContext(playerContext); - const { isLoggedIn, access_token } = useContext(authContext); + const { currentPlaylist } = useContext(playerContext); + const spotifyApi = useSpotifyApi(); + const { access_token } = useContext(authContext); const [categories, setCategories] = useState([]); useEffect(() => { - (async () => { - try { - if (access_token) { - spotifyApi.setAccessToken(access_token); + if (access_token) { + (async () => { + try { const categoriesReceived = await spotifyApi.getCategories({ country: "US" }); setCategories(categoriesReceived.body.categories.items); + } catch (error) { + console.error("Spotify featured playlist loading failed: ", error); } - } catch (error) { - console.error("Spotify featured playlist loading failed: ", error); - } - })(); + })(); + } }, [access_token]); return ( {currentPlaylist && } - {isLoggedIn && - categories.map(({ id, name }, index) => { - return ; - })} + {categories.map((category, index) => { + return ; + })} ); @@ -48,21 +48,25 @@ interface CategoryCardProps { function CategoryCard({ id, name }: CategoryCardProps) { const history = useHistory(); const [playlists, setPlaylists] = useState([]); - const { access_token, isLoggedIn } = useContext(authContext); - const { spotifyApi, currentPlaylist } = useContext(playerContext); + const { currentPlaylist } = useContext(playerContext); + const spotifyApi = useSpotifyApi(); useEffect(() => { + let mounted = true; + (async () => { try { if (id !== "current") { - spotifyApi.setAccessToken(access_token); const playlistsRes = await spotifyApi.getPlaylistsForCategory(id, { limit: 4 }); - setPlaylists(playlistsRes.body.playlists.items); + mounted && setPlaylists(playlistsRes.body.playlists.items); } } catch (error) { console.error(`Failed to get playlists of category ${name} for: `, error); } })(); + return () => { + mounted = false; + }; }, []); function goToGenre() { @@ -103,10 +107,9 @@ function CategoryCard({ id, name }: CategoryCardProps) { {(playlists.length > 0 || id === "current") &&