fix: stop ExoPlayer shuffle conflict causing end-of-queue desync

When reaching the last shuffled song, the UI changed but audio kept playing
the same song. Root cause: ExoPlayer still had its own shuffle mode on (set
in onReady), so its auto-advance and _nsBridge('next') picked random indices
that conflicted with the pre-shuffled JS array.

- setShuffleMode always false: we own the playback order via pre-shuffled
  JS array, ExoPlayer must advance sequentially through it
- Remove _nsBridge('next') fallback: never let ExoPlayer decide the next
  song autonomously. End of queue with no repeat = let ExoPlayer stop.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
HoneyandClaude Sonnet 4.6 committed 2026-06-04 11:13:45 +02:00
1 parent ef40795a9c
commit db7a515ee4
1 file changed
+4 -5
+4 -5
View File
@@ -130,8 +130,10 @@ window.NSPlayer = {
} catch (e) {} } catch (e) {}
} }
// Always sync shuffle/repeat settings. // Always sync shuffle/repeat settings.
// setShuffleMode is always false — we pre-shuffle the JS array ourselves and
// traverse sequentially, so ExoPlayer's internal shuffle must stay off.
_nsBridge('setRepeatMode', S.repeat === false ? 'off' : S.repeat); _nsBridge('setRepeatMode', S.repeat === false ? 'off' : S.repeat);
_nsBridge('setShuffleMode', S.shuffle); _nsBridge('setShuffleMode', false);
}, },
// Play/pause/buffer state changed. // Play/pause/buffer state changed.
@@ -714,10 +716,7 @@ export function nextSong() {
// Explicit index prevents desync when JS and native queue pointers diverge. // Explicit index prevents desync when JS and native queue pointers diverge.
_nsBridge('seekToIndex', ni, 0); _nsBridge('seekToIndex', ni, 0);
_nsBridge('play'); _nsBridge('play');
} else { // else: ni = -1 means end of queue with no repeat — let ExoPlayer stop naturally.
// Shuffle mode: native picks the shuffled-next item; onTrackChanged will confirm the index.
_nsBridge('next');
}
if (S.radioMode && S.queue.length - S.qIdx < 5) fillRadioQueue(); if (S.radioMode && S.queue.length - S.qIdx < 5) fillRadioQueue();
return; return;
} }