diff --git a/.env.local b/.env.local index 847efe7..d7ce315 100644 --- a/.env.local +++ b/.env.local @@ -1 +1 @@ -NEXT_PUBLIC_COMMIT_SHA=bc159ac +NEXT_PUBLIC_COMMIT_SHA=87a2f06 diff --git a/app/browse/page.tsx b/app/browse/page.tsx index 3f26460..f89f3ee 100644 --- a/app/browse/page.tsx +++ b/app/browse/page.tsx @@ -120,7 +120,7 @@ export default function BrowsePage() { key={artist.id} artist={artist} className="flex-shrink-0" - size={150} + size={190} /> ))} diff --git a/app/components/album-artwork.tsx b/app/components/album-artwork.tsx index 8b3e2d4..494f33d 100644 --- a/app/components/album-artwork.tsx +++ b/app/components/album-artwork.tsx @@ -16,11 +16,16 @@ import { ContextMenuTrigger, } from "../../components/ui/context-menu" -import { Album } from "@/lib/navidrome" import { useNavidrome } from "./NavidromeContext" import Link from "next/link"; import { useAudioPlayer } from "@/app/components/AudioPlayerContext"; import { getNavidromeAPI } from "@/lib/navidrome"; +import React, { useState, useEffect } from 'react'; +import { Button } from "@/components/ui/button"; +import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; +import { ArtistIcon } from "@/app/components/artist-icon"; +import { Heart, Music, Disc, Mic, Play } from "lucide-react"; +import { Album, Artist, Song } from "@/lib/navidrome"; interface AlbumArtworkProps extends React.HTMLAttributes { album: Album @@ -37,10 +42,10 @@ export function AlbumArtwork({ className, ...props }: AlbumArtworkProps) { + const { api, isConnected } = useNavidrome(); const router = useRouter(); - const { addAlbumToQueue } = useAudioPlayer(); + const { addAlbumToQueue, playTrack, addToQueue } = useAudioPlayer(); const { playlists, starItem, unstarItem } = useNavidrome(); - const api = getNavidromeAPI(); const handleClick = () => { router.push(`/album/${album.id}`); @@ -57,6 +62,46 @@ export function AlbumArtwork({ starItem(album.id, 'album'); } }; + + const handlePlayAlbum = async (album: Album) => { + if (!api) return; + + try { + const songs = await api.getAlbumSongs(album.id); + if (songs.length > 0) { + const tracks = songs.map((song: Song) => ({ + id: song.id, + name: song.title, + artist: song.artist, + album: song.album, + albumId: song.albumId, + artistId: song.artistId, + url: api.getStreamUrl(song.id), + duration: song.duration, + coverArt: song.coverArt ? api.getCoverArtUrl(song.coverArt) : undefined, + })); + + playTrack(tracks[0]); + tracks.slice(1).forEach((track: any) => addToQueue(track)); + } + } catch (error) { + console.error('Failed to play album:', error); + } + }; + + const toggleFavorite = async (id: string, type: 'song' | 'album' | 'artist', isStarred: boolean) => { + if (!api) return; + + try { + if (isStarred) { + await api.unstar(id, type); + } else { + await api.star(id, type); + } + } catch (error) { + console.error('Failed to toggle favorite:', error); + } + }; // Get cover art URL with proper fallback const coverArtUrl = album.coverArt && api ? api.getCoverArtUrl(album.coverArt, 300) @@ -66,7 +111,34 @@ export function AlbumArtwork({
-
+ handleClick()}> +
+ {album.coverArt && api ? ( + {album.name} + ) : ( +
+ +
+ )} +
+ handlePlayAlbum(album)}/> +
+
+ +

{album.name}

+

router.push(album.artistId)}>{album.artist}

+

+ {album.songCount} songs • {Math.floor(album.duration / 60)} min +

+
+
+ {/*
{album.name} -
+
*/}
@@ -122,12 +194,6 @@ export function AlbumArtwork({ Share
-
-

{album.name}

-

- {album.artist} -

-
) } \ No newline at end of file diff --git a/app/components/artist-icon.tsx b/app/components/artist-icon.tsx index 7c766a7..894cf7b 100644 --- a/app/components/artist-icon.tsx +++ b/app/components/artist-icon.tsx @@ -98,11 +98,6 @@ export function ArtistIcon({ className="object-cover w-full h-full" /> -
- -

{artist.name}

diff --git a/app/favorites/page.tsx b/app/favorites/page.tsx index 78cea04..03bef8b 100644 --- a/app/favorites/page.tsx +++ b/app/favorites/page.tsx @@ -282,7 +282,13 @@ const FavoritesPage = () => {
- + {artist.name}

{artist.name}