diff --git a/index.html b/index.html index faa8632..d121e54 100644 --- a/index.html +++ b/index.html @@ -247,18 +247,18 @@
- - - + +
@@ -293,13 +293,13 @@

-

+
+
@@ -347,7 +350,7 @@ Mix @@ -669,9 +672,9 @@

We only store music data and a randomized ID to find out which Google account is which.
All data is anonymous. We do not store anything like emails, usernames, or anything sensitive.

However, if you want complete control over your data, we allow you to use your own firebase configuration.

- Advanced: Custom Configuration + Advanced: Custom Configuration
- + diff --git a/js/app.js b/js/app.js index 44833f5..0c4260b 100644 --- a/js/app.js +++ b/js/app.js @@ -325,6 +325,30 @@ document.addEventListener('DOMContentLoaded', async () => { alert('Failed to play album: ' + error.message); } } + if (e.target.closest('#download-mix-btn')) { + const btn = e.target.closest('#download-mix-btn'); + if (btn.disabled) return; + + const param = window.location.hash.split('#mix/')[1]; + if (!param) return; + const [mixId] = param.split('?'); + + btn.disabled = true; + const originalHTML = btn.innerHTML; + btn.innerHTML = 'Downloading...'; + + try { + const { mix, tracks } = await api.getMix(mixId); + await downloadPlaylistAsZip(mix, tracks, api, player.quality, lyricsManager); + } catch (error) { + console.error('Mix download failed:', error); + alert('Failed to download mix: ' + error.message); + } finally { + btn.disabled = false; + btn.innerHTML = originalHTML; + } + } + if (e.target.closest('#download-playlist-btn')) { const btn = e.target.closest('#download-playlist-btn'); if (btn.disabled) return; diff --git a/js/ui.js b/js/ui.js index e53d6ad..953e207 100644 --- a/js/ui.js +++ b/js/ui.js @@ -1185,6 +1185,8 @@ async showFullscreenCover(track, nextTrack, lyricsManager, audioPlayer) { const tracklistContainer = document.getElementById('mix-detail-tracklist'); const playBtn = document.getElementById('play-mix-btn'); if (playBtn) playBtn.innerHTML = `${SVG_PLAY}Play`; + const dlBtn = document.getElementById('download-mix-btn'); + if (dlBtn) dlBtn.innerHTML = `${SVG_DOWNLOAD}Download`; // Skeleton loading imageEl.src = ''; diff --git a/styles.css b/styles.css index 7aed88f..5ba5553 100644 --- a/styles.css +++ b/styles.css @@ -2401,6 +2401,35 @@ input:checked + .slider::before { border-bottom: none; } + +#playlist-detail-description, +#mix-detail-description { + color: var(--foreground); + font-size: 0.9rem; +} + +#playlist-detail-tracklist { + display: flex; + flex-direction: column; + gap: 2px; +} + +#playlist-detail-tracklist .track-list-header { + display: grid; + grid-template-columns: 40px 1fr auto; + align-items: center; + gap: var(--spacing-md); + padding: var(--spacing-sm); + color: var(--muted-foreground); + font-size: 0.9rem; + border-bottom: 1px solid var(--border); + margin-bottom: var(--spacing-xs); +} + +#playlist-detail-tracklist .track-list-header .duration-header { + justify-self: flex-end; +} + /* Responsive Design */ @media (max-width: 1024px) { .app-container { @@ -3165,49 +3194,6 @@ input:checked + .slider::before { opacity: 1; } -#playlist-detail-description, -#mix-detail-description { - color: var(--foreground); - font-size: 0.9rem; - line-height: 1.6; - margin-top: 1rem; - max-width: 600px; -} - -#playlist-detail-tracklist { - display: flex; - flex-direction: column; - gap: 2px; -} - -#playlist-detail-tracklist .track-list-header { - display: grid; - grid-template-columns: 40px 1fr auto; - align-items: center; - gap: var(--spacing-md); - padding: var(--spacing-sm); - color: var(--muted-foreground); - font-size: 0.9rem; - border-bottom: 1px solid var(--border); - margin-bottom: var(--spacing-xs); -} - -#playlist-detail-tracklist .track-list-header .duration-header { - justify-self: flex-end; -} - -@media (max-width: 480px) { - #playlist-detail-title { - font-size: 1.75rem; - } -} - -@media (min-width: 1024px) { - #playlist-detail-title { - font-size: 4rem; - } -} - /* Window Controls Overlay */ @media (display-mode: window-controls-overlay) { .app-container {