When scrubbing show position's time even without preview images (#175)

When scrubbing along the seek bar, always show the position's time even
if there is no trickplay/preview image to display.
This commit is contained in:
damontecres 2025-11-08 09:34:12 -05:00 committed by GitHub
parent 7bdf7952c9
commit 762e8f287d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 77 additions and 80 deletions

View file

@ -342,29 +342,36 @@ fun PlaybackOverlay(
(playerControls.currentPosition.toFloat() / playerControls.duration) (playerControls.currentPosition.toFloat() / playerControls.duration)
} }
} }
if (trickplayInfo != null) {
AnimatedVisibility( AnimatedVisibility(
seekProgressPercent >= 0 && seekBarFocused, seekProgressPercent >= 0 && seekBarFocused,
) { ) {
val tilesPerImage = trickplayInfo.tileWidth * trickplayInfo.tileHeight
val index =
(seekProgressMs / trickplayInfo.interval).toInt() / tilesPerImage
val imageUrl = trickplayUrlFor(index)
if (imageUrl != null) {
Box( Box(
modifier = modifier =
Modifier Modifier
.align(Alignment.Center) .align(Alignment.Center)
.fillMaxWidth(.95f), .fillMaxWidth(.95f),
) { ) {
SeekPreviewImage( Column(
verticalArrangement = Arrangement.spacedBy(8.dp),
horizontalAlignment = Alignment.CenterHorizontally,
modifier = modifier =
Modifier Modifier
.align(Alignment.BottomStart) .align(Alignment.BottomStart)
.offsetByPercent( .offsetByPercent(
xPercentage = seekProgressPercent.coerceIn(0f, 1f), xPercentage = seekProgressPercent.coerceIn(0f, 1f),
).padding(bottom = controllerHeight - titleHeight - subtitleHeight), ).padding(bottom = controllerHeight - titleHeight - subtitleHeight),
) {
if (trickplayInfo != null) {
val tilesPerImage = trickplayInfo.tileWidth * trickplayInfo.tileHeight
val index =
(seekProgressMs / trickplayInfo.interval).toInt() / tilesPerImage
val imageUrl = trickplayUrlFor(index)
if (imageUrl != null) {
SeekPreviewImage(
modifier =
Modifier,
previewImageUrl = imageUrl, previewImageUrl = imageUrl,
duration = playerControls.duration, duration = playerControls.duration,
seekProgressMs = seekProgressMs, seekProgressMs = seekProgressMs,
@ -374,6 +381,12 @@ fun PlaybackOverlay(
) )
} }
} }
Text(
text = (seekProgressMs / 1000L).seconds.toString(),
color = MaterialTheme.colorScheme.onSurface,
style = MaterialTheme.typography.labelLarge,
)
}
} }
} }
AnimatedVisibility( AnimatedVisibility(

View file

@ -2,12 +2,9 @@ package com.github.damontecres.wholphin.ui.playback
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.border import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.painter.Painter import androidx.compose.ui.graphics.painter.Painter
@ -17,7 +14,6 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.tv.material3.MaterialTheme import androidx.tv.material3.MaterialTheme
import androidx.tv.material3.Text
import coil3.compose.AsyncImage import coil3.compose.AsyncImage
import coil3.request.CachePolicy import coil3.request.CachePolicy
import coil3.request.ImageRequest import coil3.request.ImageRequest
@ -25,7 +21,6 @@ import coil3.request.transformations
import com.github.damontecres.wholphin.ui.CoilTrickplayTransformation import com.github.damontecres.wholphin.ui.CoilTrickplayTransformation
import com.github.damontecres.wholphin.ui.isNotNullOrBlank import com.github.damontecres.wholphin.ui.isNotNullOrBlank
import org.jellyfin.sdk.model.api.TrickplayInfo import org.jellyfin.sdk.model.api.TrickplayInfo
import kotlin.time.Duration.Companion.seconds
fun Modifier.offsetByPercent( fun Modifier.offsetByPercent(
xPercentage: Float, xPercentage: Float,
@ -85,11 +80,6 @@ fun SeekPreviewImage(
) { ) {
val context = LocalContext.current val context = LocalContext.current
Column(
modifier = modifier,
verticalArrangement = Arrangement.spacedBy(8.dp),
horizontalAlignment = Alignment.CenterHorizontally,
) {
if (previewImageUrl.isNotNullOrBlank() && if (previewImageUrl.isNotNullOrBlank() &&
videoWidth != null && videoWidth != null &&
videoHeight != null videoHeight != null
@ -105,7 +95,7 @@ fun SeekPreviewImage(
AsyncImage( AsyncImage(
modifier = modifier =
Modifier modifier
.width(width) .width(width)
.height(height) .height(height)
.background(Color.Black) .background(Color.Black)
@ -130,10 +120,4 @@ fun SeekPreviewImage(
placeholder = placeHolder, placeholder = placeHolder,
) )
} }
Text(
text = (seekProgressMs / 1000L).seconds.toString(),
color = MaterialTheme.colorScheme.onSurface,
style = MaterialTheme.typography.labelLarge,
)
}
} }