fix: smooth NP swipe-open animation; live playing highlight in song lists
Swipe animation: - _resetDrag(true) now reads the overlay's current drag position and starts the CSS transition from there instead of resetting to translateY(100%) first. That reset was causing the visible stutter (overlay jumped off-screen then slid back up). Now the overlay continues seamlessly from wherever the finger released to translateY(0). Playing highlight: - makeSongItem: adds data-song-id attribute to every .song-item element. - updatePlayerUI: calls _updatePlayingHighlights() after every track change. This toggles .playing on all visible song items in any open list/playlist/ favorites view so the highlighted row always matches what's actually playing, without requiring the user to navigate away and back. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
0fbb1385f1
commit
b0fb1b200d
3 files changed
+32
-2
No files matched your search
@@ -31,6 +31,7 @@ export function makeSongItem(s, idx, list, { noArtistLink = false, noAlbumLink =
|
|||||||
const el = document.createElement('div');
|
const el = document.createElement('div');
|
||||||
if(s.starred && !s._starred) s._starred = true;
|
if(s.starred && !s._starred) s._starred = true;
|
||||||
el.className = 'song-item' + (S.queue[S.qIdx]?.id === s.id ? ' playing' : '');
|
el.className = 'song-item' + (S.queue[S.qIdx]?.id === s.id ? ' playing' : '');
|
||||||
|
el.dataset.songId = s.id;
|
||||||
const cv = coverUrl(s.coverArt, 128);
|
const cv = coverUrl(s.coverArt, 128);
|
||||||
const artistParts = (s.artist || '').split(/\s*(?:\/|•|,)\s*/).filter(Boolean);
|
const artistParts = (s.artist || '').split(/\s*(?:\/|•|,)\s*/).filter(Boolean);
|
||||||
const artistHtml = artistParts.length
|
const artistHtml = artistParts.length
|
||||||
|
|||||||
+23
-2
@@ -221,8 +221,29 @@ window.addEventListener('load', () => {
|
|||||||
function _resetDrag(open) {
|
function _resetDrag(open) {
|
||||||
playerBar.classList.remove('dragging');
|
playerBar.classList.remove('dragging');
|
||||||
playerBar.style.transform = '';
|
playerBar.style.transform = '';
|
||||||
if(npOverlay) { npOverlay.style.transition = ''; npOverlay.style.transform = ''; }
|
|
||||||
if(open) openNowPlaying();
|
if (!npOverlay) { if(open) openNowPlaying(); _sy=0; _dragging=false; return; }
|
||||||
|
|
||||||
|
if (open) {
|
||||||
|
// Continue animating from the current drag position instead of
|
||||||
|
// resetting to translateY(100%) first (which caused the stutter).
|
||||||
|
const m = npOverlay.style.transform.match(/translateY\(([^p]+)px\)/);
|
||||||
|
const curY = m ? parseFloat(m[1]) : window.innerHeight;
|
||||||
|
npOverlay.style.transition = 'none';
|
||||||
|
npOverlay.style.transform = `translateY(${curY}px)`;
|
||||||
|
void npOverlay.offsetHeight; // flush layout so curY is the transition start
|
||||||
|
npOverlay.style.transition = '';
|
||||||
|
npOverlay.style.transform = 'translateY(0)';
|
||||||
|
npOverlay.addEventListener('transitionend', () => {
|
||||||
|
npOverlay.style.transform = '';
|
||||||
|
npOverlay.style.transition = '';
|
||||||
|
}, { once: true });
|
||||||
|
openNowPlaying();
|
||||||
|
} else {
|
||||||
|
npOverlay.style.transition = '';
|
||||||
|
npOverlay.style.transform = '';
|
||||||
|
}
|
||||||
|
|
||||||
_sy=0; _dragging=false;
|
_sy=0; _dragging=false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -356,6 +356,13 @@ export function playCurrent() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function _updatePlayingHighlights() {
|
||||||
|
const id = String(S.queue[S.qIdx]?.id ?? '');
|
||||||
|
document.querySelectorAll('.song-item[data-song-id]').forEach(el => {
|
||||||
|
el.classList.toggle('playing', el.dataset.songId === id);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export function updatePlayerUI(s, _skipMediaSession = false) {
|
export function updatePlayerUI(s, _skipMediaSession = false) {
|
||||||
document.getElementById('player-title').textContent = s.title;
|
document.getElementById('player-title').textContent = s.title;
|
||||||
const artistParts = (s.artist || '').split(/\s*(?:\/|•|,)\s*/).filter(Boolean);
|
const artistParts = (s.artist || '').split(/\s*(?:\/|•|,)\s*/).filter(Boolean);
|
||||||
@@ -387,6 +394,7 @@ export function updatePlayerUI(s, _skipMediaSession = false) {
|
|||||||
}));
|
}));
|
||||||
} catch {}
|
} catch {}
|
||||||
_syncNpDirect(s);
|
_syncNpDirect(s);
|
||||||
|
_updatePlayingHighlights();
|
||||||
// Preload the hi-res NP cover now so opening the overlay is instant
|
// Preload the hi-res NP cover now so opening the overlay is instant
|
||||||
const _npCv = coverUrl(s.coverArt, 1024);
|
const _npCv = coverUrl(s.coverArt, 1024);
|
||||||
if (_npCv && _npCv !== _npBgLastUrl) { const _pre = new Image(); _pre.src = _npCv; }
|
if (_npCv && _npCv !== _npBgLastUrl) { const _pre = new Image(); _pre.src = _npCv; }
|
||||||
|
|||||||
Reference in new issue
Block a user