fix: load playlist image on frontend

This commit is contained in:
Xoconoch
2025-08-28 08:40:39 -06:00
parent 0b7c9d0da8
commit f800251de1
5 changed files with 66 additions and 6 deletions

View File

@@ -1,7 +1,7 @@
fastapi==0.116.1
uvicorn[standard]==0.35.0
celery==5.5.3
deezspot-spotizerr==3.1.4
deezspot-spotizerr==3.1.5
httpx==0.28.1
bcrypt==4.2.1
PyJWT==2.10.1

View File

@@ -135,6 +135,16 @@ export const Album = () => {
};
}, [loadMore]);
// Auto progressive loading regardless of scroll
useEffect(() => {
if (!album) return;
if (!hasMore || isLoadingMore) return;
const t = setTimeout(() => {
loadMore();
}, 300);
return () => clearTimeout(t);
}, [album, hasMore, isLoadingMore, loadMore]);
const handleDownloadTrack = (track: LibrespotTrackType) => {
if (!track.id) return;
toast.info(`Adding ${track.name} to queue...`);

View File

@@ -303,6 +303,16 @@ export const Artist = () => {
return () => observer.disconnect();
}, [fetchMoreAlbums, hasMore]);
// Auto progressive loading regardless of scroll
useEffect(() => {
if (!artist) return;
if (!hasMore || loading || loadingMore) return;
const t = setTimeout(() => {
fetchMoreAlbums();
}, 350);
return () => clearTimeout(t);
}, [artist, hasMore, loading, loadingMore, fetchMoreAlbums]);
// --- existing handlers (unchanged) ---
const handleDownloadTrack = (track: LibrespotTrackType) => {
if (!track.id) return;

View File

@@ -153,6 +153,16 @@ export const Playlist = () => {
}
}, [playlistMetadata, items.length, totalTracks, loadMoreTracks]);
// Auto progressive loading regardless of scroll
useEffect(() => {
if (!playlistMetadata) return;
if (!hasMoreTracks || loadingTracks) return;
const t = setTimeout(() => {
loadMoreTracks();
}, 300);
return () => clearTimeout(t);
}, [playlistMetadata, hasMoreTracks, loadingTracks, loadMoreTracks]);
const handleDownloadTrack = (track: LibrespotTrackType) => {
if (!track?.id) return;
addItem({ spotifyId: track.id, type: "track", name: track.name });
@@ -227,11 +237,40 @@ export const Playlist = () => {
{/* Playlist Header - Mobile Optimized */}
<div className="bg-surface dark:bg-surface-dark border border-border dark:border-border-dark rounded-xl p-4 md:p-6 shadow-sm">
<div className="flex flex-col items-center gap-4 md:gap-6">
<img
src={playlistMetadata.images?.at(0)?.url || "/placeholder.jpg"}
alt={playlistMetadata.name}
className="w-32 h-32 sm:w-40 sm:h-40 md:w-48 md:h-48 object-cover rounded-lg shadow-lg mx-auto"
/>
{playlistMetadata.picture ? (
<img
src={playlistMetadata.picture}
alt={playlistMetadata.name}
className="w-32 h-32 sm:w-40 sm:h-40 md:w-48 md:h-48 object-cover rounded-lg shadow-lg mx-auto"
/>
) : (
<div
className="w-32 h-32 sm:w-40 sm:h-40 md:w-48 md:h-48 rounded-lg shadow-lg mx-auto overflow-hidden bg-surface-muted dark:bg-surface-muted-dark grid grid-cols-2 grid-rows-2"
>
{(Array.from(
new Map(
filteredItems
.map(({ track }) => (track as any)?.album?.images?.at(-1)?.url)
.filter((u) => !!u)
.map((u) => [u, u] as const)
).values()
) as string[]).slice(0, 4).map((url, i) => (
<img
key={`${url}-${i}`}
src={url}
alt={`Cover ${i + 1}`}
className="w-full h-full object-cover"
/>
))}
{filteredItems.length === 0 && (
<img
src="/placeholder.jpg"
alt={playlistMetadata.name}
className="col-span-2 row-span-2 w-full h-full object-cover"
/>
)}
</div>
)}
<div className="flex-grow space-y-2 text-center">
<h1 className="text-2xl md:text-3xl font-bold text-content-primary dark:text-content-primary-dark leading-tight">{playlistMetadata.name}</h1>
{playlistMetadata.description && (

View File

@@ -142,6 +142,7 @@ export interface LibrespotPlaylistType {
snapshot_id: string;
tracks: LibrespotPlaylistTracksPageType;
type: "playlist";
picture?: string;
}
// Type guards