feat: add next track info to enlarged cover view with animation
This commit is contained in:
parent
25c6f1e5fb
commit
8361d31408
5 changed files with 68 additions and 2 deletions
|
|
@ -43,6 +43,10 @@
|
|||
<div class="fullscreen-track-info">
|
||||
<h2 id="fullscreen-track-title"></h2>
|
||||
<h3 id="fullscreen-track-artist"></h3>
|
||||
<div id="fullscreen-next-track" style="display: none;">
|
||||
<span class="label">Up Next: </span>
|
||||
<span class="value"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fullscreen-controls">
|
||||
<!-- Controls will be cloned or managed here if needed, or we just rely on main controls -->
|
||||
|
|
|
|||
10
js/app.js
10
js/app.js
|
|
@ -252,7 +252,8 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|||
clearLyricsPanelSync(audioPlayer, lyricsPanel);
|
||||
}
|
||||
} else if (mode === 'cover') {
|
||||
ui.showFullscreenCover(player.currentTrack);
|
||||
const nextTrack = player.getNextTrack();
|
||||
ui.showFullscreenCover(player.currentTrack, nextTrack);
|
||||
} else {
|
||||
// Default to 'album' mode - navigate to album
|
||||
if (player.currentTrack.album?.id) {
|
||||
|
|
@ -315,6 +316,13 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update Fullscreen/Enlarged Cover if it's open
|
||||
const fullscreenOverlay = document.getElementById('fullscreen-cover-overlay');
|
||||
if (fullscreenOverlay && getComputedStyle(fullscreenOverlay).display !== 'none') {
|
||||
const nextTrack = player.getNextTrack();
|
||||
ui.showFullscreenCover(player.currentTrack, nextTrack);
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener('click', async (e) => {
|
||||
|
|
|
|||
13
js/player.js
13
js/player.js
|
|
@ -366,6 +366,19 @@ export class Player {
|
|||
return this.shuffleActive ? this.shuffledQueue : this.queue;
|
||||
}
|
||||
|
||||
getNextTrack() {
|
||||
const currentQueue = this.getCurrentQueue();
|
||||
if (this.currentQueueIndex === -1 || currentQueue.length === 0) return null;
|
||||
|
||||
const nextIndex = this.currentQueueIndex + 1;
|
||||
if (nextIndex < currentQueue.length) {
|
||||
return currentQueue[nextIndex];
|
||||
} else if (this.repeatMode === REPEAT_MODE.ALL) {
|
||||
return currentQueue[0];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
updatePlayingTrackIndicator() {
|
||||
const currentTrack = this.getCurrentQueue()[this.currentQueueIndex];
|
||||
document.querySelectorAll('.track-item').forEach(item => {
|
||||
|
|
|
|||
16
js/ui.js
16
js/ui.js
|
|
@ -259,13 +259,14 @@ export class UIRenderer {
|
|||
root.style.removeProperty('--ring');
|
||||
}
|
||||
|
||||
showFullscreenCover(track) {
|
||||
showFullscreenCover(track, nextTrack) {
|
||||
if (!track) return;
|
||||
|
||||
const overlay = document.getElementById('fullscreen-cover-overlay');
|
||||
const image = document.getElementById('fullscreen-cover-image');
|
||||
const title = document.getElementById('fullscreen-track-title');
|
||||
const artist = document.getElementById('fullscreen-track-artist');
|
||||
const nextTrackEl = document.getElementById('fullscreen-next-track');
|
||||
|
||||
const coverUrl = this.api.getCoverUrl(track.album?.cover, '1280');
|
||||
|
||||
|
|
@ -273,6 +274,19 @@ export class UIRenderer {
|
|||
title.textContent = track.title;
|
||||
artist.textContent = track.artist?.name || 'Unknown Artist';
|
||||
|
||||
if (nextTrack) {
|
||||
nextTrackEl.style.display = 'flex';
|
||||
nextTrackEl.querySelector('.value').textContent = `${nextTrack.title} • ${nextTrack.artist?.name || 'Unknown'}`;
|
||||
|
||||
// Replay animation
|
||||
nextTrackEl.classList.remove('animate-in');
|
||||
void nextTrackEl.offsetWidth; // Trigger reflow
|
||||
nextTrackEl.classList.add('animate-in');
|
||||
} else {
|
||||
nextTrackEl.style.display = 'none';
|
||||
nextTrackEl.classList.remove('animate-in');
|
||||
}
|
||||
|
||||
// Set the background image via CSS variable for the pseudo-element to use
|
||||
overlay.style.setProperty('--bg-image', `url('${coverUrl}')`);
|
||||
|
||||
|
|
|
|||
27
styles.css
27
styles.css
|
|
@ -1319,6 +1319,33 @@ input:checked + .slider::before {
|
|||
text-shadow: 0 2px 10px rgba(0,0,0,0.5);
|
||||
}
|
||||
|
||||
#fullscreen-next-track {
|
||||
margin-top: 1.5rem;
|
||||
font-size: 0.9rem;
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
text-shadow: 0 1px 4px rgba(0,0,0,0.5);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.2rem;
|
||||
opacity: 0; /* Initially hidden for animation */
|
||||
}
|
||||
|
||||
#fullscreen-next-track.animate-in {
|
||||
animation: fadeIn 0.5s ease 0.2s forwards; /* Added forwards to keep opacity 1 */
|
||||
}
|
||||
|
||||
#fullscreen-next-track .label {
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
font-size: 0.75rem;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
#fullscreen-next-track .value {
|
||||
font-weight: 500;
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
#fullscreen-cover-overlay {
|
||||
padding-bottom: 160px; /* Account for taller mobile player bar */
|
||||
|
|
|
|||
Loading…
Reference in a new issue