Error Applet component, little incomplete documentation & incomplete tabmenu added

This commit is contained in:
root 2021-03-03 10:31:45 +06:00
parent faea24e86e
commit fe39ab0ffd
13 changed files with 590 additions and 184 deletions

View File

@ -1,63 +1,44 @@
# react-nodegui-starter
# Spotube
Spotube is a [qt](https://qt.io) based lightweight spotify client which uses [nodegui/react-nodegui](https://github.com/nodegui/react-nodegui) as frontend & nodejs as backend. It utilizes the power of Spotify & Youtube's public API & creates a hazardless, performant & resource friendly User Experience
**Clone and run for a quick way to see React NodeGui in action.**
## Features
Following are the features that currently spotube offers:
- Open Source
- No telementry, diagnostics or user data collection
- Lightweight & resource friendly
- Near native performance & seemless with default desktop themes (Win10, Win7, OSX, QT-default)
- Playback control is on user's machine instead of server based
- Small size & less data hungry
- No spotify or youtube ads since it uses all public & free APIs (But it's recommended to support the creators by watching/liking/subscribing to the artists youtube channel or add as favourite track in spotify. Mostly buying spotify premium is the best way to support their valuable creations)
<img alt="logo" src="https://github.com/nodegui/react-nodegui-starter/raw/master/assets/demo.png" height="500" />
## Installation
I'm always releasing newer versions of binary of the software each 2-3 month with minor changes & each 6-8 month with major changes. Grab the binaries
## To Use
Windows: [.exe]()
To clone and run this repository you'll need [Git](https://git-scm.com) and [Node.js](https://nodejs.org/en/download/) (which comes with [npm](http://npmjs.com)) installed on your computer. From your command line:
OSX: **I hate apple** (Just kidding, actually don't have a mac)
```bash
# Clone this repository
git clone https://github.com/nodegui/react-nodegui-starter
# Install CMake
brew install cmake
# Go into the repository
cd react-nodegui-starter
# Install dependencies
npm install
# Run the dev server
npm run dev
# Open andother terminal and run the app
npm start
```
Linux: [.appimage]()
## Installation & Resources for learning React NodeGui
- [Documentation](https://react.nodegui.org) - all of React NodeGui's documentation.
- [NodeGui](https://nodegui.org) - all of NodeGui's documentation.
**I'll/try to upload the package binaries to linux debian/arch/ubuntu/snap/flatpack/redhat stores or software centers or repositories**
## Packaging app as a distributable
## Configuration
There are some configurations that needs to be done to start using this software
In order to distribute your finished app, you can use [@nodegui/packer](https://github.com/nodegui/packer)
You need a spotify account & a web app for
### Step 1: (_**Run this command only once**_)
- clientId
- clientSecret
```sh
npx nodegui-packer --init MyAppName
```
See these screenshots:
This will produce the deploy directory containing the template. You can modify this to suite your needs. Like add icons, change the name, description and add other native features or dependencies. Make sure you commit this directory.
[1]()
### Step 2: (_**Run this command every time you want to build a new distributable**_)
[2]()
Next you can run the pack command:
[3]()
```sh
npm run build
```
[4]()
This will produce the js bundle along with assets inside the `./dist` directory
```sh
npx nodegui-packer --pack ./dist
```
This will build the distributable using @nodegui/packer based on your template. The output of the command is found under the build directory. You should gitignore the build directory.
More details about packer can be found here: https://github.com/nodegui/packer
## License
MIT
**[Important]!**: No personal data or any kind of sensitive information won't be collected from spotify. Don't believe? See the code for yourself

327
spotube.sublime-workspace Normal file
View File

@ -0,0 +1,327 @@
{
"auto_complete":
{
"selected_items":
[
]
},
"buffers":
[
{
"file": "src/components/Player.tsx",
"settings":
{
"buffer_size": 8355,
"line_ending": "Unix"
}
},
{
"file": "src/routes.tsx",
"settings":
{
"buffer_size": 688,
"line_ending": "Unix"
}
}
],
"build_system": "",
"build_system_choices":
[
],
"build_varint": "",
"command_palette":
{
"height": 0.0,
"last_filter": "",
"selected_items":
[
[
"Types: Sh",
"TypeScript: Show Error List"
],
[
"pro",
"Project: Save As"
],
[
"insta",
"Package Control: Install Package"
],
[
"re",
"Package Control: Remove Package"
],
[
"lsp type",
"Preferences: LSP-typescript Settings"
],
[
"install ",
"Package Control: Install Package"
],
[
"LSP: enale",
"LSP: Enable Language Server in Project"
],
[
"remove",
"Package Control: Remove Package"
],
[
"theme",
"UI: Select Theme"
],
[
"termi",
"Terminus: Close"
],
[
"Sync Up",
"Sync Settings: Upload"
],
[
"Sync crea",
"Sync Settings: Create and Upload"
],
[
"package ins",
"Package Control: Install Package"
],
[
"pac",
"Install Package Control"
]
],
"width": 0.0
},
"console":
{
"height": 170.0,
"history":
[
]
},
"distraction_free":
{
"menu_visible": true,
"show_minimap": false,
"show_open_files": false,
"show_tabs": false,
"side_bar_visible": false,
"status_bar_visible": false
},
"file_history":
[
"/home/krtirtho/development/desktop-dev/spotube/spotube.sublime-project",
"/home/krtirtho/.config/sublime-text-3/Packages/User/Preferences.sublime-settings",
"/home/krtirtho/.config/sublime-text-3/Packages/TypeScript/Preferences.sublime-settings",
"/home/krtirtho/.config/sublime-text-3/Packages/TypeScript/TypeScriptReact.sublime-settings",
"/home/krtirtho/.config/sublime-text-3/Packages/TypeScript/TypeScript.sublime-settings",
"/home/krtirtho/.config/sublime-text-3/Packages/Default/Default (Linux).sublime-keymap",
"/home/krtirtho/.config/sublime-text-3/Packages/User/Default (Linux).sublime-keymap",
"/home/krtirtho/.config/sublime-text-3/Packages/Sync Settings/SyncSettings.sublime-settings",
"/home/krtirtho/.config/sublime-text-3/Packages/User/SyncSettings.sublime-settings"
],
"find":
{
"height": 26.0
},
"find_in_files":
{
"height": 0.0,
"where_history":
[
]
},
"find_state":
{
"case_sensitive": false,
"find_history":
[
],
"highlight": true,
"in_selection": false,
"preserve_case": false,
"regex": false,
"replace_history":
[
],
"reverse": false,
"show_context": true,
"use_buffer2": true,
"whole_word": false,
"wrap": true
},
"groups":
[
{
"selected": 1,
"sheets":
[
{
"buffer": 0,
"file": "src/components/Player.tsx",
"semi_transient": false,
"settings":
{
"buffer_size": 8355,
"regions":
{
},
"selection":
[
[
2966,
2966
]
],
"settings":
{
"syntax": "Packages/TypeScript/TypeScriptReact.tmLanguage",
"tab_size": 2,
"translate_tabs_to_spaces": true,
"use_tab_stops": false
},
"translation.x": 0.0,
"translation.y": 1275.0,
"zoom_level": 1.0
},
"stack_index": 1,
"type": "text"
},
{
"buffer": 1,
"file": "src/routes.tsx",
"semi_transient": false,
"settings":
{
"buffer_size": 688,
"regions":
{
},
"selection":
[
[
688,
688
]
],
"settings":
{
"color_scheme": "Packages/GitHub Theme/schemes/GitHub Dark.sublime-color-scheme",
"syntax": "Packages/TypeScript/TypeScriptReact.tmLanguage",
"tab_size": 2,
"translate_tabs_to_spaces": true,
"typescript_plugin_format_options":
{
"convertTabsToSpaces": true,
"indentSize": 2,
"tabSize": 2
},
"use_tab_stops": false
},
"translation.x": 0.0,
"translation.y": 0.0,
"zoom_level": 1.0
},
"stack_index": 0,
"type": "text"
}
]
}
],
"incremental_find":
{
"height": 26.0
},
"input":
{
"height": 38.0
},
"layout":
{
"cells":
[
[
0,
0,
1,
1
]
],
"cols":
[
0.0,
1.0
],
"rows":
[
0.0,
1.0
]
},
"menu_visible": true,
"output.diagnostics":
{
"height": 0.0
},
"output.doc":
{
"height": 0.0
},
"output.errorlist":
{
"height": 140.0
},
"output.find_results":
{
"height": 0.0
},
"pinned_build_system": "",
"project": "spotube.sublime-project",
"replace":
{
"height": 48.0
},
"save_all_on_build": true,
"select_file":
{
"height": 0.0,
"last_filter": "",
"selected_items":
[
],
"width": 0.0
},
"select_project":
{
"height": 0.0,
"last_filter": "",
"selected_items":
[
],
"width": 0.0
},
"select_symbol":
{
"height": 0.0,
"last_filter": "",
"selected_items":
[
],
"width": 0.0
},
"selected_group": 0,
"settings":
{
},
"show_minimap": true,
"show_open_files": true,
"show_tabs": true,
"side_bar_visible": true,
"side_bar_width": 225.0,
"status_bar_visible": true,
"template_settings":
{
}
}

View File

@ -139,12 +139,10 @@ function RootApp() {
<authContext.Provider value={{ isLoggedIn, setIsLoggedIn, access_token, expires_in, setAccess_token, setExpires_in: setExpireTime, ...credentials }}>
<playerContext.Provider value={{ currentPlaylist, currentTrack, setCurrentPlaylist, setCurrentTrack }}>
<QueryClientProvider client={queryClient}>
{/* <View style={`flex: 1; flex-direction: 'column'; justify-content: 'center'; align-items: 'stretch'; height: '100%';`}> */}
<BoxView direction={Direction.TopToBottom}>
<View style={`flex: 1; flex-direction: 'column'; justify-content: 'center'; align-items: 'stretch'; height: '100%';`}>
<Routes />
{isLoggedIn && <Player />}
</BoxView>
{/* </View> */}
</View>
</QueryClientProvider>
</playerContext.Provider>
</authContext.Provider>

View File

@ -1,38 +1,43 @@
import React, { useContext, useEffect, useState } from "react";
import { Button, ScrollArea, BoxView } from "@nodegui/react-nodegui";
import React from "react";
import { Button, ScrollArea, BoxView, View } from "@nodegui/react-nodegui";
import { useHistory } from "react-router";
import CachedImage from "./shared/CachedImage";
import { CursorShape, Direction } from "@nodegui/nodegui";
import useSpotifyApi from "../hooks/useSpotifyApi";
import showError from "../helpers/showError";
import authContext from "../context/authContext";
import useSpotifyApiError from "../hooks/useSpotifyApiError";
import { QueryCacheKeys } from "../conf";
import useSpotifyQuery from "../hooks/useSpotifyQuery";
import ErrorApplet from "./shared/ErrorApplet";
function Home() {
const spotifyApi = useSpotifyApi();
const { access_token } = useContext(authContext);
const [categories, setCategories] = useState<SpotifyApi.CategoryObject[]>([]);
const handleSpotifyError = useSpotifyApiError(spotifyApi);
useEffect(() => {
if (categories.length === 0) {
const {
data: categories,
isError,
isRefetchError,
refetch,
} = useSpotifyQuery<SpotifyApi.CategoryObject[]>(
QueryCacheKeys.categories,
(spotifyApi) =>
spotifyApi
.getCategories({ country: "US" })
.then((categoriesReceived) => setCategories(categoriesReceived.body.categories.items))
.catch((error) => {
showError(error, "[Spotify genre loading failed]: ");
handleSpotifyError(error);
});
}
}, [access_token]);
.then((categoriesReceived) => categoriesReceived.body.categories.items),
{ initialData: [] }
);
return (
<ScrollArea style={`flex-grow: 1; border: none;`}>
<BoxView direction={Direction.TopToBottom}>
{categories.map((category, index) => {
return <CategoryCard key={index+category.id} id={category.id} name={category.name} />;
<View style={`flex-direction: 'column'; justify-content: 'center'; flex: 1;`}>
{(isError || isRefetchError) && (
<ErrorApplet message="Failed to query genres" reload={refetch} helps />
)}
{categories?.map((category, index) => {
return (
<CategoryCard
key={index + category.id}
id={category.id}
name={category.name}
/>
);
})}
</BoxView>
</View>
</ScrollArea>
);
}
@ -46,40 +51,52 @@ interface CategoryCardProps {
const CategoryCard = ({ id, name }: CategoryCardProps) => {
const history = useHistory();
const [playlists, setPlaylists] = useState<SpotifyApi.PlaylistObjectSimplified[]>([]);
const spotifyApi = useSpotifyApi();
const handleSpotifyError = useSpotifyApiError(spotifyApi);
useEffect(() => {
if (playlists.length === 0) {
const { data: playlists, isError } = useSpotifyQuery<
SpotifyApi.PlaylistObjectSimplified[]
>(
[QueryCacheKeys.categoryPlaylists, id],
(spotifyApi) =>
spotifyApi
.getPlaylistsForCategory(id, { limit: 4 })
.then((playlistsRes) => setPlaylists(playlistsRes.body.playlists.items))
.catch((error) => {
showError(error, `[Failed to get playlists of category ${name}]: `);
handleSpotifyError(error);
});
}
}, []);
.then((playlistsRes) => playlistsRes.body.playlists.items),
{ initialData: [] }
);
function goToGenre() {
history.push(`/genre/playlists/${id}`, { name });
}
if (isError) {
return <></ >;
}
return (
<BoxView id="container" styleSheet={categoryStylesheet} direction={Direction.TopToBottom}>
<Button id="anchor-heading" cursor={CursorShape.PointingHandCursor} on={{ MouseButtonRelease: goToGenre }} text={name} />
<BoxView direction={Direction.LeftToRight}>
{playlists.map((playlist, index) => {
return <PlaylistCard key={index+playlist.id} id={playlist.id} name={playlist.name} thumbnail={playlist.images[0].url} />;
<View id="container" styleSheet={categoryStylesheet}>
<Button
id="anchor-heading"
cursor={CursorShape.PointingHandCursor}
on={{ MouseButtonRelease: goToGenre }}
text={name}
/>
<View id="child-view">
{playlists?.map((playlist, index) => {
return (
<PlaylistCard
key={index + playlist.id}
id={playlist.id}
name={playlist.name}
thumbnail={playlist.images[0].url}
/>
);
})}
</BoxView>
</BoxView>
</View>
</View>
);
};
const categoryStylesheet = `
#container{
flex: 1;
flex-direction: column;
justify-content: 'center';
margin-bottom: 20px;
}
#anchor-heading{
@ -89,7 +106,12 @@ const categoryStylesheet = `
outline: none;
font-size: 20px;
font-weight: bold;
text-align: left;
align-self: flex-start;
}
#child-view{
flex: 1;
justify-content: 'space-around';
align-items: 'center';
}
#anchor-heading:hover{
border: none;
@ -104,7 +126,8 @@ interface PlaylistCardProps {
id: string;
}
export const PlaylistCard = React.memo(({ id, name, thumbnail }: PlaylistCardProps) => {
export const PlaylistCard = React.memo(
({ id, name, thumbnail }: PlaylistCardProps) => {
const history = useHistory();
function gotoPlaylist() {
@ -113,9 +136,9 @@ export const PlaylistCard = React.memo(({ id, name, thumbnail }: PlaylistCardPro
const playlistStyleSheet = `
#playlist-container{
max-width: 150px;
max-height: 150px;
min-height: 150px;
max-width: 250px;
flex-direction: column;
padding: 2px;
}
#playlist-container:hover{
border: 1px solid green;
@ -126,8 +149,19 @@ export const PlaylistCard = React.memo(({ id, name, thumbnail }: PlaylistCardPro
`;
return (
<BoxView size={{height: 150, width: 150, fixed: true}} direction={Direction.TopToBottom} id="playlist-container" cursor={CursorShape.PointingHandCursor} styleSheet={playlistStyleSheet} on={{ MouseButtonRelease: gotoPlaylist }}>
<CachedImage src={thumbnail} maxSize={{ height: 150, width: 150 }} scaledContents alt={name} />
</BoxView>
<View
id="playlist-container"
cursor={CursorShape.PointingHandCursor}
styleSheet={playlistStyleSheet}
on={{ MouseButtonRelease: gotoPlaylist }}
>
<CachedImage
src={thumbnail}
maxSize={{ height: 150, width: 150 }}
scaledContents
alt={name}
/>
</View>
);
}
);
});

View File

@ -1,32 +1,21 @@
import { ScrollArea, Text, View } from "@nodegui/react-nodegui";
import React, { useContext, useEffect, useState } from "react";
import { Direction } from "@nodegui/nodegui";
import { BoxView, ScrollArea, Text, View, GridView, GridColumn, GridRow } from "@nodegui/react-nodegui";
import React from "react";
import { useLocation, useParams } from "react-router";
import authContext from "../context/authContext";
import showError from "../helpers/showError";
import useSpotifyApi from "../hooks/useSpotifyApi";
import useSpotifyApiError from "../hooks/useSpotifyApiError";
import { QueryCacheKeys } from "../conf";
import useSpotifyQuery from "../hooks/useSpotifyQuery";
import BackButton from "./BackButton";
import { PlaylistCard } from "./Home";
function PlaylistGenreView() {
const { id } = useParams<{ id: string }>();
const location = useLocation<{ name: string }>();
const [playlists, setPlaylists] = useState<SpotifyApi.PlaylistObjectSimplified[]>([]);
const { access_token, isLoggedIn } = useContext(authContext);
const spotifyApi = useSpotifyApi();
const handleSpotifyError = useSpotifyApiError(spotifyApi);
useEffect(() => {
if (playlists.length === 0 && access_token) {
spotifyApi
.getPlaylistsForCategory(id)
.then((playlistsRes) => setPlaylists(playlistsRes.body.playlists.items))
.catch((error) => {
showError(error, `[Failed to get playlists of category ${location.state.name} for]: `);
handleSpotifyError(error);
});
}
}, [access_token]);
const { data: playlists } = useSpotifyQuery<SpotifyApi.PlaylistObjectSimplified[]>(
[QueryCacheKeys.genrePlaylists, id],
(spotifyApi) => spotifyApi.getPlaylistsForCategory(id)
.then((playlistsRes) => playlistsRes.body.playlists.items),
{ initialData: [] }
)
const playlistGenreViewStylesheet = `
#genre-container{
@ -56,9 +45,15 @@ function PlaylistGenreView() {
<Text id="heading">{`<h2>${location.state.name}</h2>`}</Text>
<ScrollArea id="scroll-view">
<View id="child-container">
{isLoggedIn &&
playlists.map((playlist, index) => {
return <PlaylistCard key={((index * Date.now()) / Math.random()) * 100} id={playlist.id} name={playlist.name} thumbnail={playlist.images[0].url} />;
{playlists?.map((playlist, index) => {
return (
<PlaylistCard
key={index + playlist.id}
id={playlist.id}
name={playlist.name}
thumbnail={playlist.images[0].url}
/>
);
})}
</View>
</ScrollArea>

View File

@ -1,5 +1,5 @@
import React, { FC, useContext } from "react";
import { BoxView, Button, ScrollArea, Text } from "@nodegui/react-nodegui";
import { BoxView, View, Button, ScrollArea, Text } from "@nodegui/react-nodegui";
import BackButton from "./BackButton";
import { useLocation, useParams } from "react-router";
import { Direction, QAbstractButtonSignals, QIcon } from "@nodegui/nodegui";
@ -44,15 +44,15 @@ const PlaylistView: FC = () => {
};
return (
<BoxView direction={Direction.TopToBottom}>
<BoxView style={`max-width: 150px;`}>
<View style={`flex: 1; flex-direction: 'column'; flex-grow: 1;`}>
<View style={`justify-content: 'space-evenly'; max-width: 150px; padding: 10px;`}>
<BackButton />
<IconButton icon={new QIcon(heartRegular)} />
<IconButton style={`background-color: #00be5f; color: white;`} on={{ clicked: handlePlaylistPlayPause }} icon={new QIcon(currentPlaylist?.id === params.id ? stop : play)} />
</BoxView>
</View>
<Text>{`<center><h2>${location.state.name[0].toUpperCase()}${location.state.name.slice(1)}</h2></center>`}</Text>
<ScrollArea style={`flex-grow: 1; border: none;`}>
<BoxView /* style={`flex-direction:column;`} */ direction={Direction.TopToBottom}>
<ScrollArea style={`flx:1; flex-grow: 1; border: none;`}>
<View style={`flex-direction:column; flex: 1;`}>
{isLoading && <Text>{`Loading Tracks...`}</Text>}
{isError && (
<>
@ -78,9 +78,9 @@ const PlaylistView: FC = () => {
/>
);
})}
</BoxView>
</View>
</ScrollArea>
</BoxView>
</View>
);
};

View File

@ -0,0 +1,47 @@
import React from "react";
import {Route} from "react-router"
import {View, Button} from "@nodegui/react-nodegui"
import {QIcon} from "@nodegui/nodegui"
function TabMenu(){
return (
<View id="tabmenu" styleSheet={tabBarStylesheet}>
<TabMenuItem title="Browse"/>
<TabMenuItem title="Library"/>
<TabMenuItem title="Currently Playing"/>
</View>
)
}
const tabBarStylesheet = `
#tabmenu{
flex-direction: 'column';
align-items: 'center';
max-width: 225px;
}
#tabmenu-item{
background-color: transparent;
}
#tabmenu-item:hover{
color: green;
}
#tabmenu-item:active{
color: #59ff88;
}
`
export default TabMenu;
interface TabMenuItemProps{
title: string;
/**
* path to the icon in string
*/
icon?: string;
}
export function TabMenuItem({icon, title}:TabMenuItemProps){
return (
<Button id="tabmenu-item" text={title}/>
)
}

View File

@ -0,0 +1,24 @@
import { View, Button, Text } from "@nodegui/react-nodegui";
import React from "react"
interface ErrorAppletProps {
message?: string;
reload: Function;
helps?: boolean;
}
function ErrorApplet({ message, reload, helps }: ErrorAppletProps) {
return (
<View style="flex-direction: 'column'; align-items: 'center';">
<Text openExternalLinks>{`
<h3>${message ? message : 'An error occured'}</h3>
${helps ? `<p>Check if you're connected to internet & then try again. If the issue still persists ask for help or create a <a href="https://github.com/krtirtho/spotube/issues">issue</a>
</p>`: ``
}
`}</Text>
<Button on={{ clicked() { reload() } }} text="Reload" />
</View>
)
}
export default ErrorApplet;

View File

@ -9,5 +9,6 @@ export const redirectURI = "http://localhost:4304/auth/spotify/callback"
export enum QueryCacheKeys{
categories="categories",
categoryPlaylists = "categoryPlaylists",
playlistTracks="playlistTracks"
genrePlaylists="genrePlaylists",
playlistTracks="playlistTracks",
}

View File

@ -1,29 +0,0 @@
import { DependencyList, useContext, useEffect } from "react";
import authContext from "../context/authContext";
import { CredentialKeys } from "../app";
import SpotifyWebApi from "spotify-web-api-node";
interface UseAccessTokenResult {
access_token: string;
}
export default (spotifyApi: SpotifyWebApi, deps: DependencyList = []): UseAccessTokenResult => {
const { access_token, expires_in, isLoggedIn, setExpires_in, setAccess_token } = useContext(authContext);
const refreshToken = localStorage.getItem(CredentialKeys.refresh_token);
useEffect(() => {
const isExpiredToken = Date.now() > expires_in;
if (isLoggedIn && isExpiredToken && refreshToken) {
spotifyApi.setRefreshToken(refreshToken);
spotifyApi
.refreshAccessToken()
.then(({ body: { access_token, expires_in } }) => {
setAccess_token(access_token);
setExpires_in(expires_in);
})
.catch();
}
}, deps);
return { access_token };
};

View File

@ -2,19 +2,38 @@ import chalk from "chalk";
import { useContext, useEffect } from "react";
import { CredentialKeys } from "../app";
import authContext from "../context/authContext";
import showError from "../helpers/showError";
import spotifyApi from "../initializations/spotifyApi";
function useSpotifyApi() {
const { access_token, clientId, clientSecret, isLoggedIn } = useContext(authContext);
const {
access_token,
clientId,
clientSecret,
isLoggedIn,
setAccess_token,
} = useContext(authContext);
const refreshToken = localStorage.getItem(CredentialKeys.refresh_token);
useEffect(() => {
if (isLoggedIn && clientId && clientSecret && refreshToken) {
console.log(chalk.bgCyan.black("Setting up spotify credentials"))
console.log(chalk.bgCyan.black("Setting up spotify credentials"));
spotifyApi.setClientId(clientId);
spotifyApi.setClientSecret(clientSecret);
spotifyApi.setRefreshToken(refreshToken);
if (!access_token) {
spotifyApi
.refreshAccessToken()
.then((token) => {
console.log(chalk.bgRedBright.yellow("Refreshing access token from useSpotifyApi"));
setAccess_token(token.body.access_token);
})
.catch((error) => {
showError(error);
});
}
spotifyApi.setAccessToken(access_token);
console.log(chalk.bgCyan.green("Finished setting up credentials"));
}
}, [access_token, clientId, clientSecret, isLoggedIn]);

View File

@ -1,5 +1,5 @@
import { useEffect } from "react";
import { QueryFunction, QueryKey, useQuery, UseQueryOptions, UseQueryResult } from "react-query";
import { QueryKey, useQuery, UseQueryOptions, UseQueryResult } from "react-query";
import SpotifyWebApi from "spotify-web-api-node";
import useSpotifyApi from "./useSpotifyApi";
import useSpotifyApiError from "./useSpotifyApiError";

View File

@ -1,10 +1,12 @@
import React, { useContext } from "react";
import {View} from "@nodegui/react-nodegui";
import { Route } from "react-router";
import authContext from "./context/authContext";
import Home from "./components/Home";
import Login from "./components/Login";
import PlaylistView from "./components/PlaylistView";
import PlaylistGenreView from "./components/PlaylistGenreView";
import TabMenu from "./components/TabMenu";
function Routes() {
const {
@ -12,11 +14,18 @@ function Routes() {
} = useContext(authContext);
return (
<>
<Route exact path="/">
{isLoggedIn ? <Home /> : <Login />}
</Route>
<Route path="/">
{ isLoggedIn ?
<View style="background-color: black; flex: 1; flex-direction: 'column';">
<TabMenu />
<Route exact path="/"><Home/></Route>
<Route exact path="/playlist/:id"><PlaylistView /></Route>
<Route exact path="/genre/playlists/:id"><PlaylistGenreView /></Route>
</View>
: <Login/>
}
</Route>
</>
);
}