diff --git a/src/frontend/src/app/app.component.ts b/src/frontend/src/app/app.component.ts index 2eae499..159cd72 100644 --- a/src/frontend/src/app/app.component.ts +++ b/src/frontend/src/app/app.component.ts @@ -53,6 +53,7 @@ export interface SpootyWorkspaceTabsState { const WORKSPACE_STORAGE_KEY = 'jarri_spooty_workspace_state_v1'; const WORKSPACE_TABS_STORAGE_KEY = 'jarri_spooty_workspace_tabs_v1'; const ARCHIVE_DESTINATION_KEY = 'jarri_spooty_archive_destination_v1'; +const AUTH_TOKEN_STORAGE_KEY = 'spooty_auth_token'; const GRID_SIZE = 12; const MIN_PANEL_WIDTH = 260; const MIN_PANEL_HEIGHT = 160; @@ -176,9 +177,26 @@ export function defaultWorkspaceTabsState(): SpootyWorkspaceTabsState { }; } +function getStorageItem(key: string): string | null { + try { + return localStorage.getItem(key); + } catch (error) { + console.error(`Failed to read localStorage key "${key}"`, error); + return null; + } +} + +function setStorageItem(key: string, value: string): void { + try { + localStorage.setItem(key, value); + } catch (error) { + console.error(`Failed to write localStorage key "${key}"`, error); + } +} + export function loadWorkspaceState(): SpootyWorkspaceState { try { - const raw = localStorage.getItem(WORKSPACE_STORAGE_KEY); + const raw = getStorageItem(WORKSPACE_STORAGE_KEY); if (!raw) { return defaultWorkspaceState(); @@ -204,7 +222,7 @@ export function loadWorkspaceState(): SpootyWorkspaceState { export function loadWorkspaceTabsState(): SpootyWorkspaceTabsState { try { - const raw = localStorage.getItem(WORKSPACE_TABS_STORAGE_KEY); + const raw = getStorageItem(WORKSPACE_TABS_STORAGE_KEY); if (raw) { const parsed = JSON.parse(raw) as SpootyWorkspaceTabsState; @@ -318,8 +336,8 @@ 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) || ''; + authTokenPresent = Boolean(getStorageItem(AUTH_TOKEN_STORAGE_KEY)); + archiveDestination = getStorageItem(ARCHIVE_DESTINATION_KEY) || ''; archiveListing?: ArchiveListing; archiveLoading = false; archiveError = ''; @@ -370,7 +388,7 @@ export class AppComponent implements OnDestroy { return; } - localStorage.setItem('spooty_auth_token', token); + setStorageItem(AUTH_TOKEN_STORAGE_KEY, token); this.authTokenPresent = true; url.searchParams.delete('token'); window.history.replaceState({}, document.title, url.toString()); @@ -411,7 +429,7 @@ export class AppComponent implements OnDestroy { } saveArchiveDestination(): void { - localStorage.setItem(ARCHIVE_DESTINATION_KEY, this.archiveDestination); + setStorageItem(ARCHIVE_DESTINATION_KEY, this.archiveDestination); } refreshArchive(): void { @@ -769,7 +787,7 @@ export class AppComponent implements OnDestroy { } private saveWorkspaceState(): void { - localStorage.setItem( + setStorageItem( WORKSPACE_TABS_STORAGE_KEY, JSON.stringify(this.workspaceTabsState), ); diff --git a/src/frontend/src/app/services/auth-token.interceptor.ts b/src/frontend/src/app/services/auth-token.interceptor.ts index cd9356f..2d75ed0 100644 --- a/src/frontend/src/app/services/auth-token.interceptor.ts +++ b/src/frontend/src/app/services/auth-token.interceptor.ts @@ -3,7 +3,13 @@ import { HttpInterceptorFn } from '@angular/common/http'; const TOKEN_STORAGE_KEY = 'spooty_auth_token'; export const authTokenInterceptor: HttpInterceptorFn = (req, next) => { - const token = localStorage.getItem(TOKEN_STORAGE_KEY); + let token: string | null = null; + + try { + token = localStorage.getItem(TOKEN_STORAGE_KEY); + } catch (error) { + console.error('Failed to read auth token from localStorage', error); + } if (!token) { return next(req); diff --git a/src/frontend/src/index.html b/src/frontend/src/index.html index 091d567..d824443 100644 --- a/src/frontend/src/index.html +++ b/src/frontend/src/index.html @@ -8,6 +8,21 @@
+