diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/playback/NextUpEpisode.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/playback/NextUpEpisode.kt index f032c8b7..d93ffda6 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/playback/NextUpEpisode.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/playback/NextUpEpisode.kt @@ -10,10 +10,8 @@ import androidx.compose.foundation.layout.aspectRatio import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons @@ -21,6 +19,7 @@ import androidx.compose.material.icons.filled.PlayArrow import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -29,7 +28,10 @@ import androidx.compose.ui.focus.focusRequester import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.toArgb import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalResources import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp @@ -47,10 +49,17 @@ import com.github.damontecres.wholphin.R import com.github.damontecres.wholphin.ui.AppColors import com.github.damontecres.wholphin.ui.AspectRatios import com.github.damontecres.wholphin.ui.PreviewTvSpec +import com.github.damontecres.wholphin.ui.dot +import com.github.damontecres.wholphin.ui.formatDuration +import com.github.damontecres.wholphin.ui.formatTime import com.github.damontecres.wholphin.ui.theme.WholphinTheme import com.github.damontecres.wholphin.ui.tryRequestFocus +import com.github.damontecres.wholphin.ui.util.Clock +import com.github.damontecres.wholphin.ui.util.LocalClock import kotlin.time.Duration +import kotlin.time.Duration.Companion.minutes import kotlin.time.Duration.Companion.seconds +import kotlin.time.toJavaDuration /** * Layout for showing the next up episode during playback @@ -64,6 +73,7 @@ fun NextUpEpisode( timeLeft: Duration?, modifier: Modifier = Modifier, aspectRatio: Float = AspectRatios.WIDE, + runtime: Duration? = null, ) { val interactionSource = remember { MutableInteractionSource() } val focusRequester = remember { FocusRequester() } @@ -122,9 +132,36 @@ fun NextUpEpisode( text = description ?: "", style = MaterialTheme.typography.bodyMedium, color = MaterialTheme.colorScheme.onSurface, + maxLines = 4, overflow = TextOverflow.Ellipsis, modifier = Modifier, ) + runtime?.let { + val context = LocalContext.current + val resources = LocalResources.current + val now by LocalClock.current.now + val text = + remember(now, runtime) { + buildAnnotatedString { + append(resources.formatDuration(runtime)) + dot() + val endsAt = now.plus(runtime.toJavaDuration()) + val endTimeStr = formatTime(context, endsAt) + append(resources.getString(R.string.ends_at, endTimeStr)) + } + } + Text( + text = text, + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.onSurface, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + modifier = + Modifier + .padding(top = 4.dp) + .align(Alignment.Start), + ) + } } } } @@ -189,34 +226,41 @@ fun NextUpCard( @Composable private fun NextUpEpisodePreview() { WholphinTheme(true) { + val theme = MaterialTheme.colorScheme val previewHandler = AsyncImagePreviewHandler { - ColorImage(Color.Blue.toArgb()) + ColorImage(theme.surfaceVariant.toArgb()) + } + Box( + modifier = Modifier.fillMaxSize().background(Color.Black), + ) { + CompositionLocalProvider( + LocalAsyncImagePreviewHandler provides previewHandler, + LocalClock provides Clock(), + ) { + NextUpEpisode( + title = "Episode Title", + description = + "This is the description of the episode. It might be long. " + + "It might be very, very long and overflow the available space. " + + "But it just keeps going and going.", + imageUrl = "", + onClick = {}, + aspectRatio = AspectRatios.WIDE, + timeLeft = 30.seconds, + runtime = 32.minutes + 20.seconds, + modifier = + Modifier + .padding(8.dp) + .fillMaxHeight(.4f) + .fillMaxWidth(.66f) + .align(Alignment.BottomCenter) + .background( + MaterialTheme.colorScheme.surfaceColorAtElevation(2.dp), + shape = RoundedCornerShape(8.dp), + ), + ) } - - CompositionLocalProvider(LocalAsyncImagePreviewHandler provides previewHandler) { - NextUpEpisode( - title = "Episode Title", - description = - "This is the description of the episode. It might be long. " + - "It might be very, very long and overflow the available space. " + - "But it just keeps going and going.", - imageUrl = "", - onClick = {}, - aspectRatio = AspectRatios.FOUR_THREE, - timeLeft = 30.seconds, - modifier = - Modifier - .padding(16.dp) - .height(200.dp) - .width(400.dp) -// .fillMaxWidth(.4f) -// .align(Alignment.BottomCenter) - .background( - MaterialTheme.colorScheme.surfaceColorAtElevation(2.dp), - shape = RoundedCornerShape(8.dp), - ), - ) } } } diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/playback/PlaybackPage.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/playback/PlaybackPage.kt index 6e64be5b..6d22cd10 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/playback/PlaybackPage.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/playback/PlaybackPage.kt @@ -94,6 +94,7 @@ import com.github.damontecres.wholphin.util.Media3SubtitleOverride import io.github.peerless2012.ass.media.widget.AssSubtitleView import kotlinx.coroutines.delay import kotlinx.coroutines.launch +import org.jellyfin.sdk.model.extensions.ticks import timber.log.Timber import kotlin.time.Duration import kotlin.time.Duration.Companion.milliseconds @@ -600,6 +601,7 @@ fun PlaybackPageContent( viewModel.playNextUp() }, timeLeft = if (autoPlayEnabled) timeLeft.seconds else null, + runtime = it.data.runTimeTicks?.ticks, modifier = Modifier .padding(8.dp)