diff --git a/src/frontend/src/app/app.component.html b/src/frontend/src/app/app.component.html index fbc5216..02d37c5 100644 --- a/src/frontend/src/app/app.component.html +++ b/src/frontend/src/app/app.component.html @@ -32,6 +32,12 @@ +
+ Auth token required. + Open this app with the token once, for example + ?token=your_token_here, and it will be stored in your browser. +
+
diff --git a/src/frontend/src/app/app.component.scss b/src/frontend/src/app/app.component.scss index 96e55c0..13ef857 100644 --- a/src/frontend/src/app/app.component.scss +++ b/src/frontend/src/app/app.component.scss @@ -83,6 +83,19 @@ h1 { background: rgba(8, 15, 15, 0.9); } +.auth-warning { + margin: 12px 24px 0; + padding: 12px 14px; + border: 1px solid rgba(255, 214, 102, 0.35); + border-radius: 10px; + background: rgba(255, 214, 102, 0.12); + color: #ffe3a3; +} + +.auth-warning code { + color: #f3fff7; +} + .panel-picker { display: flex; gap: 10px; diff --git a/src/frontend/src/app/app.component.ts b/src/frontend/src/app/app.component.ts index e743b48..2eae499 100644 --- a/src/frontend/src/app/app.component.ts +++ b/src/frontend/src/app/app.component.ts @@ -318,6 +318,7 @@ export class AppComponent implements OnDestroy { selectedTrack$ = this.trackService.selectedTrack$; version = this.versionService.getVersion(); spotifyConnected = false; + authTokenPresent = Boolean(localStorage.getItem('spooty_auth_token')); archiveDestination = localStorage.getItem(ARCHIVE_DESTINATION_KEY) || ''; archiveListing?: ArchiveListing; archiveLoading = false; @@ -370,6 +371,7 @@ export class AppComponent implements OnDestroy { } localStorage.setItem('spooty_auth_token', token); + this.authTokenPresent = true; url.searchParams.delete('token'); window.history.replaceState({}, document.title, url.toString()); } @@ -377,7 +379,13 @@ export class AppComponent implements OnDestroy { checkSpotifyStatus(): void { this.http .get<{ connected: boolean }>('/api/spotify/status') - .subscribe((status) => (this.spotifyConnected = status.connected)); + .subscribe({ + next: (status) => (this.spotifyConnected = status.connected), + error: (error) => { + console.error('Failed to check Spotify status', error); + this.spotifyConnected = false; + }, + }); } connectSpotify(): void { diff --git a/src/frontend/src/app/services/playlist.service.ts b/src/frontend/src/app/services/playlist.service.ts index 90863da..703783b 100644 --- a/src/frontend/src/app/services/playlist.service.ts +++ b/src/frontend/src/app/services/playlist.service.ts @@ -11,7 +11,7 @@ import { withUIEntities } from "@ngneat/elf-entities"; import {joinRequestResult, trackRequestResult} from "@ngneat/elf-requests"; -import {combineLatest, filter, first, map, Observable, of, switchMap, tap} from "rxjs"; +import {catchError, combineLatest, filter, first, map, Observable, of, switchMap, tap} from "rxjs"; import {TrackService} from "./track.service"; import {Socket} from "ngx-socket-io"; import {Playlist} from "../models/playlist"; @@ -115,6 +115,14 @@ export class PlaylistService { fetch(): void { this.http.get(ENDPOINT).pipe( + catchError((error) => { + console.error('Failed to fetch playlists', error); + this.store.update( + setEntities([]), + setEntities([], { ref: UIEntitiesRef }), + ); + return of([]); + }), tap((data: Playlist[]) => this.store.update( setEntities(data), setEntities(data.map(item => ({id: item.id, collapsed: false})), {ref: UIEntitiesRef})