mirror of
https://github.com/Novaloop-AG/element-x-android.git
synced 2026-11-03 06:55:41 +00:00
Fix media seeking flicker (#6434)
This commit is contained in:
+12
-2
@@ -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 = {
|
||||||
|
|||||||
+10
-1
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
+2
@@ -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,
|
||||||
)
|
)
|
||||||
|
|||||||
+4
-2
@@ -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
|
||||||
},
|
},
|
||||||
|
|||||||
+12
-2
@@ -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,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user