show buffered percentage and fix progressbar colors
This commit is contained in:
parent
51b85c1720
commit
9786a5634d
|
@ -34,6 +34,7 @@ data class VideoPlayerUIState(
|
||||||
val embeddedUiRatio: Float,
|
val embeddedUiRatio: Float,
|
||||||
val contentFitMode: ContentScale,
|
val contentFitMode: ContentScale,
|
||||||
val seekerPosition: Float,
|
val seekerPosition: Float,
|
||||||
|
val bufferedPercentage: Float,
|
||||||
val isLoading: Boolean,
|
val isLoading: Boolean,
|
||||||
val durationInMs: Long,
|
val durationInMs: Long,
|
||||||
val playbackPositionInMs: Long
|
val playbackPositionInMs: Long
|
||||||
|
@ -44,10 +45,11 @@ data class VideoPlayerUIState(
|
||||||
fullscreen = false,
|
fullscreen = false,
|
||||||
uiVissible = false,
|
uiVissible = false,
|
||||||
uiVisible = false,
|
uiVisible = false,
|
||||||
contentRatio = 16 / 9F,
|
contentRatio = 16 / 9f,
|
||||||
embeddedUiRatio = 16F / 9F,
|
embeddedUiRatio = 16f / 9f,
|
||||||
contentFitMode = ContentScale.FIT_INSIDE,
|
contentFitMode = ContentScale.FIT_INSIDE,
|
||||||
seekerPosition = 0F,
|
seekerPosition = 0f,
|
||||||
|
bufferedPercentage = 0f,
|
||||||
isLoading = true,
|
isLoading = true,
|
||||||
durationInMs = 0,
|
durationInMs = 0,
|
||||||
playbackPositionInMs = 0
|
playbackPositionInMs = 0
|
||||||
|
|
|
@ -34,7 +34,6 @@ import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
import kotlinx.coroutines.flow.update
|
import kotlinx.coroutines.flow.update
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
@ -230,12 +229,15 @@ class VideoPlayerViewModelImpl @Inject constructor(
|
||||||
private fun updateProgressOnce() {
|
private fun updateProgressOnce() {
|
||||||
val progress = player?.currentPosition ?: 0
|
val progress = player?.currentPosition ?: 0
|
||||||
val duration = player?.duration ?: 1
|
val duration = player?.duration ?: 1
|
||||||
|
val bufferedPercentage = (player?.bufferedPercentage?.toFloat() ?: 0f) / 100f
|
||||||
val progressPercentage = progress.toFloat() / duration.toFloat()
|
val progressPercentage = progress.toFloat() / duration.toFloat()
|
||||||
|
|
||||||
mutableUiState.update {
|
mutableUiState.update {
|
||||||
it.copy(
|
it.copy(
|
||||||
seekerPosition = progressPercentage,
|
seekerPosition = progressPercentage,
|
||||||
durationInMs = duration,
|
durationInMs = duration,
|
||||||
playbackPositionInMs = progress
|
playbackPositionInMs = progress,
|
||||||
|
bufferedPercentage = bufferedPercentage
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,6 +61,7 @@ fun VideoPlayerControllerUI(
|
||||||
isLoading: Boolean,
|
isLoading: Boolean,
|
||||||
durationInMs: Long,
|
durationInMs: Long,
|
||||||
playbackPositionInMs: Long,
|
playbackPositionInMs: Long,
|
||||||
|
bufferedPercentage: Float,
|
||||||
play: () -> Unit,
|
play: () -> Unit,
|
||||||
pause: () -> Unit,
|
pause: () -> Unit,
|
||||||
prevStream: () -> Unit,
|
prevStream: () -> Unit,
|
||||||
|
@ -158,6 +159,7 @@ fun VideoPlayerControllerUI(
|
||||||
durationInMs = durationInMs,
|
durationInMs = durationInMs,
|
||||||
playbackPositionInMs = playbackPositionInMs,
|
playbackPositionInMs = playbackPositionInMs,
|
||||||
seekPosition = seekPosition,
|
seekPosition = seekPosition,
|
||||||
|
bufferedPercentage = bufferedPercentage,
|
||||||
switchToFullscreen = switchToFullscreen,
|
switchToFullscreen = switchToFullscreen,
|
||||||
switchToEmbeddedView = switchToEmbeddedView,
|
switchToEmbeddedView = switchToEmbeddedView,
|
||||||
seekPositionChanged = seekPositionChanged,
|
seekPositionChanged = seekPositionChanged,
|
||||||
|
@ -203,6 +205,7 @@ fun VideoPlayerControllerUIPreviewEmbedded() {
|
||||||
isLoading = false,
|
isLoading = false,
|
||||||
durationInMs = 9*60*1000,
|
durationInMs = 9*60*1000,
|
||||||
playbackPositionInMs = 6*60*1000,
|
playbackPositionInMs = 6*60*1000,
|
||||||
|
bufferedPercentage = 0.4f,
|
||||||
play = {},
|
play = {},
|
||||||
pause = {},
|
pause = {},
|
||||||
prevStream = {},
|
prevStream = {},
|
||||||
|
@ -229,6 +232,7 @@ fun VideoPlayerControllerUIPreviewLandscape() {
|
||||||
isLoading = true,
|
isLoading = true,
|
||||||
durationInMs = 9*60*1000,
|
durationInMs = 9*60*1000,
|
||||||
playbackPositionInMs = 6*60*1000,
|
playbackPositionInMs = 6*60*1000,
|
||||||
|
bufferedPercentage = 0.4f,
|
||||||
play = {},
|
play = {},
|
||||||
pause = {},
|
pause = {},
|
||||||
prevStream = {},
|
prevStream = {},
|
||||||
|
@ -256,6 +260,7 @@ fun VideoPlayerControllerUIPreviewPortrait() {
|
||||||
isLoading = false,
|
isLoading = false,
|
||||||
durationInMs = 9*60*1000,
|
durationInMs = 9*60*1000,
|
||||||
playbackPositionInMs = 6*60*1000,
|
playbackPositionInMs = 6*60*1000,
|
||||||
|
bufferedPercentage = 0.4f,
|
||||||
play = {},
|
play = {},
|
||||||
pause = {},
|
pause = {},
|
||||||
prevStream = {},
|
prevStream = {},
|
||||||
|
|
|
@ -28,7 +28,6 @@ import androidx.compose.foundation.layout.aspectRatio
|
||||||
import androidx.compose.foundation.layout.fillMaxHeight
|
import androidx.compose.foundation.layout.fillMaxHeight
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.material3.MaterialTheme
|
|
||||||
import androidx.compose.material3.Surface
|
import androidx.compose.material3.Surface
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.DisposableEffect
|
import androidx.compose.runtime.DisposableEffect
|
||||||
|
@ -152,6 +151,7 @@ fun VideoPlayerUI(
|
||||||
isLoading = uiState.isLoading,
|
isLoading = uiState.isLoading,
|
||||||
durationInMs = uiState.durationInMs,
|
durationInMs = uiState.durationInMs,
|
||||||
playbackPositionInMs = uiState.playbackPositionInMs,
|
playbackPositionInMs = uiState.playbackPositionInMs,
|
||||||
|
bufferedPercentage = uiState.bufferedPercentage,
|
||||||
play = viewModel::play,
|
play = viewModel::play,
|
||||||
pause = viewModel::pause,
|
pause = viewModel::pause,
|
||||||
prevStream = viewModel::prevStream,
|
prevStream = viewModel::prevStream,
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
*/
|
*/
|
||||||
package net.newpipe.newplayer.ui.seeker
|
package net.newpipe.newplayer.ui.seeker
|
||||||
|
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.Immutable
|
import androidx.compose.runtime.Immutable
|
||||||
import androidx.compose.runtime.Stable
|
import androidx.compose.runtime.Stable
|
||||||
|
@ -49,16 +50,16 @@ object SeekerDefaults {
|
||||||
*/
|
*/
|
||||||
@Composable
|
@Composable
|
||||||
fun seekerColors(
|
fun seekerColors(
|
||||||
progressColor: Color = VideoPlayerColorScheme.primary,
|
progressColor: Color = MaterialTheme.colorScheme.primary,
|
||||||
trackColor: Color = TrackColor,
|
trackColor: Color = TrackColor,
|
||||||
disabledProgressColor: Color = VideoPlayerColorScheme.onSurface.copy(alpha = DisabledProgressAlpha),
|
disabledProgressColor: Color = MaterialTheme.colorScheme.onSurface.copy(alpha = DisabledProgressAlpha),
|
||||||
disabledTrackColor: Color = disabledProgressColor
|
disabledTrackColor: Color = disabledProgressColor
|
||||||
.copy(alpha = DisabledTrackAlpha)
|
.copy(alpha = DisabledTrackAlpha)
|
||||||
.compositeOver(VideoPlayerColorScheme.onSurface),
|
.compositeOver(MaterialTheme.colorScheme.onSurface),
|
||||||
thumbColor: Color = VideoPlayerColorScheme.primary,
|
thumbColor: Color = MaterialTheme.colorScheme.primary,
|
||||||
disabledThumbColor: Color = VideoPlayerColorScheme.onSurface
|
disabledThumbColor: Color = MaterialTheme.colorScheme.onSurface
|
||||||
.copy(alpha = 0.0F)
|
.copy(alpha = 0.0F)
|
||||||
.compositeOver(VideoPlayerColorScheme.surface),
|
.compositeOver(MaterialTheme.colorScheme.surface),
|
||||||
readAheadColor: Color = ReadAheadColor
|
readAheadColor: Color = ReadAheadColor
|
||||||
): SeekerColors = DefaultSeekerColor(
|
): SeekerColors = DefaultSeekerColor(
|
||||||
progressColor = progressColor,
|
progressColor = progressColor,
|
||||||
|
|
|
@ -58,7 +58,9 @@ val video_player_onSurface = Color(0xFFF8F8F8)
|
||||||
// The color of the menu Icons
|
// The color of the menu Icons
|
||||||
val video_player_onSurfaceVariant = Color(0xFFF8F8F8)
|
val video_player_onSurfaceVariant = Color(0xFFF8F8F8)
|
||||||
|
|
||||||
|
// The background color of the seekbar
|
||||||
val video_player_surfaceVariant = Color(0xFF4F4539)
|
val video_player_surfaceVariant = Color(0xFF4F4539)
|
||||||
|
|
||||||
val video_player_outline = Color(0xFF9C8F80)
|
val video_player_outline = Color(0xFF9C8F80)
|
||||||
val video_player_inverseOnSurface = Color(0xFF1F1B16)
|
val video_player_inverseOnSurface = Color(0xFF1F1B16)
|
||||||
val video_player_inverseSurface = Color(0xFFEAE1D9)
|
val video_player_inverseSurface = Color(0xFFEAE1D9)
|
||||||
|
@ -80,6 +82,7 @@ fun VideoPlayerControllerUIPreviewEmbeddedColorPreview() {
|
||||||
isLoading = false,
|
isLoading = false,
|
||||||
durationInMs = 9*60*1000,
|
durationInMs = 9*60*1000,
|
||||||
playbackPositionInMs = 6*60*1000,
|
playbackPositionInMs = 6*60*1000,
|
||||||
|
bufferedPercentage = 0.4f,
|
||||||
play = {},
|
play = {},
|
||||||
pause = {},
|
pause = {},
|
||||||
prevStream = {},
|
prevStream = {},
|
||||||
|
|
|
@ -29,6 +29,7 @@ import androidx.compose.material.icons.filled.Fullscreen
|
||||||
import androidx.compose.material.icons.filled.FullscreenExit
|
import androidx.compose.material.icons.filled.FullscreenExit
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Surface
|
import androidx.compose.material3.Surface
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
@ -41,7 +42,10 @@ import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.core.os.ConfigurationCompat
|
import androidx.core.os.ConfigurationCompat
|
||||||
import net.newpipe.newplayer.R
|
import net.newpipe.newplayer.R
|
||||||
|
import net.newpipe.newplayer.ui.seeker.DefaultSeekerColor
|
||||||
import net.newpipe.newplayer.ui.seeker.Seeker
|
import net.newpipe.newplayer.ui.seeker.Seeker
|
||||||
|
import net.newpipe.newplayer.ui.seeker.SeekerColors
|
||||||
|
import net.newpipe.newplayer.ui.seeker.SeekerDefaults
|
||||||
import net.newpipe.newplayer.ui.theme.VideoPlayerTheme
|
import net.newpipe.newplayer.ui.theme.VideoPlayerTheme
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
|
@ -53,6 +57,7 @@ fun BottomUI(
|
||||||
seekPosition: Float,
|
seekPosition: Float,
|
||||||
durationInMs: Long,
|
durationInMs: Long,
|
||||||
playbackPositionInMs: Long,
|
playbackPositionInMs: Long,
|
||||||
|
bufferedPercentage: Float,
|
||||||
switchToFullscreen: () -> Unit,
|
switchToFullscreen: () -> Unit,
|
||||||
switchToEmbeddedView: () -> Unit,
|
switchToEmbeddedView: () -> Unit,
|
||||||
seekPositionChanged: (Float) -> Unit,
|
seekPositionChanged: (Float) -> Unit,
|
||||||
|
@ -68,7 +73,9 @@ fun BottomUI(
|
||||||
Modifier.weight(1F),
|
Modifier.weight(1F),
|
||||||
value = seekPosition,
|
value = seekPosition,
|
||||||
onValueChange = seekPositionChanged,
|
onValueChange = seekPositionChanged,
|
||||||
onValueChangeFinished = seekingFinished
|
onValueChangeFinished = seekingFinished,
|
||||||
|
readAheadValue = bufferedPercentage,
|
||||||
|
colors = customizedSeekerColors()
|
||||||
)
|
)
|
||||||
|
|
||||||
//Slider(value = 0.4F, onValueChange = {}, modifier = Modifier.weight(1F))
|
//Slider(value = 0.4F, onValueChange = {}, modifier = Modifier.weight(1F))
|
||||||
|
@ -85,6 +92,20 @@ fun BottomUI(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun customizedSeekerColors() : SeekerColors {
|
||||||
|
val colors = DefaultSeekerColor(
|
||||||
|
progressColor = MaterialTheme.colorScheme.primary,
|
||||||
|
thumbColor = MaterialTheme.colorScheme.primary,
|
||||||
|
trackColor = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.7f),
|
||||||
|
readAheadColor = MaterialTheme.colorScheme.primary.copy(alpha = 0.5f),
|
||||||
|
disabledProgressColor = MaterialTheme.colorScheme.primary,
|
||||||
|
disabledThumbColor = MaterialTheme.colorScheme.primary,
|
||||||
|
disabledTrackColor = MaterialTheme.colorScheme.primary
|
||||||
|
)
|
||||||
|
return colors
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@ReadOnlyComposable
|
@ReadOnlyComposable
|
||||||
fun getLocale(): Locale? {
|
fun getLocale(): Locale? {
|
||||||
|
@ -136,6 +157,7 @@ fun VideoPlayerControllerBottomUIPreview() {
|
||||||
seekPosition = 0.4F,
|
seekPosition = 0.4F,
|
||||||
durationInMs = 90 * 60 * 1000,
|
durationInMs = 90 * 60 * 1000,
|
||||||
playbackPositionInMs = 3 * 60 * 1000,
|
playbackPositionInMs = 3 * 60 * 1000,
|
||||||
|
bufferedPercentage = 0.4f,
|
||||||
switchToFullscreen = { },
|
switchToFullscreen = { },
|
||||||
switchToEmbeddedView = { },
|
switchToEmbeddedView = { },
|
||||||
seekPositionChanged = {}
|
seekPositionChanged = {}
|
||||||
|
|
|
@ -22,6 +22,5 @@
|
||||||
<resources>
|
<resources>
|
||||||
<string name="ccc_6502_video" translatable="false">https://ftp.fau.de/cdn.media.ccc.de/congress/2010/mp4-h264-HQ/27c3-4159-en-reverse_engineering_mos_6502.mp4</string>
|
<string name="ccc_6502_video" translatable="false">https://ftp.fau.de/cdn.media.ccc.de/congress/2010/mp4-h264-HQ/27c3-4159-en-reverse_engineering_mos_6502.mp4</string>
|
||||||
<string name="ccc_6502_audio" translatable="false">https://ftp.fau.de/cdn.media.ccc.de/congress/2010/ogg-audio-only/27c3-4159-en-reverse_engineering_mos_6502.ogg</string>
|
<string name="ccc_6502_audio" translatable="false">https://ftp.fau.de/cdn.media.ccc.de/congress/2010/ogg-audio-only/27c3-4159-en-reverse_engineering_mos_6502.ogg</string>
|
||||||
<string name="ccc_chromebooks_video" translatable="false">https://ftp.fau.de/cdn.media.ccc.de/congress/2023/h264-hd/37c3-11929-eng-deu-swe-Turning_Chromebooks_into_regular_laptops_hd.mp4</string>
|
|
||||||
<string name="portrait_video_example" translatable="false">https://videos.pexels.com/video-files/5512609/5512609-hd_1080_1920_25fps.mp4</string>
|
<string name="portrait_video_example" translatable="false">https://videos.pexels.com/video-files/5512609/5512609-hd_1080_1920_25fps.mp4</string>
|
||||||
</resources>
|
</resources>
|
Loading…
Reference in New Issue