feat(home): add Your Mixes section with DailyQ and WeeklyQ cards
Static section (no API call) with video-background cards that navigate to DynamicSuggestView and WeeklySuggestView. Positioned after Qobuz Playlists in default Home order, toggleable via Home Settings.
This commit is contained in:
1 parent
494ddce28b
commit
fc5da6cfc4
8 files changed
+103
-6
No files matched your search
@@ -129,6 +129,8 @@
|
||||
onNavigateAlbumsOfTheWeek?: () => void;
|
||||
onNavigatePressAccolades?: () => void;
|
||||
onNavigateQobuzPlaylists?: () => void;
|
||||
onNavigateDailyQ?: () => void;
|
||||
onNavigateWeeklyQ?: () => void;
|
||||
}
|
||||
|
||||
let {
|
||||
@@ -175,6 +177,8 @@
|
||||
onNavigateAlbumsOfTheWeek,
|
||||
onNavigatePressAccolades,
|
||||
onNavigateQobuzPlaylists,
|
||||
onNavigateDailyQ,
|
||||
onNavigateWeeklyQ,
|
||||
}: Props = $props();
|
||||
|
||||
// Home settings state
|
||||
@@ -1447,6 +1451,39 @@
|
||||
</HorizontalScrollRow>
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
{#if sectionId === 'yourMixes'}
|
||||
<HorizontalScrollRow>
|
||||
{#snippet header()}
|
||||
<div class="section-header-group">
|
||||
<h2 class="section-title">{$t('home.yourMixes')}</h2>
|
||||
</div>
|
||||
{/snippet}
|
||||
{#snippet children()}
|
||||
<button class="mix-card" onclick={() => onNavigateDailyQ?.()}
|
||||
onkeydown={(e) => e.key === 'Enter' && onNavigateDailyQ?.()}>
|
||||
<div class="mix-card-artwork">
|
||||
<video src="/video/dailyq.mp4" autoplay loop muted playsinline></video>
|
||||
</div>
|
||||
<div class="mix-card-info">
|
||||
<div class="mix-card-title">{$t('yourMixes.title')}</div>
|
||||
<div class="mix-card-owner">Qobuz</div>
|
||||
</div>
|
||||
</button>
|
||||
<button class="mix-card" onclick={() => onNavigateWeeklyQ?.()}
|
||||
onkeydown={(e) => e.key === 'Enter' && onNavigateWeeklyQ?.()}>
|
||||
<div class="mix-card-artwork">
|
||||
<video src="/video/weeklyq.mp4" autoplay loop muted playsinline></video>
|
||||
</div>
|
||||
<div class="mix-card-info">
|
||||
<div class="mix-card-title">{$t('weeklyMixes.title')}</div>
|
||||
<div class="mix-card-owner">Qobuz</div>
|
||||
</div>
|
||||
</button>
|
||||
<div class="spacer"></div>
|
||||
{/snippet}
|
||||
</HorizontalScrollRow>
|
||||
{/if}
|
||||
{/each}
|
||||
|
||||
<!-- Empty state: only show after all loading completes with no content -->
|
||||
@@ -1815,4 +1852,48 @@
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.mix-card {
|
||||
flex-shrink: 0;
|
||||
width: 180px;
|
||||
cursor: pointer;
|
||||
background: none;
|
||||
border: none;
|
||||
padding: 0;
|
||||
text-align: left;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.mix-card-artwork {
|
||||
width: 180px;
|
||||
height: 180px;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
background: var(--bg-tertiary);
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.mix-card-artwork video {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.mix-card-title {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: var(--text-primary);
|
||||
line-height: 1.4;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
.mix-card-owner {
|
||||
font-size: 12px;
|
||||
font-weight: 400;
|
||||
color: var(--text-muted);
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -44,7 +44,8 @@
|
||||
"artistPlays": "{count} Wiedergaben",
|
||||
"moreFromFavorites": "Mehr aus Favoriten",
|
||||
"startListening": "Beginne mit dem Hören",
|
||||
"startListeningDescription": "Spiele Musik oder füge Favoriten hinzu, um Empfehlungen zu aktivieren."
|
||||
"startListeningDescription": "Spiele Musik oder füge Favoriten hinzu, um Empfehlungen zu aktivieren.",
|
||||
"yourMixes": "Deine Mixe"
|
||||
},
|
||||
"discover": {
|
||||
"newReleases": "Neuerscheinungen",
|
||||
|
||||
@@ -47,7 +47,8 @@
|
||||
"artistPlays": "{count} plays",
|
||||
"moreFromFavorites": "More From Favorites",
|
||||
"startListening": "Start Listening",
|
||||
"startListeningDescription": "Play music or add favorites to activate recommendations."
|
||||
"startListeningDescription": "Play music or add favorites to activate recommendations.",
|
||||
"yourMixes": "Your mixes"
|
||||
},
|
||||
"discover": {
|
||||
"newReleases": "New Releases",
|
||||
|
||||
@@ -47,7 +47,8 @@
|
||||
"artistPlays": "{count} reproducciones",
|
||||
"moreFromFavorites": "Más de Favoritos",
|
||||
"startListening": "Empieza a Escuchar",
|
||||
"startListeningDescription": "Reproduce música o agrega favoritos para activar recomendaciones."
|
||||
"startListeningDescription": "Reproduce música o agrega favoritos para activar recomendaciones.",
|
||||
"yourMixes": "Tus mixes"
|
||||
},
|
||||
"discover": {
|
||||
"newReleases": "Novedades",
|
||||
|
||||
@@ -44,7 +44,8 @@
|
||||
"artistPlays": "{count} lectures",
|
||||
"moreFromFavorites": "Plus de favoris",
|
||||
"startListening": "Commencer l'écoute",
|
||||
"startListeningDescription": "Lisez de la musique ou ajoutez des favoris pour activer les recommandations."
|
||||
"startListeningDescription": "Lisez de la musique ou ajoutez des favoris pour activer les recommandations.",
|
||||
"yourMixes": "Tes mix"
|
||||
},
|
||||
"discover": {
|
||||
"newReleases": "Nouvelles sorties",
|
||||
|
||||
@@ -17,7 +17,8 @@ export type HomeSectionId =
|
||||
| 'recentAlbums'
|
||||
| 'continueTracks'
|
||||
| 'topArtists'
|
||||
| 'favoriteAlbums';
|
||||
| 'favoriteAlbums'
|
||||
| 'yourMixes';
|
||||
|
||||
export interface HomeSection {
|
||||
id: HomeSectionId;
|
||||
@@ -53,6 +54,7 @@ const DEFAULT_SECTIONS: HomeSection[] = [
|
||||
{ id: 'qobuzissimes', label: 'Qobuzissimes', visible: false, source: 'qobuz' },
|
||||
{ id: 'editorPicks', label: "Editor's Picks", visible: false, source: 'qobuz' },
|
||||
{ id: 'qobuzPlaylists', label: 'Qobuz Playlists', visible: true, source: 'qobuz' },
|
||||
{ id: 'yourMixes', label: 'Your Mixes', visible: true, source: 'qobuz' },
|
||||
{ id: 'essentialDiscography', label: 'Essential Discography', visible: true, source: 'qobuz' },
|
||||
{ id: 'recentAlbums', label: 'Recently Played', visible: true, source: 'ml' },
|
||||
{ id: 'continueTracks', label: 'Continue Listening', visible: true, source: 'ml' },
|
||||
|
||||
@@ -31,7 +31,9 @@ export type ViewType =
|
||||
| 'discover-press-accolades'
|
||||
| 'discover-playlists'
|
||||
| 'purchases'
|
||||
| 'purchase-album';
|
||||
| 'purchase-album'
|
||||
| 'dailyq'
|
||||
| 'weeklyq';
|
||||
export type FavoritesTab = 'tracks' | 'albums' | 'artists' | 'playlists';
|
||||
|
||||
// Navigation state
|
||||
|
||||
@@ -324,6 +324,8 @@
|
||||
import DiscoverPlaylistsBrowseView from '$lib/components/views/DiscoverPlaylistsBrowseView.svelte';
|
||||
import PurchasesView from '$lib/components/views/PurchasesView.svelte';
|
||||
import PurchaseAlbumDetailView from '$lib/components/views/PurchaseAlbumDetailView.svelte';
|
||||
import DynamicSuggestView from '$lib/components/views/DynamicSuggestView.svelte';
|
||||
import WeeklySuggestView from '$lib/components/views/WeeklySuggestView.svelte';
|
||||
|
||||
// Overlays
|
||||
import QueuePanel from '$lib/components/QueuePanel.svelte';
|
||||
@@ -3383,6 +3385,8 @@
|
||||
onNavigateAlbumsOfTheWeek={() => navigateTo('discover-albums-of-the-week')}
|
||||
onNavigatePressAccolades={() => navigateTo('discover-press-accolades')}
|
||||
onNavigateQobuzPlaylists={() => navigateTo('discover-playlists')}
|
||||
onNavigateDailyQ={() => navigateTo('dailyq')}
|
||||
onNavigateWeeklyQ={() => navigateTo('weeklyq')}
|
||||
/>
|
||||
{/if}
|
||||
{:else if activeView === 'search'}
|
||||
@@ -3790,6 +3794,10 @@
|
||||
onPlaylistCopyToLibrary={copyPlaylistToLibraryById}
|
||||
onPlaylistShareQobuz={sharePlaylistQobuzLinkById}
|
||||
/>
|
||||
{:else if activeView === 'dailyq'}
|
||||
<DynamicSuggestView />
|
||||
{:else if activeView === 'weeklyq'}
|
||||
<WeeklySuggestView />
|
||||
{:else if activeView === 'purchases'}
|
||||
<PurchasesView
|
||||
onAlbumClick={handlePurchaseAlbumClick}
|
||||
|
||||
Reference in new issue
Block a user