fix: eliminate notification/playerbar song desync on Android

Two-pronged fix for the state drift between the system notification
(ground truth) and the WebView player bar:

JS (player.js): onTrackChanged now reconciles the incoming index with a
synchronous NSBridge.getState() call before applying it. Stale callbacks
from earlier rapid skips immediately correct themselves to the live
settled index instead of overwriting the correct state.

Kotlin (MusicService.kt): debounce JS-initiated transitions (seek /
setQueue) by 120 ms so rapid skip sequences produce one onTrackChanged
notification at the final index rather than one per skip step. Auto-advance
transitions are still fired immediately since JS doesn't initiate those.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
HoneyandClaude Sonnet 4.6 committed 2026-05-20 23:38:25 +02:00
1 parent 0874fd4f9f
commit 52079536b6
2 files changed
+38 -10

No files matched your search

+10 -3
View File
@@ -143,9 +143,16 @@ window.NSPlayer = {
try {
const p = JSON.parse(payloadJson);
if (typeof p.index !== 'number') return;
if (p.index < 0 || p.index >= S.queue.length) return;
const indexChanged = (p.index !== S.qIdx);
S.qIdx = p.index;
// Reconcile with the live native state so stale out-of-order callbacks
// (e.g. from rapid skips) don't overwrite the already-correct index.
let idx = p.index;
try {
const live = JSON.parse(window.NSBridge.getState() || '{}');
if (typeof live.currentIndex === 'number') idx = live.currentIndex;
} catch {}
if (idx < 0 || idx >= S.queue.length) return;
const indexChanged = (idx !== S.qIdx);
S.qIdx = idx;
const s = S.queue[S.qIdx];
if (!s) return;
updatePlayerUI(s, true);