Add release date display to AlbumCard overlay
- Add releaseDate prop to AlbumCard component
- Display release date below genre in overlay (format: "Jan 25, 2026")
- Update all AlbumCard usages across views to pass releaseDate:
- ArtistDetailView (all album sections)
- HomeView (all featured album sections)
- SearchView (search results)
- FavoritesView (favorite albums)
- LabelView (label albums)
- AlbumDetailView ("By the same artist" section)
- Add releaseDate to types and adapters
- Skip local library view (VirtualizedAlbumList)
This commit is contained in:
1 parent
e9e319aa46
commit
e9c7e4672c
10 files changed
+73
-6
No files matched your search
@@ -260,6 +260,7 @@ function toArtistAlbumSummary(album: QobuzAlbum): ArtistAlbumSummary {
|
||||
title: album.title,
|
||||
artwork,
|
||||
year: album.release_date_original?.split('-')[0],
|
||||
releaseDate: album.release_date_original,
|
||||
quality,
|
||||
genre: album.genre?.name || "Unknown genre"
|
||||
};
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
title: string;
|
||||
artist: string;
|
||||
genre: string;
|
||||
releaseDate?: string;
|
||||
quality?: string;
|
||||
size?: 'standard' | 'large';
|
||||
searchId?: string;
|
||||
@@ -40,6 +41,7 @@
|
||||
title,
|
||||
artist,
|
||||
genre,
|
||||
releaseDate,
|
||||
quality,
|
||||
size = 'standard',
|
||||
searchId,
|
||||
@@ -90,6 +92,19 @@
|
||||
imageError = true;
|
||||
}
|
||||
|
||||
function formatReleaseDate(dateStr: string | undefined): string {
|
||||
if (!dateStr) return '';
|
||||
const date = new Date(dateStr);
|
||||
if (isNaN(date.getTime())) return '';
|
||||
return date.toLocaleDateString('en-US', {
|
||||
month: 'short',
|
||||
day: 'numeric',
|
||||
year: 'numeric'
|
||||
});
|
||||
}
|
||||
|
||||
const formattedDate = $derived(formatReleaseDate(releaseDate));
|
||||
|
||||
async function handleToggleFavorite(event: MouseEvent) {
|
||||
event.stopPropagation();
|
||||
if (!albumId || !favoriteAvailable) return;
|
||||
@@ -184,7 +199,12 @@
|
||||
<!-- Action Overlay -->
|
||||
{#if hasOverlay}
|
||||
<div class="action-overlay" class:menu-open={menuOpen}>
|
||||
<div class="overlay-genre">{genre}</div>
|
||||
<div class="overlay-info">
|
||||
<span class="overlay-genre">{genre}</span>
|
||||
{#if formattedDate}
|
||||
<span class="overlay-date">{formattedDate}</span>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
{#if showFavoriteButton}
|
||||
<button
|
||||
@@ -393,15 +413,30 @@
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
.overlay-genre {
|
||||
.overlay-info {
|
||||
align-self: flex-start;
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
padding: 14px 14px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.overlay-genre {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: white;
|
||||
text-shadow: 0 1px 3px rgba(0, 0, 0, 0.8);
|
||||
word-wrap: break-word;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
|
||||
.overlay-date {
|
||||
font-size: 12px;
|
||||
font-weight: 400;
|
||||
color: rgba(255, 255, 255, 0.85);
|
||||
text-shadow: 0 1px 3px rgba(0, 0, 0, 0.8);
|
||||
}
|
||||
|
||||
:global(.album-card .album-menu) {
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
artwork: string;
|
||||
quality: string;
|
||||
genre: string;
|
||||
releaseDate?: string;
|
||||
}
|
||||
|
||||
interface Props {
|
||||
@@ -485,6 +486,7 @@
|
||||
title={relatedAlbum.title}
|
||||
artist={album.artist}
|
||||
genre={relatedAlbum.genre}
|
||||
releaseDate={relatedAlbum.releaseDate}
|
||||
size="large"
|
||||
quality={relatedAlbum.quality}
|
||||
onclick={() => onRelatedAlbumClick?.(relatedAlbum.id)}
|
||||
|
||||
@@ -1519,6 +1519,7 @@
|
||||
title={album.title}
|
||||
artist={album.year || ''}
|
||||
genre={album.genre}
|
||||
releaseDate={album.releaseDate}
|
||||
size="large"
|
||||
quality={album.quality}
|
||||
searchId={`album-${album.id}`}
|
||||
@@ -1581,6 +1582,7 @@
|
||||
title={album.title}
|
||||
artist={album.year || ''}
|
||||
genre={album.genre}
|
||||
releaseDate={album.releaseDate}
|
||||
size="large"
|
||||
quality={album.quality}
|
||||
searchId={`album-${album.id}`}
|
||||
@@ -1642,6 +1644,7 @@
|
||||
title={album.title}
|
||||
artist={album.year || ''}
|
||||
genre={album.genre}
|
||||
releaseDate={album.releaseDate}
|
||||
size="large"
|
||||
quality={album.quality}
|
||||
searchId={`album-${album.id}`}
|
||||
@@ -1703,6 +1706,7 @@
|
||||
title={album.title}
|
||||
artist={album.year || ''}
|
||||
genre={album.genre}
|
||||
releaseDate={album.releaseDate}
|
||||
size="large"
|
||||
quality={album.quality}
|
||||
searchId={`album-${album.id}`}
|
||||
@@ -1764,6 +1768,7 @@
|
||||
title={album.title}
|
||||
artist={album.year || ''}
|
||||
genre={album.genre}
|
||||
releaseDate={album.releaseDate}
|
||||
size="large"
|
||||
quality={album.quality}
|
||||
searchId={`album-${album.id}`}
|
||||
@@ -1888,6 +1893,7 @@
|
||||
title={album.title}
|
||||
artist={album.year || ''}
|
||||
genre={album.genre}
|
||||
releaseDate={album.releaseDate}
|
||||
size="large"
|
||||
quality={album.quality}
|
||||
searchId={`album-${album.id}`}
|
||||
|
||||
@@ -1301,6 +1301,7 @@
|
||||
title={album.title}
|
||||
artist={album.artist.name}
|
||||
genre={getGenreLabel(album)}
|
||||
releaseDate={album.release_date_original}
|
||||
size="large"
|
||||
quality={getQualityLabel(album)}
|
||||
onPlay={onAlbumPlay ? () => onAlbumPlay(album.id) : undefined}
|
||||
@@ -1374,6 +1375,7 @@
|
||||
title={album.title}
|
||||
artist={album.artist.name}
|
||||
genre={getGenreLabel(album)}
|
||||
releaseDate={album.release_date_original}
|
||||
size="large"
|
||||
quality={getQualityLabel(album)}
|
||||
onPlay={onAlbumPlay ? () => onAlbumPlay(album.id) : undefined}
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
artist: string;
|
||||
genre: string;
|
||||
quality?: string;
|
||||
releaseDate?: string;
|
||||
}
|
||||
|
||||
interface ArtistCardData {
|
||||
@@ -334,7 +335,8 @@
|
||||
title: album.title,
|
||||
artist: album.artist?.name || 'Unknown Artist',
|
||||
genre: album.genre?.name || 'Unknown genre',
|
||||
quality: formatQuality(album.hires_streamable, album.maximum_bit_depth, album.maximum_sampling_rate)
|
||||
quality: formatQuality(album.hires_streamable, album.maximum_bit_depth, album.maximum_sampling_rate),
|
||||
releaseDate: album.release_date_original
|
||||
};
|
||||
}
|
||||
|
||||
@@ -647,6 +649,7 @@
|
||||
title={album.title}
|
||||
artist={album.artist}
|
||||
genre={album.genre}
|
||||
releaseDate={album.releaseDate}
|
||||
size="large"
|
||||
quality={album.quality}
|
||||
onPlay={onAlbumPlay ? () => onAlbumPlay(album.id) : undefined}
|
||||
@@ -678,6 +681,7 @@
|
||||
title={album.title}
|
||||
artist={album.artist}
|
||||
genre={album.genre}
|
||||
releaseDate={album.releaseDate}
|
||||
size="large"
|
||||
quality={album.quality}
|
||||
onPlay={onAlbumPlay ? () => onAlbumPlay(album.id) : undefined}
|
||||
@@ -709,6 +713,7 @@
|
||||
title={album.title}
|
||||
artist={album.artist}
|
||||
genre={album.genre}
|
||||
releaseDate={album.releaseDate}
|
||||
size="large"
|
||||
quality={album.quality}
|
||||
onPlay={onAlbumPlay ? () => onAlbumPlay(album.id) : undefined}
|
||||
@@ -740,6 +745,7 @@
|
||||
title={album.title}
|
||||
artist={album.artist}
|
||||
genre={album.genre}
|
||||
releaseDate={album.releaseDate}
|
||||
size="large"
|
||||
quality={album.quality}
|
||||
onPlay={onAlbumPlay ? () => onAlbumPlay(album.id) : undefined}
|
||||
@@ -771,6 +777,7 @@
|
||||
title={album.title}
|
||||
artist={album.artist}
|
||||
genre={album.genre}
|
||||
releaseDate={album.releaseDate}
|
||||
size="large"
|
||||
quality={album.quality}
|
||||
onPlay={onAlbumPlay ? () => onAlbumPlay(album.id) : undefined}
|
||||
@@ -802,6 +809,7 @@
|
||||
title={album.title}
|
||||
artist={album.artist}
|
||||
genre={album.genre}
|
||||
releaseDate={album.releaseDate}
|
||||
size="large"
|
||||
quality={album.quality}
|
||||
onPlay={onAlbumPlay ? () => onAlbumPlay(album.id) : undefined}
|
||||
@@ -904,6 +912,7 @@
|
||||
title={album.title}
|
||||
artist={album.artist}
|
||||
genre={album.genre}
|
||||
releaseDate={album.releaseDate}
|
||||
size="large"
|
||||
quality={album.quality}
|
||||
onPlay={onAlbumPlay ? () => onAlbumPlay(album.id) : undefined}
|
||||
|
||||
@@ -278,6 +278,7 @@
|
||||
title={album.title}
|
||||
artist={album.artist?.name || 'Unknown Artist'}
|
||||
genre={getGenreLabel(album)}
|
||||
releaseDate={album.release_date_original}
|
||||
quality={getQualityLabel(album)}
|
||||
size="large"
|
||||
onclick={() => onAlbumClick?.(album.id)}
|
||||
|
||||
@@ -726,6 +726,7 @@
|
||||
title={allResults.albums.items[0].title}
|
||||
artist={allResults.albums.items[0].artist?.name || 'Unknown Artist'}
|
||||
genre={getGenreLabel(allResults.albums.items[0])}
|
||||
releaseDate={allResults.albums.items[0].release_date_original}
|
||||
size="large"
|
||||
quality={getQualityLabel(allResults.albums.items[0])}
|
||||
onPlay={onAlbumPlay ? () => onAlbumPlay(allResults.albums.items[0].id) : undefined}
|
||||
@@ -863,6 +864,7 @@
|
||||
title={album.title}
|
||||
artist={album.artist?.name || 'Unknown Artist'}
|
||||
genre={getGenreLabel(album)}
|
||||
releaseDate={album.release_date_original}
|
||||
size="large"
|
||||
quality={getQualityLabel(album)}
|
||||
onPlay={onAlbumPlay ? () => onAlbumPlay(album.id) : undefined}
|
||||
@@ -1003,6 +1005,7 @@
|
||||
title={album.title}
|
||||
artist={album.artist?.name || 'Unknown Artist'}
|
||||
genre={getGenreLabel(album)}
|
||||
releaseDate={album.release_date_original}
|
||||
size="large"
|
||||
quality={getQualityLabel(album)}
|
||||
onPlay={onAlbumPlay ? () => onAlbumPlay(album.id) : undefined}
|
||||
|
||||
@@ -188,6 +188,7 @@ export interface ArtistDetail {
|
||||
title: string;
|
||||
artwork: string;
|
||||
year?: string;
|
||||
releaseDate?: string;
|
||||
quality: string;
|
||||
genre: string;
|
||||
}[];
|
||||
@@ -196,6 +197,7 @@ export interface ArtistDetail {
|
||||
title: string;
|
||||
artwork: string;
|
||||
year?: string;
|
||||
releaseDate?: string;
|
||||
quality: string;
|
||||
genre: string;
|
||||
}[];
|
||||
@@ -204,6 +206,7 @@ export interface ArtistDetail {
|
||||
title: string;
|
||||
artwork: string;
|
||||
year?: string;
|
||||
releaseDate?: string;
|
||||
quality: string;
|
||||
genre: string;
|
||||
}[];
|
||||
@@ -212,6 +215,7 @@ export interface ArtistDetail {
|
||||
title: string;
|
||||
artwork: string;
|
||||
year?: string;
|
||||
releaseDate?: string;
|
||||
quality: string;
|
||||
genre: string;
|
||||
}[];
|
||||
@@ -220,6 +224,7 @@ export interface ArtistDetail {
|
||||
title: string;
|
||||
artwork: string;
|
||||
year?: string;
|
||||
releaseDate?: string;
|
||||
quality: string;
|
||||
genre: string;
|
||||
}[];
|
||||
@@ -228,6 +233,7 @@ export interface ArtistDetail {
|
||||
title: string;
|
||||
artwork: string;
|
||||
year?: string;
|
||||
releaseDate?: string;
|
||||
quality: string;
|
||||
genre: string;
|
||||
}[];
|
||||
|
||||
@@ -335,7 +335,7 @@
|
||||
let isArtistAlbumsLoading = $state(false);
|
||||
|
||||
// Artist albums for "By the same artist" section in album view
|
||||
let albumArtistAlbums = $state<{ id: string; title: string; artwork: string; quality: string; genre: string }[]>([]);
|
||||
let albumArtistAlbums = $state<{ id: string; title: string; artwork: string; quality: string; genre: string; releaseDate?: string }[]>([]);
|
||||
|
||||
// Overlay States (from uiStore subscription)
|
||||
let isQueueOpen = $state(false);
|
||||
@@ -456,14 +456,16 @@
|
||||
title: a.title,
|
||||
artwork: a.artwork,
|
||||
quality: a.quality,
|
||||
genre: a.genre
|
||||
genre: a.genre,
|
||||
releaseDate: a.releaseDate
|
||||
})),
|
||||
...artistDetail.liveAlbums.map(a => ({
|
||||
id: a.id,
|
||||
title: a.title,
|
||||
artwork: a.artwork,
|
||||
quality: a.quality,
|
||||
genre: a.genre
|
||||
genre: a.genre,
|
||||
releaseDate: a.releaseDate
|
||||
}))
|
||||
].slice(0, 16);
|
||||
|
||||
|
||||
Reference in new issue
Block a user