Improve frontend auth startup handling
This commit is contained in:
@@ -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">
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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})
|
||||||
|
|||||||
Reference in New Issue
Block a user