Add connection state management to Navidrome context and improve API response handling
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
'use client';
|
'use client';
|
||||||
import React, { createContext, useContext, useEffect, useState, ReactNode } from 'react';
|
import React, { createContext, useContext, useEffect, useState, ReactNode } from 'react';
|
||||||
import { getNavidromeAPI, Album, Artist, Song, Playlist } from '@/lib/navidrome';
|
import { getNavidromeAPI, Album, Artist, Song, Playlist } from '@/lib/navidrome';
|
||||||
|
import { useCallback } from 'react';
|
||||||
|
|
||||||
interface NavidromeContextType {
|
interface NavidromeContextType {
|
||||||
// Data
|
// Data
|
||||||
@@ -14,6 +15,9 @@ interface NavidromeContextType {
|
|||||||
artistsLoading: boolean;
|
artistsLoading: boolean;
|
||||||
playlistsLoading: boolean;
|
playlistsLoading: boolean;
|
||||||
|
|
||||||
|
// Connection state
|
||||||
|
isConnected: boolean;
|
||||||
|
|
||||||
// Error states
|
// Error states
|
||||||
error: string | null;
|
error: string | null;
|
||||||
|
|
||||||
@@ -48,6 +52,7 @@ export const NavidromeProvider: React.FC<NavidromeProviderProps> = ({ children }
|
|||||||
const [playlistsLoading, setPlaylistsLoading] = useState(false);
|
const [playlistsLoading, setPlaylistsLoading] = useState(false);
|
||||||
|
|
||||||
const [error, setError] = useState<string | null>(null);
|
const [error, setError] = useState<string | null>(null);
|
||||||
|
const [isConnected, setIsConnected] = useState(false);
|
||||||
|
|
||||||
const isLoading = albumsLoading || artistsLoading || playlistsLoading;
|
const isLoading = albumsLoading || artistsLoading || playlistsLoading;
|
||||||
|
|
||||||
@@ -234,8 +239,9 @@ export const NavidromeProvider: React.FC<NavidromeProviderProps> = ({ children }
|
|||||||
// Test connection and load initial data
|
// Test connection and load initial data
|
||||||
const initialize = async () => {
|
const initialize = async () => {
|
||||||
try {
|
try {
|
||||||
const isConnected = await api.ping();
|
const connected = await api.ping();
|
||||||
if (isConnected) {
|
setIsConnected(connected);
|
||||||
|
if (connected) {
|
||||||
await refreshData();
|
await refreshData();
|
||||||
} else {
|
} else {
|
||||||
setError('Failed to connect to Navidrome server');
|
setError('Failed to connect to Navidrome server');
|
||||||
@@ -243,6 +249,7 @@ export const NavidromeProvider: React.FC<NavidromeProviderProps> = ({ children }
|
|||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Failed to initialize Navidrome:', err);
|
console.error('Failed to initialize Navidrome:', err);
|
||||||
setError('Failed to initialize Navidrome connection');
|
setError('Failed to initialize Navidrome connection');
|
||||||
|
setIsConnected(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -261,6 +268,9 @@ export const NavidromeProvider: React.FC<NavidromeProviderProps> = ({ children }
|
|||||||
artistsLoading,
|
artistsLoading,
|
||||||
playlistsLoading,
|
playlistsLoading,
|
||||||
|
|
||||||
|
// Connection state
|
||||||
|
isConnected,
|
||||||
|
|
||||||
// Error state
|
// Error state
|
||||||
error,
|
error,
|
||||||
|
|
||||||
|
|||||||
@@ -147,8 +147,9 @@ class NavidromeAPI {
|
|||||||
const response = await this.makeRequest('getArtists');
|
const response = await this.makeRequest('getArtists');
|
||||||
const artists: Artist[] = [];
|
const artists: Artist[] = [];
|
||||||
|
|
||||||
if (response.artists?.index) {
|
const artistsData = response.artists as { index?: Array<{ artist?: Artist[] }> };
|
||||||
for (const index of response.artists.index) {
|
if (artistsData?.index) {
|
||||||
|
for (const index of artistsData.index) {
|
||||||
if (index.artist) {
|
if (index.artist) {
|
||||||
artists.push(...index.artist);
|
artists.push(...index.artist);
|
||||||
}
|
}
|
||||||
@@ -160,9 +161,10 @@ class NavidromeAPI {
|
|||||||
|
|
||||||
async getArtist(artistId: string): Promise<{ artist: Artist; albums: Album[] }> {
|
async getArtist(artistId: string): Promise<{ artist: Artist; albums: Album[] }> {
|
||||||
const response = await this.makeRequest('getArtist', { id: artistId });
|
const response = await this.makeRequest('getArtist', { id: artistId });
|
||||||
|
const artistData = response.artist as Artist & { album?: Album[] };
|
||||||
return {
|
return {
|
||||||
artist: response.artist,
|
artist: artistData,
|
||||||
albums: response.artist.album || []
|
albums: artistData.album || []
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -172,14 +174,16 @@ class NavidromeAPI {
|
|||||||
size,
|
size,
|
||||||
offset
|
offset
|
||||||
});
|
});
|
||||||
return response.albumList2?.album || [];
|
const albumListData = response.albumList2 as { album?: Album[] };
|
||||||
|
return albumListData?.album || [];
|
||||||
}
|
}
|
||||||
|
|
||||||
async getAlbum(albumId: string): Promise<{ album: Album; songs: Song[] }> {
|
async getAlbum(albumId: string): Promise<{ album: Album; songs: Song[] }> {
|
||||||
const response = await this.makeRequest('getAlbum', { id: albumId });
|
const response = await this.makeRequest('getAlbum', { id: albumId });
|
||||||
|
const albumData = response.album as Album & { song?: Song[] };
|
||||||
return {
|
return {
|
||||||
album: response.album,
|
album: albumData,
|
||||||
songs: response.album.song || []
|
songs: albumData.song || []
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -195,23 +199,31 @@ class NavidromeAPI {
|
|||||||
songCount
|
songCount
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const searchData = response.searchResult3 as {
|
||||||
|
artist?: Artist[];
|
||||||
|
album?: Album[];
|
||||||
|
song?: Song[];
|
||||||
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
artists: response.searchResult3?.artist || [],
|
artists: searchData?.artist || [],
|
||||||
albums: response.searchResult3?.album || [],
|
albums: searchData?.album || [],
|
||||||
songs: response.searchResult3?.song || []
|
songs: searchData?.song || []
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async getPlaylists(): Promise<Playlist[]> {
|
async getPlaylists(): Promise<Playlist[]> {
|
||||||
const response = await this.makeRequest('getPlaylists');
|
const response = await this.makeRequest('getPlaylists');
|
||||||
return response.playlists?.playlist || [];
|
const playlistsData = response.playlists as { playlist?: Playlist[] };
|
||||||
|
return playlistsData?.playlist || [];
|
||||||
}
|
}
|
||||||
|
|
||||||
async getPlaylist(playlistId: string): Promise<{ playlist: Playlist; songs: Song[] }> {
|
async getPlaylist(playlistId: string): Promise<{ playlist: Playlist; songs: Song[] }> {
|
||||||
const response = await this.makeRequest('getPlaylist', { id: playlistId });
|
const response = await this.makeRequest('getPlaylist', { id: playlistId });
|
||||||
|
const playlistData = response.playlist as Playlist & { entry?: Song[] };
|
||||||
return {
|
return {
|
||||||
playlist: response.playlist,
|
playlist: playlistData,
|
||||||
songs: response.playlist.entry || []
|
songs: playlistData.entry || []
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -311,7 +323,8 @@ class NavidromeAPI {
|
|||||||
albumCount: 0
|
albumCount: 0
|
||||||
});
|
});
|
||||||
|
|
||||||
return response.searchResult3?.song || [];
|
const searchData = response.searchResult3 as { song?: Song[] };
|
||||||
|
return searchData?.song || [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user