diff --git a/app/src/main/java/net/jeena/jtubetv/ui/screens/PlayerScreen.kt b/app/src/main/java/net/jeena/jtubetv/ui/screens/PlayerScreen.kt index b77e291..a080bed 100644 --- a/app/src/main/java/net/jeena/jtubetv/ui/screens/PlayerScreen.kt +++ b/app/src/main/java/net/jeena/jtubetv/ui/screens/PlayerScreen.kt @@ -286,6 +286,17 @@ private fun PlayerSurface( // a re-buffer after seeking) — shows an indicator until media really plays // (issue #8: the Loading screen ended too early and the rest was black). var buffering by remember { mutableStateOf(true) } + // The DISPLAYED overlay follows the raw player state debounced (issue #17): + // ExoPlayer flaps READY↔BUFFERING at every buffer edge and seek — tearing + // the overlay out of composition on each flap restarted the red spinner + // from zero ("it struggles and restarts"). Last pending value wins after + // 200 ms: quick flaps cancel the pending change and the overlay stays + // composed, so the animation never restarts mid-playback. + var bufferingPending by remember { mutableStateOf(true) } + LaunchedEffect(bufferingPending) { + kotlinx.coroutines.delay(200) + buffering = bufferingPending + } // Key press that was consumed at ACTION_DOWN — its trailing ACTION_UP must not // re-reveal the native controller right after a play/pause toggle. var consumedDownKey by remember { mutableStateOf(0) } @@ -393,7 +404,7 @@ private fun PlayerSurface( } override fun onPlaybackStateChanged(playbackState: Int) { - buffering = playbackState != Player.STATE_READY + bufferingPending = playbackState != Player.STATE_READY } }) onDispose {