fix: NP overlay still shows stale song on auto-advance

Two fixes:
1. Remove snapshot read from openNowPlaying() — the MediaController snapshot
   can show the old song at the old index (both still valid entries in the
   queue), so the ID check does not detect staleness; after the onTrackChanged
   fix S.qIdx is always authoritative so there is no need to read the snapshot
2. Call syncNowPlaying() explicitly in onTrackChanged so the NP overlay is
   refreshed immediately when the song changes while it is already open

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
HoneyandClaude Sonnet 4.6 committed 2026-05-28 01:04:16 +02:00
1 parent ba28518d8a
commit 2d303083a0
2 files changed
+2 -16

No files matched your search

-15
View File
@@ -8,21 +8,6 @@ import { openPlModal, showSongInfo } from './ui.js';
// ─── NOW PLAYING OVERLAY ─── // ─── NOW PLAYING OVERLAY ───
export function openNowPlaying() { export function openNowPlaying() {
// On Android, verify the snapshot index before using it — the MediaController
// snapshot can lag behind ExoPlayer by one track on auto-advance. Only accept
// it when the song ID at that position matches (i.e. snapshot is not stale).
if (typeof window.NSBridge !== 'undefined') {
try {
const state = JSON.parse(window.NSBridge.getState() || '{}');
const snapIdx = state.currentIndex;
const snapId = state.currentId || '';
if (typeof snapIdx === 'number' && snapIdx >= 0 && snapIdx < S.queue.length) {
const expected = S.queue[snapIdx];
if (!snapId || !expected?.id || String(snapId) === String(expected.id))
S.qIdx = snapIdx;
}
} catch {}
}
S.npOpen = true; S.npOpen = true;
const overlay = document.getElementById('np-overlay'); const overlay = document.getElementById('np-overlay');
overlay.classList.add('open'); overlay.classList.add('open');
+2 -1
View File
@@ -3,7 +3,7 @@ import { esc, formatDur, toast } from './utils.js';
import { api, streamUrl, coverUrl, downloadUrl, dispTitle, dispArtist, dispArtistParts, dispAlbum } from './api.js'; import { api, streamUrl, coverUrl, downloadUrl, dispTitle, dispArtist, dispArtistParts, dispAlbum } from './api.js';
// views.js/ui.js circular imports — safe (only used inside function bodies) // views.js/ui.js circular imports — safe (only used inside function bodies)
import { loadRecommendations } from './views.js'; import { loadRecommendations } from './views.js';
import { updateLyricsHighlight, onNpSongChange } from './nowplaying.js'; import { updateLyricsHighlight, onNpSongChange, syncNowPlaying } from './nowplaying.js';
// ─── NATIVE BRIDGE DETECTION ─────────────────────────────────────────────── // ─── NATIVE BRIDGE DETECTION ───────────────────────────────────────────────
// True when running inside the NovaSonic Android wrapper (NSBridge injected before loadUrl). // True when running inside the NovaSonic Android wrapper (NSBridge injected before loadUrl).
@@ -203,6 +203,7 @@ window.NSPlayer = {
const s = S.queue[S.qIdx]; const s = S.queue[S.qIdx];
if (!s) return; if (!s) return;
updatePlayerUI(s, true); updatePlayerUI(s, true);
syncNowPlaying();
onNpSongChange(s.id); onNpSongChange(s.id);
if (indexChanged) renderQueue(); if (indexChanged) renderQueue();
// Schedule scrobble — fires after 12s of uninterrupted playback. // Schedule scrobble — fires after 12s of uninterrupted playback.