fix: bottom bar no touch seek; lyrics seek on Android; smoother NP animation

- initProgressScrub: pass noTouch=true for the bottom mini-bar so touch
  events are never registered on it; only mouse events remain (desktop-only).
  The now-playing scrubber is unchanged and keeps full touch support.
- Export seekToMs(ms) from player.js; use it in the lyrics click handler
  instead of S.audio.currentTime which has no effect when HAS_BRIDGE
  (native ExoPlayer handles playback, not the HTML audio element).
- styles.css: add will-change:transform to .player and .np-overlay to keep
  them on GPU compositor layers during the swipe gesture; tweak NP open
  transition to cubic-bezier(.4,0,.2,1) for a snappier feel.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
HoneyandClaude Sonnet 4.6 committed 2026-05-18 22:42:58 +02:00
1 parent 9d8a5a22bb
commit 4856f0ca57
3 files changed
+40 -25

No files matched your search

+35 -21
View File
@@ -656,10 +656,12 @@ export function seekTo(e) {
}
export function initProgressScrub() {
// Bottom mini-bar: mouse-only (touch disabled — too easy to accidentally seek on mobile).
_initBarScrub(
document.getElementById('progress-bar'),
document.getElementById('progress-fill'),
pos => { document.getElementById('time-cur').textContent = formatDur(pos * _dur()); }
pos => { document.getElementById('time-cur').textContent = formatDur(pos * _dur()); },
/* noTouch= */ true
);
_initBarScrub(
document.getElementById('np-bar'),
@@ -668,7 +670,17 @@ export function initProgressScrub() {
);
}
function _initBarScrub(bar, fill, onMove) {
// Export for lyrics / other callers that need to seek by ms.
export function seekToMs(ms) {
if (HAS_BRIDGE) {
_setSkipping();
_nsBridge('seekTo', Math.round(ms));
} else {
S.audio.currentTime = ms / 1000;
}
}
function _initBarScrub(bar, fill, onMove, noTouch = false) {
if(!bar || !fill) return;
function getPos(clientX) { const r = bar.getBoundingClientRect(); return Math.max(0, Math.min(1, (clientX-r.left)/r.width)); }
function startScrub(pos) { S._scrubbing=true; fill.style.transition='none'; fill.style.width=(pos*100)+'%'; onMove(pos); }
@@ -691,25 +703,27 @@ function _initBarScrub(bar, fill, onMove) {
fill.style.transition = '';
}
}
// Touch: require ≥8px horizontal drag before committing to scrub.
// A plain tap cancels cleanly without seeking.
let _touchStartX = 0, _touchMoved = false;
bar.addEventListener('touchstart', e => {
_touchStartX = e.touches[0].clientX;
_touchMoved = false;
e.stopPropagation();
e.preventDefault(); // block synthetic mousedown/click that would trigger scrub on plain tap
});
bar.addEventListener('touchmove', e => {
const dx = Math.abs(e.touches[0].clientX - _touchStartX);
if (!_touchMoved && dx >= 8) { _touchMoved = true; startScrub(getPos(e.touches[0].clientX)); }
if (_touchMoved && S._scrubbing) moveScrub(getPos(e.touches[0].clientX));
}, {passive:true});
bar.addEventListener('touchend', e => {
if (_touchMoved && S._scrubbing) endScrub(getPos(e.changedTouches[0].clientX));
else S._scrubbing = false;
_touchMoved = false;
}, {passive:true});
if (!noTouch) {
// Touch: require ≥8px horizontal drag before committing to scrub.
// A plain tap cancels cleanly without seeking.
let _touchStartX = 0, _touchMoved = false;
bar.addEventListener('touchstart', e => {
_touchStartX = e.touches[0].clientX;
_touchMoved = false;
e.stopPropagation();
e.preventDefault(); // block synthetic mousedown/click that would trigger scrub on plain tap
});
bar.addEventListener('touchmove', e => {
const dx = Math.abs(e.touches[0].clientX - _touchStartX);
if (!_touchMoved && dx >= 8) { _touchMoved = true; startScrub(getPos(e.touches[0].clientX)); }
if (_touchMoved && S._scrubbing) moveScrub(getPos(e.touches[0].clientX));
}, {passive:true});
bar.addEventListener('touchend', e => {
if (_touchMoved && S._scrubbing) endScrub(getPos(e.changedTouches[0].clientX));
else S._scrubbing = false;
_touchMoved = false;
}, {passive:true});
}
bar.addEventListener('mousedown', e => {
startScrub(getPos(e.clientX)); e.preventDefault();
const mm = e2 => { if(S._scrubbing) moveScrub(getPos(e2.clientX)); };