Improve frontend auth startup handling

This commit is contained in:
Dymas
2026-06-22 10:00:29 +02:00
parent bf09a151a8
commit 09c420ab46
4 changed files with 37 additions and 2 deletions
+6
View File
@@ -32,6 +32,12 @@
</button> </button>
</nav> </nav>
<section *ngIf="!authTokenPresent" class="auth-warning">
<strong>Auth token required.</strong>
Open this app with the token once, for example
<code>?token=your_token_here</code>, and it will be stored in your browser.
</section>
<section class="workspace-controls"> <section class="workspace-controls">
<div class="panel-picker"> <div class="panel-picker">
<div class="select"> <div class="select">
+13
View File
@@ -83,6 +83,19 @@ h1 {
background: rgba(8, 15, 15, 0.9); 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 { .panel-picker {
display: flex; display: flex;
gap: 10px; gap: 10px;
+9 -1
View File
@@ -318,6 +318,7 @@ export class AppComponent implements OnDestroy {
selectedTrack$ = this.trackService.selectedTrack$; selectedTrack$ = this.trackService.selectedTrack$;
version = this.versionService.getVersion(); version = this.versionService.getVersion();
spotifyConnected = false; spotifyConnected = false;
authTokenPresent = Boolean(localStorage.getItem('spooty_auth_token'));
archiveDestination = localStorage.getItem(ARCHIVE_DESTINATION_KEY) || ''; archiveDestination = localStorage.getItem(ARCHIVE_DESTINATION_KEY) || '';
archiveListing?: ArchiveListing; archiveListing?: ArchiveListing;
archiveLoading = false; archiveLoading = false;
@@ -370,6 +371,7 @@ export class AppComponent implements OnDestroy {
} }
localStorage.setItem('spooty_auth_token', token); localStorage.setItem('spooty_auth_token', token);
this.authTokenPresent = true;
url.searchParams.delete('token'); url.searchParams.delete('token');
window.history.replaceState({}, document.title, url.toString()); window.history.replaceState({}, document.title, url.toString());
} }
@@ -377,7 +379,13 @@ export class AppComponent implements OnDestroy {
checkSpotifyStatus(): void { checkSpotifyStatus(): void {
this.http this.http
.get<{ connected: boolean }>('/api/spotify/status') .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 { connectSpotify(): void {
@@ -11,7 +11,7 @@ import {
withUIEntities withUIEntities
} from "@ngneat/elf-entities"; } from "@ngneat/elf-entities";
import {joinRequestResult, trackRequestResult} from "@ngneat/elf-requests"; 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 {TrackService} from "./track.service";
import {Socket} from "ngx-socket-io"; import {Socket} from "ngx-socket-io";
import {Playlist} from "../models/playlist"; import {Playlist} from "../models/playlist";
@@ -115,6 +115,14 @@ export class PlaylistService {
fetch(): void { fetch(): void {
this.http.get<Playlist[]>(ENDPOINT).pipe( this.http.get<Playlist[]>(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( tap((data: Playlist[]) => this.store.update(
setEntities(data), setEntities(data),
setEntities(data.map(item => ({id: item.id, collapsed: false})), {ref: UIEntitiesRef}) setEntities(data.map(item => ({id: item.id, collapsed: false})), {ref: UIEntitiesRef})