From 6dc47a2c779c81a1be526c229c374397768db468 Mon Sep 17 00:00:00 2001 From: Honey Date: Fri, 29 May 2026 01:46:23 +0200 Subject: [PATCH] fix: suppress stale-snapshot NP flicker during skip window on Android Guard both snapshot-reconciliation paths (_skipping window can return the old index before ExoPlayer commits the new one): - onPlaybackStateChanged: skip the safety-net snapshot read while _skipping - onPositionUpdate: reset _reconTick (defer recon) while _skipping - _setSkipping: always reset _reconTick on every new skip/seek Co-Authored-By: Claude Sonnet 4.6 --- src/player.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/player.js b/src/player.js index 91d59fd..1c997f0 100644 --- a/src/player.js +++ b/src/player.js @@ -160,7 +160,8 @@ window.NSPlayer = { navigator.mediaSession.playbackState = state.isPlaying ? 'playing' : 'paused'; // Safety net: when playback starts, verify JS is showing the correct track. // Catches any edge cases where onTrackChanged was missed or queue drifted. - if (state.isPlaying) { + // Skip during _skipping window: snapshot may lag and still report the OLD index. + if (state.isPlaying && !_skipping) { try { const live = JSON.parse(window.NSBridge.getState() || '{}'); const liveIdx = live.currentIndex; @@ -225,7 +226,9 @@ window.NSPlayer = { // Every 8 ticks (~2 s): verify JS track matches native snapshot. // Catches the gap between auto-advance and onTrackChanged arriving in JS // (evaluateJavascript is deferred while WebView is backgrounded/resuming). - if (HAS_BRIDGE && ++_reconTick >= 8) { + // During _skipping window snapshot is stale — reset counter and wait. + if (_skipping) { _reconTick = 0; } + else if (HAS_BRIDGE && ++_reconTick >= 8) { _reconTick = 0; try { const snap = JSON.parse(window.NSBridge.getState() || '{}'); @@ -658,7 +661,8 @@ function _computeNextIdx() { } function _setSkipping() { - _skipping = true; + _skipping = true; + _reconTick = 0; clearTimeout(_skipTimer); _skipTimer = setTimeout(() => { _skipping = false; }, 2000); }