fix: revert MusicService debounce — it was causing the desync, not fixing it
The 120ms debounce on JS-initiated transitions (seek/setQueue) delayed updateStateSnapshot(), leaving a stale window where getState() returned the old index. If an AUTO callback fired during that window and the JS onTrackChanged handler called getState(), it would read the stale index and overwrite the correct player bar state with the wrong song. Fix: always fire onTrackChanged immediately so updateStateSnapshot() runs synchronously. The JS-side getState() reconciliation (from the previous commit) then reliably gets the settled native index every time. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
52079536b6
commit
f97e31178c
1 file changed
+6
-25
@@ -155,10 +155,6 @@ class MusicService : MediaSessionService() {
|
||||
|
||||
private inner class PlayerListener : Player.Listener {
|
||||
|
||||
// Debounce JS-initiated transitions (seek / queue-replace) so rapid skips
|
||||
// produce one onTrackChanged notification with the final settled state.
|
||||
private var _pendingTrackChanged: Runnable? = null
|
||||
|
||||
override fun onIsPlayingChanged(isPlaying: Boolean) {
|
||||
val state = player.playbackState
|
||||
stateListener?.onPlaybackStateChanged(
|
||||
@@ -188,31 +184,16 @@ class MusicService : MediaSessionService() {
|
||||
Player.MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED -> "queue"
|
||||
else -> "seek"
|
||||
}
|
||||
// Always warm artwork immediately so the notification never shows a blank cover.
|
||||
warmArtworkCache()
|
||||
|
||||
// Cancel any pending debounced dispatch from a previous transition.
|
||||
_pendingTrackChanged?.let { handler.removeCallbacks(it) }
|
||||
_pendingTrackChanged = null
|
||||
|
||||
val dispatch = Runnable {
|
||||
_pendingTrackChanged = null
|
||||
// Fire immediately — snapshot must always be fresh so the JS-side
|
||||
// getState() reconciliation in onTrackChanged sees current native state.
|
||||
stateListener?.onTrackChanged(
|
||||
player.currentMediaItemIndex,
|
||||
player.currentMediaItem?.mediaId ?: "",
|
||||
mediaItem?.mediaId ?: "",
|
||||
reasonStr
|
||||
)
|
||||
}
|
||||
|
||||
if (reason == Player.MEDIA_ITEM_TRANSITION_REASON_AUTO) {
|
||||
// Native auto-advance: JS didn't initiate this, notify immediately.
|
||||
dispatch.run()
|
||||
} else {
|
||||
// JS-initiated (seek or setQueue): debounce 120 ms so rapid skips
|
||||
// coalesce into one callback with the final settled index.
|
||||
_pendingTrackChanged = dispatch
|
||||
handler.postDelayed(dispatch, 120)
|
||||
}
|
||||
// Pre-warm artwork for current + next tracks so notification
|
||||
// never shows a blank cover on auto-advance.
|
||||
warmArtworkCache()
|
||||
}
|
||||
|
||||
override fun onTimelineChanged(timeline: Timeline, reason: Int) {
|
||||
|
||||
Reference in new issue
Block a user