mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-07-08 15:50:16 +02:00
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:
parent
7bdf7952c9
commit
762e8f287d
2 changed files with 77 additions and 80 deletions
|
|
@ -342,37 +342,50 @@ fun PlaybackOverlay(
|
|||
(playerControls.currentPosition.toFloat() / playerControls.duration)
|
||||
}
|
||||
}
|
||||
if (trickplayInfo != null) {
|
||||
AnimatedVisibility(
|
||||
seekProgressPercent >= 0 && seekBarFocused,
|
||||
) {
|
||||
val tilesPerImage = trickplayInfo.tileWidth * trickplayInfo.tileHeight
|
||||
val index =
|
||||
(seekProgressMs / trickplayInfo.interval).toInt() / tilesPerImage
|
||||
val imageUrl = trickplayUrlFor(index)
|
||||
|
||||
if (imageUrl != null) {
|
||||
Box(
|
||||
modifier =
|
||||
Modifier
|
||||
.align(Alignment.Center)
|
||||
.fillMaxWidth(.95f),
|
||||
) {
|
||||
SeekPreviewImage(
|
||||
modifier =
|
||||
Modifier
|
||||
.align(Alignment.BottomStart)
|
||||
.offsetByPercent(
|
||||
xPercentage = seekProgressPercent.coerceIn(0f, 1f),
|
||||
).padding(bottom = controllerHeight - titleHeight - subtitleHeight),
|
||||
previewImageUrl = imageUrl,
|
||||
duration = playerControls.duration,
|
||||
seekProgressMs = seekProgressMs,
|
||||
videoWidth = trickplayInfo.width,
|
||||
videoHeight = trickplayInfo.height,
|
||||
trickPlayInfo = trickplayInfo,
|
||||
)
|
||||
AnimatedVisibility(
|
||||
seekProgressPercent >= 0 && seekBarFocused,
|
||||
) {
|
||||
Box(
|
||||
modifier =
|
||||
Modifier
|
||||
.align(Alignment.Center)
|
||||
.fillMaxWidth(.95f),
|
||||
) {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
modifier =
|
||||
Modifier
|
||||
.align(Alignment.BottomStart)
|
||||
.offsetByPercent(
|
||||
xPercentage = seekProgressPercent.coerceIn(0f, 1f),
|
||||
).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,
|
||||
duration = playerControls.duration,
|
||||
seekProgressMs = seekProgressMs,
|
||||
videoWidth = trickplayInfo.width,
|
||||
videoHeight = trickplayInfo.height,
|
||||
trickPlayInfo = trickplayInfo,
|
||||
)
|
||||
}
|
||||
}
|
||||
Text(
|
||||
text = (seekProgressMs / 1000L).seconds.toString(),
|
||||
color = MaterialTheme.colorScheme.onSurface,
|
||||
style = MaterialTheme.typography.labelLarge,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,12 +2,9 @@ package com.github.damontecres.wholphin.ui.playback
|
|||
|
||||
import androidx.compose.foundation.background
|
||||
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.width
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
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.unit.dp
|
||||
import androidx.tv.material3.MaterialTheme
|
||||
import androidx.tv.material3.Text
|
||||
import coil3.compose.AsyncImage
|
||||
import coil3.request.CachePolicy
|
||||
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.isNotNullOrBlank
|
||||
import org.jellyfin.sdk.model.api.TrickplayInfo
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
|
||||
fun Modifier.offsetByPercent(
|
||||
xPercentage: Float,
|
||||
|
|
@ -85,55 +80,44 @@ fun SeekPreviewImage(
|
|||
) {
|
||||
val context = LocalContext.current
|
||||
|
||||
Column(
|
||||
modifier = modifier,
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
if (previewImageUrl.isNotNullOrBlank() &&
|
||||
videoWidth != null &&
|
||||
videoHeight != null
|
||||
) {
|
||||
if (previewImageUrl.isNotNullOrBlank() &&
|
||||
videoWidth != null &&
|
||||
videoHeight != null
|
||||
) {
|
||||
val height = 160.dp
|
||||
val width = height * (videoWidth.toFloat() / videoHeight)
|
||||
val heightPx = with(LocalDensity.current) { height.toPx().toInt() }
|
||||
val widthPx = with(LocalDensity.current) { width.toPx().toInt() }
|
||||
val height = 160.dp
|
||||
val width = height * (videoWidth.toFloat() / videoHeight)
|
||||
val heightPx = with(LocalDensity.current) { height.toPx().toInt() }
|
||||
val widthPx = with(LocalDensity.current) { width.toPx().toInt() }
|
||||
|
||||
val index = (seekProgressMs.toDouble() / trickPlayInfo.interval).toInt() // Which tile
|
||||
val numberOfTitlesPerImage = trickPlayInfo.tileHeight * trickPlayInfo.tileWidth
|
||||
val imageIndex = index % numberOfTitlesPerImage
|
||||
val index = (seekProgressMs.toDouble() / trickPlayInfo.interval).toInt() // Which tile
|
||||
val numberOfTitlesPerImage = trickPlayInfo.tileHeight * trickPlayInfo.tileWidth
|
||||
val imageIndex = index % numberOfTitlesPerImage
|
||||
|
||||
AsyncImage(
|
||||
modifier =
|
||||
Modifier
|
||||
.width(width)
|
||||
.height(height)
|
||||
.background(Color.Black)
|
||||
.border(1.5.dp, color = MaterialTheme.colorScheme.border),
|
||||
model =
|
||||
ImageRequest
|
||||
.Builder(context)
|
||||
.data(previewImageUrl)
|
||||
.memoryCachePolicy(CachePolicy.ENABLED)
|
||||
.transformations(
|
||||
CoilTrickplayTransformation(
|
||||
widthPx,
|
||||
heightPx,
|
||||
trickPlayInfo.tileHeight,
|
||||
trickPlayInfo.tileWidth,
|
||||
imageIndex,
|
||||
index,
|
||||
),
|
||||
).build(),
|
||||
contentScale = ContentScale.None,
|
||||
contentDescription = null,
|
||||
placeholder = placeHolder,
|
||||
)
|
||||
}
|
||||
Text(
|
||||
text = (seekProgressMs / 1000L).seconds.toString(),
|
||||
color = MaterialTheme.colorScheme.onSurface,
|
||||
style = MaterialTheme.typography.labelLarge,
|
||||
AsyncImage(
|
||||
modifier =
|
||||
modifier
|
||||
.width(width)
|
||||
.height(height)
|
||||
.background(Color.Black)
|
||||
.border(1.5.dp, color = MaterialTheme.colorScheme.border),
|
||||
model =
|
||||
ImageRequest
|
||||
.Builder(context)
|
||||
.data(previewImageUrl)
|
||||
.memoryCachePolicy(CachePolicy.ENABLED)
|
||||
.transformations(
|
||||
CoilTrickplayTransformation(
|
||||
widthPx,
|
||||
heightPx,
|
||||
trickPlayInfo.tileHeight,
|
||||
trickPlayInfo.tileWidth,
|
||||
imageIndex,
|
||||
index,
|
||||
),
|
||||
).build(),
|
||||
contentScale = ContentScale.None,
|
||||
contentDescription = null,
|
||||
placeholder = placeHolder,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue