From 3e228a0d46ab25e852028537e9421ea23f4c91c8 Mon Sep 17 00:00:00 2001 From: Julien Maille Date: Sat, 3 Jan 2026 13:00:12 +0100 Subject: [PATCH] FEAT: add track mix button to player bar and display release year --- index.html | 5 +++++ js/events.js | 10 ++++++++++ js/player.js | 32 ++++++++++++++++++++++++++++++-- js/ui.js | 13 ++++++++----- js/utils.js | 1 + 5 files changed, 54 insertions(+), 7 deletions(-) diff --git a/index.html b/index.html index dfbd11f..e0ebe23 100644 --- a/index.html +++ b/index.html @@ -711,6 +711,11 @@
+ diff --git a/js/events.js b/js/events.js index a04d056..8d071d6 100644 --- a/js/events.js +++ b/js/events.js @@ -667,6 +667,16 @@ export function initializeTrackInteractions(player, api, mainContent, contextMen } }); } + + const nowPlayingMixBtn = document.getElementById('now-playing-mix-btn'); + if (nowPlayingMixBtn) { + nowPlayingMixBtn.addEventListener('click', async (e) => { + e.stopPropagation(); + if (player.currentTrack) { + await handleTrackAction('track-mix', player.currentTrack, player, api, lyricsManager, 'track', ui, scrobbler); + } + }); + } } function renderQueue(player) { diff --git a/js/player.js b/js/player.js index 243251b..a0f36fb 100644 --- a/js/player.js +++ b/js/player.js @@ -44,6 +44,15 @@ export class Player { const track = this.currentTrack; const trackTitle = getTrackTitle(track); const trackArtistsHTML = getTrackArtistsHTML(track); + + let yearDisplay = ''; + const releaseDate = track.album?.releaseDate || track.streamStartDate; + if (releaseDate) { + const date = new Date(releaseDate); + if (!isNaN(date.getTime())) { + yearDisplay = ` • ${date.getFullYear()}`; + } + } const coverEl = document.querySelector('.now-playing-bar .cover'); const titleEl = document.querySelector('.now-playing-bar .title'); @@ -51,7 +60,12 @@ export class Player { if (coverEl) coverEl.src = this.api.getCoverUrl(track.album?.cover, '1280'); if (titleEl) titleEl.textContent = trackTitle; - if (artistEl) artistEl.innerHTML = trackArtistsHTML; + if (artistEl) artistEl.innerHTML = trackArtistsHTML + yearDisplay; + + const mixBtn = document.getElementById('now-playing-mix-btn'); + if (mixBtn) { + mixBtn.style.display = (track.mixes && track.mixes.TRACK_MIX) ? 'flex' : 'none'; + } const totalDurationEl = document.getElementById('total-duration'); if (totalDurationEl) totalDurationEl.textContent = formatTime(track.duration); document.title = `${trackTitle} • ${track.artist?.name || 'Unknown'}`; @@ -169,11 +183,25 @@ export class Player { const trackTitle = getTrackTitle(track); const trackArtistsHTML = getTrackArtistsHTML(track); + + let yearDisplay = ''; + const releaseDate = track.album?.releaseDate || track.streamStartDate; + if (releaseDate) { + const date = new Date(releaseDate); + if (!isNaN(date.getTime())) { + yearDisplay = ` • ${date.getFullYear()}`; + } + } document.querySelector('.now-playing-bar .cover').src = this.api.getCoverUrl(track.album?.cover, '1280'); document.querySelector('.now-playing-bar .title').textContent = trackTitle; - document.querySelector('.now-playing-bar .artist').innerHTML = trackArtistsHTML; + document.querySelector('.now-playing-bar .artist').innerHTML = trackArtistsHTML + yearDisplay; + + const mixBtn = document.getElementById('now-playing-mix-btn'); + if (mixBtn) { + mixBtn.style.display = (track.mixes && track.mixes.TRACK_MIX) ? 'flex' : 'none'; + } document.title = `${trackTitle} • ${track.artist?.name || 'Unknown'}`; this.updatePlayingTrackIndicator(); diff --git a/js/ui.js b/js/ui.js index 6efa5f0..4c34516 100644 --- a/js/ui.js +++ b/js/ui.js @@ -1189,17 +1189,20 @@ async showFullscreenCover(track, nextTrack, lyricsManager, audioPlayer) { let displayTitle; if (type === 'artist' && name) { - displayTitle = `Mix for artist ${decodeURIComponent(name)}`; + const decodedName = decodeURIComponent(name); + titleEl.innerHTML = `Mix for artist ${decodedName}`; + this.adjustTitleFontSize(titleEl, `Mix for artist ${decodedName}`); } else if (type === 'track' && name) { - displayTitle = `Mix for track ${decodeURIComponent(name)}`; + const decodedName = decodeURIComponent(name); + titleEl.innerHTML = `Mix for track ${decodedName}`; + this.adjustTitleFontSize(titleEl, `Mix for track ${decodedName}`); } else { const firstTrackArtist = tracks.length > 0 ? tracks[0].artist?.name : ''; displayTitle = mix.title || (firstTrackArtist ? `${firstTrackArtist} Mix` : 'Mix'); + titleEl.textContent = displayTitle; + this.adjustTitleFontSize(titleEl, displayTitle); } - titleEl.textContent = displayTitle; - this.adjustTitleFontSize(titleEl, displayTitle); - const totalDuration = calculateTotalDuration(tracks); metaEl.textContent = `${tracks.length} tracks • ${formatDuration(totalDuration)}`; diff --git a/js/utils.js b/js/utils.js index 0aa6a95..496a542 100644 --- a/js/utils.js +++ b/js/utils.js @@ -35,6 +35,7 @@ export const SVG_MENU = ' { if (isNaN(seconds)) return '0:00';