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,
|
title: album.title,
|
||||||
artwork,
|
artwork,
|
||||||
year: album.release_date_original?.split('-')[0],
|
year: album.release_date_original?.split('-')[0],
|
||||||
|
releaseDate: album.release_date_original,
|
||||||
quality,
|
quality,
|
||||||
genre: album.genre?.name || "Unknown genre"
|
genre: album.genre?.name || "Unknown genre"
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
title: string;
|
title: string;
|
||||||
artist: string;
|
artist: string;
|
||||||
genre: string;
|
genre: string;
|
||||||
|
releaseDate?: string;
|
||||||
quality?: string;
|
quality?: string;
|
||||||
size?: 'standard' | 'large';
|
size?: 'standard' | 'large';
|
||||||
searchId?: string;
|
searchId?: string;
|
||||||
@@ -40,6 +41,7 @@
|
|||||||
title,
|
title,
|
||||||
artist,
|
artist,
|
||||||
genre,
|
genre,
|
||||||
|
releaseDate,
|
||||||
quality,
|
quality,
|
||||||
size = 'standard',
|
size = 'standard',
|
||||||
searchId,
|
searchId,
|
||||||
@@ -90,6 +92,19 @@
|
|||||||
imageError = true;
|
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) {
|
async function handleToggleFavorite(event: MouseEvent) {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
if (!albumId || !favoriteAvailable) return;
|
if (!albumId || !favoriteAvailable) return;
|
||||||
@@ -184,7 +199,12 @@
|
|||||||
<!-- Action Overlay -->
|
<!-- Action Overlay -->
|
||||||
{#if hasOverlay}
|
{#if hasOverlay}
|
||||||
<div class="action-overlay" class:menu-open={menuOpen}>
|
<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">
|
<div class="action-buttons">
|
||||||
{#if showFavoriteButton}
|
{#if showFavoriteButton}
|
||||||
<button
|
<button
|
||||||
@@ -393,15 +413,30 @@
|
|||||||
height: 30px;
|
height: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.overlay-genre {
|
.overlay-info {
|
||||||
align-self: flex-start;
|
align-self: flex-start;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
padding: 14px 14px;
|
padding: 14px 14px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.overlay-genre {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: white;
|
color: white;
|
||||||
text-shadow: 0 1px 3px rgba(0, 0, 0, 0.8);
|
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) {
|
:global(.album-card .album-menu) {
|
||||||
|
|||||||
@@ -33,6 +33,7 @@
|
|||||||
artwork: string;
|
artwork: string;
|
||||||
quality: string;
|
quality: string;
|
||||||
genre: string;
|
genre: string;
|
||||||
|
releaseDate?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
@@ -485,6 +486,7 @@
|
|||||||
title={relatedAlbum.title}
|
title={relatedAlbum.title}
|
||||||
artist={album.artist}
|
artist={album.artist}
|
||||||
genre={relatedAlbum.genre}
|
genre={relatedAlbum.genre}
|
||||||
|
releaseDate={relatedAlbum.releaseDate}
|
||||||
size="large"
|
size="large"
|
||||||
quality={relatedAlbum.quality}
|
quality={relatedAlbum.quality}
|
||||||
onclick={() => onRelatedAlbumClick?.(relatedAlbum.id)}
|
onclick={() => onRelatedAlbumClick?.(relatedAlbum.id)}
|
||||||
|
|||||||
@@ -1519,6 +1519,7 @@
|
|||||||
title={album.title}
|
title={album.title}
|
||||||
artist={album.year || ''}
|
artist={album.year || ''}
|
||||||
genre={album.genre}
|
genre={album.genre}
|
||||||
|
releaseDate={album.releaseDate}
|
||||||
size="large"
|
size="large"
|
||||||
quality={album.quality}
|
quality={album.quality}
|
||||||
searchId={`album-${album.id}`}
|
searchId={`album-${album.id}`}
|
||||||
@@ -1581,6 +1582,7 @@
|
|||||||
title={album.title}
|
title={album.title}
|
||||||
artist={album.year || ''}
|
artist={album.year || ''}
|
||||||
genre={album.genre}
|
genre={album.genre}
|
||||||
|
releaseDate={album.releaseDate}
|
||||||
size="large"
|
size="large"
|
||||||
quality={album.quality}
|
quality={album.quality}
|
||||||
searchId={`album-${album.id}`}
|
searchId={`album-${album.id}`}
|
||||||
@@ -1642,6 +1644,7 @@
|
|||||||
title={album.title}
|
title={album.title}
|
||||||
artist={album.year || ''}
|
artist={album.year || ''}
|
||||||
genre={album.genre}
|
genre={album.genre}
|
||||||
|
releaseDate={album.releaseDate}
|
||||||
size="large"
|
size="large"
|
||||||
quality={album.quality}
|
quality={album.quality}
|
||||||
searchId={`album-${album.id}`}
|
searchId={`album-${album.id}`}
|
||||||
@@ -1703,6 +1706,7 @@
|
|||||||
title={album.title}
|
title={album.title}
|
||||||
artist={album.year || ''}
|
artist={album.year || ''}
|
||||||
genre={album.genre}
|
genre={album.genre}
|
||||||
|
releaseDate={album.releaseDate}
|
||||||
size="large"
|
size="large"
|
||||||
quality={album.quality}
|
quality={album.quality}
|
||||||
searchId={`album-${album.id}`}
|
searchId={`album-${album.id}`}
|
||||||
@@ -1764,6 +1768,7 @@
|
|||||||
title={album.title}
|
title={album.title}
|
||||||
artist={album.year || ''}
|
artist={album.year || ''}
|
||||||
genre={album.genre}
|
genre={album.genre}
|
||||||
|
releaseDate={album.releaseDate}
|
||||||
size="large"
|
size="large"
|
||||||
quality={album.quality}
|
quality={album.quality}
|
||||||
searchId={`album-${album.id}`}
|
searchId={`album-${album.id}`}
|
||||||
@@ -1888,6 +1893,7 @@
|
|||||||
title={album.title}
|
title={album.title}
|
||||||
artist={album.year || ''}
|
artist={album.year || ''}
|
||||||
genre={album.genre}
|
genre={album.genre}
|
||||||
|
releaseDate={album.releaseDate}
|
||||||
size="large"
|
size="large"
|
||||||
quality={album.quality}
|
quality={album.quality}
|
||||||
searchId={`album-${album.id}`}
|
searchId={`album-${album.id}`}
|
||||||
|
|||||||
@@ -1301,6 +1301,7 @@
|
|||||||
title={album.title}
|
title={album.title}
|
||||||
artist={album.artist.name}
|
artist={album.artist.name}
|
||||||
genre={getGenreLabel(album)}
|
genre={getGenreLabel(album)}
|
||||||
|
releaseDate={album.release_date_original}
|
||||||
size="large"
|
size="large"
|
||||||
quality={getQualityLabel(album)}
|
quality={getQualityLabel(album)}
|
||||||
onPlay={onAlbumPlay ? () => onAlbumPlay(album.id) : undefined}
|
onPlay={onAlbumPlay ? () => onAlbumPlay(album.id) : undefined}
|
||||||
@@ -1374,6 +1375,7 @@
|
|||||||
title={album.title}
|
title={album.title}
|
||||||
artist={album.artist.name}
|
artist={album.artist.name}
|
||||||
genre={getGenreLabel(album)}
|
genre={getGenreLabel(album)}
|
||||||
|
releaseDate={album.release_date_original}
|
||||||
size="large"
|
size="large"
|
||||||
quality={getQualityLabel(album)}
|
quality={getQualityLabel(album)}
|
||||||
onPlay={onAlbumPlay ? () => onAlbumPlay(album.id) : undefined}
|
onPlay={onAlbumPlay ? () => onAlbumPlay(album.id) : undefined}
|
||||||
|
|||||||
@@ -38,6 +38,7 @@
|
|||||||
artist: string;
|
artist: string;
|
||||||
genre: string;
|
genre: string;
|
||||||
quality?: string;
|
quality?: string;
|
||||||
|
releaseDate?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ArtistCardData {
|
interface ArtistCardData {
|
||||||
@@ -334,7 +335,8 @@
|
|||||||
title: album.title,
|
title: album.title,
|
||||||
artist: album.artist?.name || 'Unknown Artist',
|
artist: album.artist?.name || 'Unknown Artist',
|
||||||
genre: album.genre?.name || 'Unknown genre',
|
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}
|
title={album.title}
|
||||||
artist={album.artist}
|
artist={album.artist}
|
||||||
genre={album.genre}
|
genre={album.genre}
|
||||||
|
releaseDate={album.releaseDate}
|
||||||
size="large"
|
size="large"
|
||||||
quality={album.quality}
|
quality={album.quality}
|
||||||
onPlay={onAlbumPlay ? () => onAlbumPlay(album.id) : undefined}
|
onPlay={onAlbumPlay ? () => onAlbumPlay(album.id) : undefined}
|
||||||
@@ -678,6 +681,7 @@
|
|||||||
title={album.title}
|
title={album.title}
|
||||||
artist={album.artist}
|
artist={album.artist}
|
||||||
genre={album.genre}
|
genre={album.genre}
|
||||||
|
releaseDate={album.releaseDate}
|
||||||
size="large"
|
size="large"
|
||||||
quality={album.quality}
|
quality={album.quality}
|
||||||
onPlay={onAlbumPlay ? () => onAlbumPlay(album.id) : undefined}
|
onPlay={onAlbumPlay ? () => onAlbumPlay(album.id) : undefined}
|
||||||
@@ -709,6 +713,7 @@
|
|||||||
title={album.title}
|
title={album.title}
|
||||||
artist={album.artist}
|
artist={album.artist}
|
||||||
genre={album.genre}
|
genre={album.genre}
|
||||||
|
releaseDate={album.releaseDate}
|
||||||
size="large"
|
size="large"
|
||||||
quality={album.quality}
|
quality={album.quality}
|
||||||
onPlay={onAlbumPlay ? () => onAlbumPlay(album.id) : undefined}
|
onPlay={onAlbumPlay ? () => onAlbumPlay(album.id) : undefined}
|
||||||
@@ -740,6 +745,7 @@
|
|||||||
title={album.title}
|
title={album.title}
|
||||||
artist={album.artist}
|
artist={album.artist}
|
||||||
genre={album.genre}
|
genre={album.genre}
|
||||||
|
releaseDate={album.releaseDate}
|
||||||
size="large"
|
size="large"
|
||||||
quality={album.quality}
|
quality={album.quality}
|
||||||
onPlay={onAlbumPlay ? () => onAlbumPlay(album.id) : undefined}
|
onPlay={onAlbumPlay ? () => onAlbumPlay(album.id) : undefined}
|
||||||
@@ -771,6 +777,7 @@
|
|||||||
title={album.title}
|
title={album.title}
|
||||||
artist={album.artist}
|
artist={album.artist}
|
||||||
genre={album.genre}
|
genre={album.genre}
|
||||||
|
releaseDate={album.releaseDate}
|
||||||
size="large"
|
size="large"
|
||||||
quality={album.quality}
|
quality={album.quality}
|
||||||
onPlay={onAlbumPlay ? () => onAlbumPlay(album.id) : undefined}
|
onPlay={onAlbumPlay ? () => onAlbumPlay(album.id) : undefined}
|
||||||
@@ -802,6 +809,7 @@
|
|||||||
title={album.title}
|
title={album.title}
|
||||||
artist={album.artist}
|
artist={album.artist}
|
||||||
genre={album.genre}
|
genre={album.genre}
|
||||||
|
releaseDate={album.releaseDate}
|
||||||
size="large"
|
size="large"
|
||||||
quality={album.quality}
|
quality={album.quality}
|
||||||
onPlay={onAlbumPlay ? () => onAlbumPlay(album.id) : undefined}
|
onPlay={onAlbumPlay ? () => onAlbumPlay(album.id) : undefined}
|
||||||
@@ -904,6 +912,7 @@
|
|||||||
title={album.title}
|
title={album.title}
|
||||||
artist={album.artist}
|
artist={album.artist}
|
||||||
genre={album.genre}
|
genre={album.genre}
|
||||||
|
releaseDate={album.releaseDate}
|
||||||
size="large"
|
size="large"
|
||||||
quality={album.quality}
|
quality={album.quality}
|
||||||
onPlay={onAlbumPlay ? () => onAlbumPlay(album.id) : undefined}
|
onPlay={onAlbumPlay ? () => onAlbumPlay(album.id) : undefined}
|
||||||
|
|||||||
@@ -278,6 +278,7 @@
|
|||||||
title={album.title}
|
title={album.title}
|
||||||
artist={album.artist?.name || 'Unknown Artist'}
|
artist={album.artist?.name || 'Unknown Artist'}
|
||||||
genre={getGenreLabel(album)}
|
genre={getGenreLabel(album)}
|
||||||
|
releaseDate={album.release_date_original}
|
||||||
quality={getQualityLabel(album)}
|
quality={getQualityLabel(album)}
|
||||||
size="large"
|
size="large"
|
||||||
onclick={() => onAlbumClick?.(album.id)}
|
onclick={() => onAlbumClick?.(album.id)}
|
||||||
|
|||||||
@@ -726,6 +726,7 @@
|
|||||||
title={allResults.albums.items[0].title}
|
title={allResults.albums.items[0].title}
|
||||||
artist={allResults.albums.items[0].artist?.name || 'Unknown Artist'}
|
artist={allResults.albums.items[0].artist?.name || 'Unknown Artist'}
|
||||||
genre={getGenreLabel(allResults.albums.items[0])}
|
genre={getGenreLabel(allResults.albums.items[0])}
|
||||||
|
releaseDate={allResults.albums.items[0].release_date_original}
|
||||||
size="large"
|
size="large"
|
||||||
quality={getQualityLabel(allResults.albums.items[0])}
|
quality={getQualityLabel(allResults.albums.items[0])}
|
||||||
onPlay={onAlbumPlay ? () => onAlbumPlay(allResults.albums.items[0].id) : undefined}
|
onPlay={onAlbumPlay ? () => onAlbumPlay(allResults.albums.items[0].id) : undefined}
|
||||||
@@ -863,6 +864,7 @@
|
|||||||
title={album.title}
|
title={album.title}
|
||||||
artist={album.artist?.name || 'Unknown Artist'}
|
artist={album.artist?.name || 'Unknown Artist'}
|
||||||
genre={getGenreLabel(album)}
|
genre={getGenreLabel(album)}
|
||||||
|
releaseDate={album.release_date_original}
|
||||||
size="large"
|
size="large"
|
||||||
quality={getQualityLabel(album)}
|
quality={getQualityLabel(album)}
|
||||||
onPlay={onAlbumPlay ? () => onAlbumPlay(album.id) : undefined}
|
onPlay={onAlbumPlay ? () => onAlbumPlay(album.id) : undefined}
|
||||||
@@ -1003,6 +1005,7 @@
|
|||||||
title={album.title}
|
title={album.title}
|
||||||
artist={album.artist?.name || 'Unknown Artist'}
|
artist={album.artist?.name || 'Unknown Artist'}
|
||||||
genre={getGenreLabel(album)}
|
genre={getGenreLabel(album)}
|
||||||
|
releaseDate={album.release_date_original}
|
||||||
size="large"
|
size="large"
|
||||||
quality={getQualityLabel(album)}
|
quality={getQualityLabel(album)}
|
||||||
onPlay={onAlbumPlay ? () => onAlbumPlay(album.id) : undefined}
|
onPlay={onAlbumPlay ? () => onAlbumPlay(album.id) : undefined}
|
||||||
|
|||||||
@@ -188,6 +188,7 @@ export interface ArtistDetail {
|
|||||||
title: string;
|
title: string;
|
||||||
artwork: string;
|
artwork: string;
|
||||||
year?: string;
|
year?: string;
|
||||||
|
releaseDate?: string;
|
||||||
quality: string;
|
quality: string;
|
||||||
genre: string;
|
genre: string;
|
||||||
}[];
|
}[];
|
||||||
@@ -196,6 +197,7 @@ export interface ArtistDetail {
|
|||||||
title: string;
|
title: string;
|
||||||
artwork: string;
|
artwork: string;
|
||||||
year?: string;
|
year?: string;
|
||||||
|
releaseDate?: string;
|
||||||
quality: string;
|
quality: string;
|
||||||
genre: string;
|
genre: string;
|
||||||
}[];
|
}[];
|
||||||
@@ -204,6 +206,7 @@ export interface ArtistDetail {
|
|||||||
title: string;
|
title: string;
|
||||||
artwork: string;
|
artwork: string;
|
||||||
year?: string;
|
year?: string;
|
||||||
|
releaseDate?: string;
|
||||||
quality: string;
|
quality: string;
|
||||||
genre: string;
|
genre: string;
|
||||||
}[];
|
}[];
|
||||||
@@ -212,6 +215,7 @@ export interface ArtistDetail {
|
|||||||
title: string;
|
title: string;
|
||||||
artwork: string;
|
artwork: string;
|
||||||
year?: string;
|
year?: string;
|
||||||
|
releaseDate?: string;
|
||||||
quality: string;
|
quality: string;
|
||||||
genre: string;
|
genre: string;
|
||||||
}[];
|
}[];
|
||||||
@@ -220,6 +224,7 @@ export interface ArtistDetail {
|
|||||||
title: string;
|
title: string;
|
||||||
artwork: string;
|
artwork: string;
|
||||||
year?: string;
|
year?: string;
|
||||||
|
releaseDate?: string;
|
||||||
quality: string;
|
quality: string;
|
||||||
genre: string;
|
genre: string;
|
||||||
}[];
|
}[];
|
||||||
@@ -228,6 +233,7 @@ export interface ArtistDetail {
|
|||||||
title: string;
|
title: string;
|
||||||
artwork: string;
|
artwork: string;
|
||||||
year?: string;
|
year?: string;
|
||||||
|
releaseDate?: string;
|
||||||
quality: string;
|
quality: string;
|
||||||
genre: string;
|
genre: string;
|
||||||
}[];
|
}[];
|
||||||
|
|||||||
@@ -335,7 +335,7 @@
|
|||||||
let isArtistAlbumsLoading = $state(false);
|
let isArtistAlbumsLoading = $state(false);
|
||||||
|
|
||||||
// Artist albums for "By the same artist" section in album view
|
// 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)
|
// Overlay States (from uiStore subscription)
|
||||||
let isQueueOpen = $state(false);
|
let isQueueOpen = $state(false);
|
||||||
@@ -456,14 +456,16 @@
|
|||||||
title: a.title,
|
title: a.title,
|
||||||
artwork: a.artwork,
|
artwork: a.artwork,
|
||||||
quality: a.quality,
|
quality: a.quality,
|
||||||
genre: a.genre
|
genre: a.genre,
|
||||||
|
releaseDate: a.releaseDate
|
||||||
})),
|
})),
|
||||||
...artistDetail.liveAlbums.map(a => ({
|
...artistDetail.liveAlbums.map(a => ({
|
||||||
id: a.id,
|
id: a.id,
|
||||||
title: a.title,
|
title: a.title,
|
||||||
artwork: a.artwork,
|
artwork: a.artwork,
|
||||||
quality: a.quality,
|
quality: a.quality,
|
||||||
genre: a.genre
|
genre: a.genre,
|
||||||
|
releaseDate: a.releaseDate
|
||||||
}))
|
}))
|
||||||
].slice(0, 16);
|
].slice(0, 16);
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user