Fix media seeking flicker (#6434)
This commit is contained in:
parent
9074692189
commit
a261156c7c
5 changed files with 40 additions and 7 deletions
|
|
@ -121,6 +121,7 @@ private fun ExoPlayerMediaAudioView(
|
||||||
durationInMillis = 0,
|
durationInMillis = 0,
|
||||||
canMute = false,
|
canMute = false,
|
||||||
isMuted = false,
|
isMuted = false,
|
||||||
|
seekingToMillis = null,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -171,15 +172,21 @@ private fun ExoPlayerMediaAudioView(
|
||||||
LaunchedEffect(exoPlayer.isPlaying) {
|
LaunchedEffect(exoPlayer.isPlaying) {
|
||||||
if (exoPlayer.isPlaying) {
|
if (exoPlayer.isPlaying) {
|
||||||
while (true) {
|
while (true) {
|
||||||
|
val position = exoPlayer.currentPosition
|
||||||
|
val seekingTo = mediaPlayerControllerState.seekingToMillis
|
||||||
mediaPlayerControllerState = mediaPlayerControllerState.copy(
|
mediaPlayerControllerState = mediaPlayerControllerState.copy(
|
||||||
progressInMillis = exoPlayer.currentPosition,
|
progressInMillis = position,
|
||||||
|
seekingToMillis = if (seekingTo != null && position >= seekingTo) null else seekingTo,
|
||||||
)
|
)
|
||||||
delay(200)
|
delay(200)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Ensure we render the final state
|
// Ensure we render the final state
|
||||||
|
val position = exoPlayer.currentPosition
|
||||||
|
val seekingTo = mediaPlayerControllerState.seekingToMillis
|
||||||
mediaPlayerControllerState = mediaPlayerControllerState.copy(
|
mediaPlayerControllerState = mediaPlayerControllerState.copy(
|
||||||
progressInMillis = exoPlayer.currentPosition,
|
progressInMillis = position,
|
||||||
|
seekingToMillis = if (seekingTo != null && position >= seekingTo) null else seekingTo,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -294,6 +301,9 @@ private fun ExoPlayerMediaAudioView(
|
||||||
exoPlayer.togglePlay()
|
exoPlayer.togglePlay()
|
||||||
},
|
},
|
||||||
onSeekChange = {
|
onSeekChange = {
|
||||||
|
mediaPlayerControllerState = mediaPlayerControllerState.copy(
|
||||||
|
seekingToMillis = it.toLong(),
|
||||||
|
)
|
||||||
exoPlayer.seekToEnsurePlaying(it.toLong())
|
exoPlayer.seekToEnsurePlaying(it.toLong())
|
||||||
},
|
},
|
||||||
onToggleMute = {
|
onToggleMute = {
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,16 @@ data class MediaPlayerControllerState(
|
||||||
val durationInMillis: Long,
|
val durationInMillis: Long,
|
||||||
val canMute: Boolean,
|
val canMute: Boolean,
|
||||||
val isMuted: Boolean,
|
val isMuted: Boolean,
|
||||||
|
val seekingToMillis: Long?,
|
||||||
) {
|
) {
|
||||||
|
/**
|
||||||
|
* The progress in milliseconds to display. When [seekingToMillis] is non-null (during a seek operation),
|
||||||
|
* this returns the target seek position. Once the player catches up to the seek position,
|
||||||
|
* [seekingToMillis] is cleared (set to null) and this returns [progressInMillis] again.
|
||||||
|
*/
|
||||||
|
val displayProgressInMillis: Long
|
||||||
|
get() = seekingToMillis ?: progressInMillis
|
||||||
|
|
||||||
@FloatRange(from = 0.0, to = 1.0)
|
@FloatRange(from = 0.0, to = 1.0)
|
||||||
val progressAsFloat = (progressInMillis.toFloat() / durationInMillis.toFloat()).coerceIn(0f, 1f)
|
val progressAsFloat = (displayProgressInMillis.toFloat() / durationInMillis.toFloat()).coerceIn(0f, 1f)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@ private fun aMediaPlayerControllerState(
|
||||||
durationInMillis: Long = 83_000,
|
durationInMillis: Long = 83_000,
|
||||||
canMute: Boolean = true,
|
canMute: Boolean = true,
|
||||||
isMuted: Boolean = false,
|
isMuted: Boolean = false,
|
||||||
|
seekingToMillis: Long? = null,
|
||||||
) = MediaPlayerControllerState(
|
) = MediaPlayerControllerState(
|
||||||
isVisible = isVisible,
|
isVisible = isVisible,
|
||||||
isPlaying = isPlaying,
|
isPlaying = isPlaying,
|
||||||
|
|
@ -42,4 +43,5 @@ private fun aMediaPlayerControllerState(
|
||||||
durationInMillis = durationInMillis,
|
durationInMillis = durationInMillis,
|
||||||
canMute = canMute,
|
canMute = canMute,
|
||||||
isMuted = isMuted,
|
isMuted = isMuted,
|
||||||
|
seekingToMillis = seekingToMillis,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -126,7 +126,7 @@ fun MediaPlayerControllerView(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.widthIn(min = 48.dp)
|
.widthIn(min = 48.dp)
|
||||||
.padding(horizontal = 8.dp),
|
.padding(horizontal = 8.dp),
|
||||||
text = state.progressInMillis.toHumanReadableDuration(),
|
text = state.displayProgressInMillis.toHumanReadableDuration(),
|
||||||
textAlign = TextAlign.Center,
|
textAlign = TextAlign.Center,
|
||||||
color = ElementTheme.colors.textPrimary,
|
color = ElementTheme.colors.textPrimary,
|
||||||
style = ElementTheme.typography.fontBodyXsMedium,
|
style = ElementTheme.typography.fontBodyXsMedium,
|
||||||
|
|
@ -135,7 +135,9 @@ fun MediaPlayerControllerView(
|
||||||
Slider(
|
Slider(
|
||||||
modifier = Modifier.weight(1f),
|
modifier = Modifier.weight(1f),
|
||||||
valueRange = 0f..state.durationInMillis.toFloat(),
|
valueRange = 0f..state.durationInMillis.toFloat(),
|
||||||
value = lastSelectedValue.takeIf { it >= 0 } ?: state.progressInMillis.toFloat(),
|
value = lastSelectedValue.takeIf { it >= 0 }
|
||||||
|
?: state.seekingToMillis?.toFloat()
|
||||||
|
?: state.progressInMillis.toFloat(),
|
||||||
onValueChange = {
|
onValueChange = {
|
||||||
lastSelectedValue = it
|
lastSelectedValue = it
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -108,6 +108,7 @@ private fun ExoPlayerMediaVideoView(
|
||||||
durationInMillis = 0,
|
durationInMillis = 0,
|
||||||
canMute = true,
|
canMute = true,
|
||||||
isMuted = false,
|
isMuted = false,
|
||||||
|
seekingToMillis = null,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -225,6 +226,9 @@ private fun ExoPlayerMediaVideoView(
|
||||||
},
|
},
|
||||||
onSeekChange = {
|
onSeekChange = {
|
||||||
autoHideController++
|
autoHideController++
|
||||||
|
mediaPlayerControllerState = mediaPlayerControllerState.copy(
|
||||||
|
seekingToMillis = it.toLong(),
|
||||||
|
)
|
||||||
exoPlayer.seekToEnsurePlaying(it.toLong())
|
exoPlayer.seekToEnsurePlaying(it.toLong())
|
||||||
},
|
},
|
||||||
onToggleMute = {
|
onToggleMute = {
|
||||||
|
|
@ -242,15 +246,21 @@ private fun ExoPlayerMediaVideoView(
|
||||||
LaunchedEffect(exoPlayer.isPlaying) {
|
LaunchedEffect(exoPlayer.isPlaying) {
|
||||||
if (exoPlayer.isPlaying) {
|
if (exoPlayer.isPlaying) {
|
||||||
while (true) {
|
while (true) {
|
||||||
|
val position = exoPlayer.currentPosition
|
||||||
|
val seekingTo = mediaPlayerControllerState.seekingToMillis
|
||||||
mediaPlayerControllerState = mediaPlayerControllerState.copy(
|
mediaPlayerControllerState = mediaPlayerControllerState.copy(
|
||||||
progressInMillis = exoPlayer.currentPosition,
|
progressInMillis = position,
|
||||||
|
seekingToMillis = if (seekingTo != null && position >= seekingTo) null else seekingTo,
|
||||||
)
|
)
|
||||||
delay(200)
|
delay(200)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Ensure we render the final state
|
// Ensure we render the final state
|
||||||
|
val position = exoPlayer.currentPosition
|
||||||
|
val seekingTo = mediaPlayerControllerState.seekingToMillis
|
||||||
mediaPlayerControllerState = mediaPlayerControllerState.copy(
|
mediaPlayerControllerState = mediaPlayerControllerState.copy(
|
||||||
progressInMillis = exoPlayer.currentPosition,
|
progressInMillis = position,
|
||||||
|
seekingToMillis = if (seekingTo != null && position >= seekingTo) null else seekingTo,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue