Merge branch 'updates/uiux-1.1.7' into pre-release
This commit is contained in:
commit
1ac60d1d90
12 files changed
+120
-22
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
|
||||
@@ -325,9 +345,9 @@
|
||||
justify-content: center;
|
||||
opacity: 0;
|
||||
transition: opacity 150ms ease;
|
||||
background: rgba(10, 10, 10, 0.5);
|
||||
backdrop-filter: blur(4px);
|
||||
-webkit-backdrop-filter: blur(4px);
|
||||
background: rgba(10, 10, 10, 0.75);
|
||||
backdrop-filter: blur(12px);
|
||||
-webkit-backdrop-filter: blur(12px);
|
||||
pointer-events: auto;
|
||||
border-radius: inherit;
|
||||
z-index: 2;
|
||||
@@ -348,6 +368,24 @@
|
||||
left: 50%;
|
||||
top: 75%;
|
||||
transform: translate(-50%, -50%);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.album-card:hover .action-buttons,
|
||||
.action-overlay:focus-within .action-buttons,
|
||||
.action-overlay.menu-open .action-buttons {
|
||||
animation: slide-in-down 0.4s ease-out forwards;
|
||||
}
|
||||
|
||||
@keyframes slide-in-down {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translate(-50%, calc(-50% - 12px));
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
}
|
||||
|
||||
.overlay-btn {
|
||||
@@ -393,21 +431,49 @@
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
.overlay-genre {
|
||||
.overlay-info {
|
||||
align-self: flex-start;
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
padding-left: 1em;
|
||||
padding: 14px 14px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
opacity: 0;
|
||||
transform: translateY(12px);
|
||||
}
|
||||
|
||||
.album-card:hover .overlay-info,
|
||||
.action-overlay:focus-within .overlay-info,
|
||||
.action-overlay.menu-open .overlay-info {
|
||||
animation: slide-in-up 0.4s ease-out forwards;
|
||||
}
|
||||
|
||||
@keyframes slide-in-up {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translateY(12px);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.overlay-genre {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: white;
|
||||
text-shadow:
|
||||
0.06em 0 black,
|
||||
0 0.06em black,
|
||||
-0.06em 0 black,
|
||||
0 -0.06em black,
|
||||
-0.06em -0.06em black,
|
||||
-0.06em 0.06em black,
|
||||
0.06em -0.06em black,
|
||||
0.06em 0.06em black;
|
||||
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) {
|
||||
|
||||
@@ -259,7 +259,7 @@
|
||||
{#if onPlayLater}
|
||||
<button class="menu-item" onclick={() => handleAction(onPlayLater)}>
|
||||
<ListEnd size={14} />
|
||||
<span>Play later</span>
|
||||
<span>Add to queue</span>
|
||||
</button>
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
@@ -379,7 +379,7 @@
|
||||
{#if onPlayLater}
|
||||
<button class="menu-item" onclick={() => handleAction(onPlayLater)}>
|
||||
<ListEnd size={14} />
|
||||
<span>Play later</span>
|
||||
<span>Add to queue</span>
|
||||
</button>
|
||||
{/if}
|
||||
{#if onCreateRadio}
|
||||
|
||||
@@ -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)}
|
||||
|
||||
@@ -1333,7 +1333,7 @@
|
||||
Play Next
|
||||
</button>
|
||||
<button class="context-menu-item" onclick={() => { handlePlayAllTracksLater(); showTracksContextMenu = false; }}>
|
||||
Play Later
|
||||
Add to queue
|
||||
</button>
|
||||
<button class="context-menu-item" onclick={() => { handleShuffleAllTracks(); showTracksContextMenu = false; }}>
|
||||
Shuffle
|
||||
@@ -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