From d40fc733a472a3e27bb70b532d8dbfd7e4c97b13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20R=C3=A4diker?= Date: Thu, 7 Sep 2023 22:41:25 +0200 Subject: [PATCH] Simplify login and make tracks selectable --- package.json | 2 +- src/Main.tsx | 63 ++++++++++++++++ src/api.tsx | 3 +- src/app/app.tsx | 159 ++++++++++++++++++++++++----------------- src/app/components.tsx | 73 +++++++++++++++---- src/app/util.tsx | 17 +++-- src/home.tsx | 26 +++---- src/index.tsx | 11 +-- 8 files changed, 241 insertions(+), 113 deletions(-) create mode 100644 src/Main.tsx diff --git a/package.json b/package.json index f4b85e8..72607b1 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "type": "module", "scripts": { "dev": "vite", - "build": "vite build && mkdir -p ./dist/app && cp ./dist/index.html ./dist/app/index.html", + "build": "vite build", "preview": "vite preview" }, "dependencies": { diff --git a/src/Main.tsx b/src/Main.tsx new file mode 100644 index 0000000..7de682e --- /dev/null +++ b/src/Main.tsx @@ -0,0 +1,63 @@ +import { IRedirectionStrategy, SpotifyApi } from "@spotify/web-api-ts-sdk" +import { useEffect, useState } from "preact/hooks" +import { createApiClient } from "./api" +import App from "./app/app" +import Home from "./home" + +export default function Main() { + const [spotify, setSpotify] = useState(null) + const [authError, setAuthError] = useState(null) + + useEffect(() => { + // check if user is already authenticated + ;(async () => { + try { + // do not redirect here, since this means user is not authenticated, do nothing instead + class NoRedirectionStrategy implements IRedirectionStrategy { + public async redirect(_targetUrl: string | URL): Promise { + return + } + public async onReturnFromRedirect(): Promise {} + } + const sdk = createApiClient(new NoRedirectionStrategy()) + const { authenticated } = await sdk.authenticate() + if (authenticated && !spotify) { + setSpotify(sdk) + } + } catch (e) { + console.info("User is not authenticated", e) + } + })() + }, []) + + if (spotify) { + return ( + { + spotify.logOut() + setSpotify(null) + }} + spotify={spotify} + /> + ) + } + + return ( + { + try { + const sdk = createApiClient() + const { authenticated } = await sdk.authenticate() + if (authenticated) { + // this should never be reached since authenticate redirects + setSpotify(sdk) + } + } catch (e: Error | unknown) { + console.error(e) + setAuthError(e.toString() || "") + } + }} + /> + ) +} diff --git a/src/api.tsx b/src/api.tsx index 349c496..caf1753 100644 --- a/src/api.tsx +++ b/src/api.tsx @@ -23,7 +23,7 @@ export const createApiClient = ( import.meta.env.VITE_SPOTIFY_CLIENT_ID, import.meta.env.PROD ? import.meta.env.VITE_SPOTIFY_REDIRECT_URI - : "http://localhost:3000/app", + : "http://localhost:3000", Scopes.playlistRead, config, ) @@ -35,7 +35,6 @@ async function* getPaginatedItems( ): AsyncGenerator<{ total: number; item: T }> { let resp = await firstResponse const items = resp.items - let counter = 1 for (let item of items) { yield Promise.resolve({ total: resp.total, item }) } diff --git a/src/app/app.tsx b/src/app/app.tsx index 1768973..018b2b0 100644 --- a/src/app/app.tsx +++ b/src/app/app.tsx @@ -1,11 +1,6 @@ import { SpotifyApi } from "@spotify/web-api-ts-sdk" -import { route } from "preact-router" import { useEffect, useState } from "preact/hooks" -import { - IRedirectionStrategy, - User, -} from "../../node_modules/@spotify/web-api-ts-sdk/src/types" -import { createApiClient } from "../api" +import { User } from "../../node_modules/@spotify/web-api-ts-sdk/src/types" import Scaffold from "../scaffold" import { PlaylistsView } from "./components" import { @@ -15,43 +10,26 @@ import { } from "./util" import noScooterCircle from "/img/no_scooter_circle.svg?url" -export default function App(_props: any) { +export default function App({ + onLogout, + spotify, +}: { + onLogout: () => void + spotify: SpotifyApi +}) { const [user, setUser] = useState(null) const [scanProgress, setScanProgress] = useState({ progress: 0, currentPlaylistName: null, }) - const [replaces, setReplaces] = useState<{ - spotify: SpotifyApi - playlists: ScannedPlaylist[] - }>(null) + const [playlists, setPlaylists] = useState(null) useEffect(() => { ;(async () => { - // do not redirect here, since this means user is not authenticated - // route to Home instead - class HomeRedirectionStrategy implements IRedirectionStrategy { - public async redirect(_targetUrl: string | URL): Promise { - route("/") - } - public async onReturnFromRedirect(): Promise {} - } - const spotify = createApiClient(new HomeRedirectionStrategy()) - const accessToken = await spotify.authenticate() - if (accessToken.access_token === "") { - route("/") - } else { - const user = await spotify.currentUser.profile() - setUser(user) - - const playlists = await scanUserPlaylists( - spotify, - user, - setScanProgress, - ) - - setReplaces({ playlists, spotify }) - } + const user = await spotify.currentUser.profile() + setUser(user) + const playlists = await scanUserPlaylists(spotify, user, setScanProgress) + setPlaylists(playlists) })() }, []) @@ -68,37 +46,17 @@ export default function App(_props: any) {
Taylor’s Version
- { - localStorage.removeItem( - "spotify-sdk:AuthorizationCodeWithPKCEStrategy:token", - ) - route("/") - }} - /> +
- {replaces == null ? ( -
-
Scanning your playlists...
-
-
-
-
- {scanProgress.currentPlaylistName || <> } -
-
+ {playlists == null ? ( + ) : ( -
- -
+ setPlaylists(p)} + spotify={spotify} + /> )} ) @@ -106,17 +64,17 @@ export default function App(_props: any) { function LogOutButton({ user, - onLogOut, + onLogout, }: { user: User - onLogOut: () => void + onLogout: () => void }) { const profileImage = user && user.images.reduce((p, c) => (p.width < c.width ? c : p)) return (