feat: dynamic NP cover color, taller settings modal, fix Android song sync

- Now Playing: add "Dynamische Hintergrundfarbe" toggle in Theme settings;
  when on, np-bg uses higher saturation/brightness so the cover color really
  shows through the blurred background
- Settings modal: extend to bottom nav on mobile (was leaving ~74px dead space
  for the player bar which the overlay already covers at z-index 200)
- Android: fix onTrackChanged always staying on the first song — the snapshot
  from MediaController can lag behind ExoPlayer on auto-advance, causing the
  stale currentIndex to overwrite the correct p.index; now only advance to
  a higher live index (for rapid-skip catch-up) and use p.trackId directly
  instead of the potentially-stale snapshot id for the queue-mismatch guard

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
HoneyandClaude Sonnet 4.6 committed 2026-05-28 00:28:06 +02:00
1 parent c405465f5c
commit 9d81cdde31
5 files changed
+35 -15

No files matched your search

+14 -9
View File
@@ -184,20 +184,20 @@ window.NSPlayer = {
try {
const p = JSON.parse(payloadJson);
if (typeof p.index !== 'number') return;
// Reconcile with the live native state so stale out-of-order callbacks
// (e.g. from rapid skips) don't overwrite the already-correct index.
// p.index comes directly from ExoPlayer (always accurate).
// Only advance to a higher live index to handle rapid forward skips where
// the callback can arrive before we processed the previous one.
// Never let a stale MediaController snapshot pull us BACK to an old index.
let idx = p.index;
let liveId = '';
try {
const live = JSON.parse(window.NSBridge.getState() || '{}');
if (typeof live.currentIndex === 'number') idx = live.currentIndex;
liveId = live.currentId || '';
if (typeof live.currentIndex === 'number' && live.currentIndex > idx) idx = live.currentIndex;
} catch {}
if (idx < 0 || idx >= S.queue.length) return;
// Reject stale callbacks from the old queue: if the song ID at this index
// doesn't match what native is actually playing, the queues are mismatched.
// Allow through if reason='queue' (we triggered a setQueue) or if no IDs to compare.
if (liveId && S.queue[idx]?.id && String(liveId) !== String(S.queue[idx].id) && p.reason !== 'queue') return;
// Verify using the trackId from the callback payload (ExoPlayer-direct, not the
// potentially-stale snapshot) so auto-advance is never rejected by a lagged snapshot.
const trackId = p.trackId || '';
if (trackId && S.queue[idx]?.id && String(trackId) !== String(S.queue[idx].id) && p.reason !== 'queue') return;
const indexChanged = (idx !== S.qIdx);
S.qIdx = idx;
const s = S.queue[S.qIdx];
@@ -484,6 +484,11 @@ export function updatePlayerUI(s, _skipMediaSession = false) {
if (_npCv && _npCv !== _npBgLastUrl) { const _pre = new Image(); _pre.src = _npCv; }
}
// Apply/remove dynamic-color mode based on current setting.
export function updateNpColorMode() {
document.getElementById('np-overlay')?.classList.toggle('dynamic-color', !!S.cfg?.coverColorBg);
}
let _npBgCurr = 'a';
let _npBgLastUrl = '';
function _crossfadeNpBg(cv) {