From ead2431bc4fea5dd5fc4f905c1d44727cc0cad94 Mon Sep 17 00:00:00 2001 From: Damontecres Date: Mon, 6 Oct 2025 14:26:26 -0400 Subject: [PATCH] Better formatting --- .../damontecres/dolphin/ui/cards/ItemCard.kt | 5 ++-- .../dolphin/ui/detail/EpisodeDetails.kt | 5 ++-- .../ui/detail/series/FocusedEpisodeHeader.kt | 5 ++-- .../dolphin/ui/playback/NextUpEpisode.kt | 26 ++++++++++++------- .../dolphin/ui/playback/PlaybackContent.kt | 11 +++++--- .../dolphin/ui/playback/PlaybackViewModel.kt | 8 ++---- .../damontecres/dolphin/util/Formatting.kt | 20 ++++++++++++++ 7 files changed, 54 insertions(+), 26 deletions(-) diff --git a/app/src/main/java/com/github/damontecres/dolphin/ui/cards/ItemCard.kt b/app/src/main/java/com/github/damontecres/dolphin/ui/cards/ItemCard.kt index 4bdfc806..f4b63126 100644 --- a/app/src/main/java/com/github/damontecres/dolphin/ui/cards/ItemCard.kt +++ b/app/src/main/java/com/github/damontecres/dolphin/ui/cards/ItemCard.kt @@ -47,6 +47,7 @@ import com.github.damontecres.dolphin.data.model.BaseItem import com.github.damontecres.dolphin.ui.FontAwesome import com.github.damontecres.dolphin.ui.enableMarquee import com.github.damontecres.dolphin.ui.ifElse +import com.github.damontecres.dolphin.util.seasonEpisode import kotlinx.coroutines.delay import org.jellyfin.sdk.model.api.BaseItemKind @@ -138,9 +139,9 @@ fun ItemCard( ) } if (dto.type == BaseItemKind.EPISODE) { - if (dto.parentIndexNumber != null && dto.indexNumber != null) { + dto.seasonEpisode?.let { Text( - text = "S${dto.parentIndexNumber} E${dto.indexNumber}", + text = it, ) } } diff --git a/app/src/main/java/com/github/damontecres/dolphin/ui/detail/EpisodeDetails.kt b/app/src/main/java/com/github/damontecres/dolphin/ui/detail/EpisodeDetails.kt index 8b326519..b4bbf9f8 100644 --- a/app/src/main/java/com/github/damontecres/dolphin/ui/detail/EpisodeDetails.kt +++ b/app/src/main/java/com/github/damontecres/dolphin/ui/detail/EpisodeDetails.kt @@ -35,6 +35,7 @@ import com.github.damontecres.dolphin.ui.isNotNullOrBlank import com.github.damontecres.dolphin.ui.nav.Destination import com.github.damontecres.dolphin.ui.nav.NavigationManager import com.github.damontecres.dolphin.util.LoadingState +import com.github.damontecres.dolphin.util.seasonEpisode import dagger.hilt.android.lifecycle.HiltViewModel import org.jellyfin.sdk.api.client.ApiClient import org.jellyfin.sdk.model.api.ImageType @@ -100,9 +101,7 @@ fun EpisodeDetailsContent( val details = buildList { - if (dto.parentIndexNumber != null && dto.indexNumber != null) { - add("S${dto.parentIndexNumber} E${dto.indexNumber}") - } + dto.seasonEpisode?.let(::add) dto.mediaSources?.firstOrNull()?.runTimeTicks?.ticks?.inWholeMinutes?.toString()?.let { add(it) } diff --git a/app/src/main/java/com/github/damontecres/dolphin/ui/detail/series/FocusedEpisodeHeader.kt b/app/src/main/java/com/github/damontecres/dolphin/ui/detail/series/FocusedEpisodeHeader.kt index b334cf61..fa3e2433 100644 --- a/app/src/main/java/com/github/damontecres/dolphin/ui/detail/series/FocusedEpisodeHeader.kt +++ b/app/src/main/java/com/github/damontecres/dolphin/ui/detail/series/FocusedEpisodeHeader.kt @@ -32,6 +32,7 @@ import com.github.damontecres.dolphin.ui.playSoundOnFocus import com.github.damontecres.dolphin.ui.roundMinutes import com.github.damontecres.dolphin.ui.timeRemaining import com.github.damontecres.dolphin.util.formatDateTime +import com.github.damontecres.dolphin.util.seasonEpisode import org.jellyfin.sdk.model.extensions.ticks @Composable @@ -56,9 +57,7 @@ fun FocusedEpisodeHeader( ) { val details = buildList { - if (dto.parentIndexNumber != null && dto.indexNumber != null) { - add("S${dto.parentIndexNumber} E${dto.indexNumber}") - } + dto.seasonEpisode?.let(::add) dto.premiereDate?.let { add(formatDateTime(it)) } val duration = dto.runTimeTicks?.ticks duration diff --git a/app/src/main/java/com/github/damontecres/dolphin/ui/playback/NextUpEpisode.kt b/app/src/main/java/com/github/damontecres/dolphin/ui/playback/NextUpEpisode.kt index 0178e517..082f1449 100644 --- a/app/src/main/java/com/github/damontecres/dolphin/ui/playback/NextUpEpisode.kt +++ b/app/src/main/java/com/github/damontecres/dolphin/ui/playback/NextUpEpisode.kt @@ -1,6 +1,7 @@ package com.github.damontecres.dolphin.ui.playback import androidx.compose.foundation.background +import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -50,6 +51,7 @@ fun NextUpEpisode( modifier: Modifier = Modifier, aspectRatio: Float = 16f / 9, ) { + val interactionSource = remember { MutableInteractionSource() } val focusRequester = remember { FocusRequester() } LaunchedEffect(Unit) { focusRequester.tryRequestFocus() } Box( @@ -60,11 +62,11 @@ fun NextUpEpisode( modifier = Modifier .fillMaxSize() - .padding(8.dp), + .padding(horizontal = 16.dp, vertical = 8.dp), ) { Text( text = "Up Next...", - style = MaterialTheme.typography.titleSmall, + style = MaterialTheme.typography.titleLarge, color = MaterialTheme.colorScheme.onSurface, textAlign = TextAlign.Center, modifier = Modifier.fillMaxWidth(), @@ -78,19 +80,23 @@ fun NextUpEpisode( imageUrl = imageUrl, onClick = onClick, timeLeft = timeLeft, + interactionSource = interactionSource, modifier = Modifier - .fillMaxWidth(.4f) - .fillMaxHeight() +// .fillMaxWidth(.4f) +// .fillMaxHeight() .focusRequester(focusRequester), ) Column( verticalArrangement = Arrangement.spacedBy(8.dp), - modifier = Modifier.fillMaxHeight(), + modifier = + Modifier + .fillMaxHeight() + .weight(1f), ) { Text( text = title ?: "", - style = MaterialTheme.typography.bodyMedium, + style = MaterialTheme.typography.titleMedium, color = MaterialTheme.colorScheme.onSurface, maxLines = 1, overflow = TextOverflow.Ellipsis, @@ -98,7 +104,7 @@ fun NextUpEpisode( ) Text( text = description ?: "", - style = MaterialTheme.typography.bodySmall, + style = MaterialTheme.typography.bodyMedium, color = MaterialTheme.colorScheme.onSurface, overflow = TextOverflow.Ellipsis, modifier = Modifier, @@ -114,18 +120,20 @@ fun NextUpCard( imageUrl: String?, onClick: () -> Unit, timeLeft: Duration?, + interactionSource: MutableInteractionSource, modifier: Modifier = Modifier, ) { Card( modifier = modifier, onClick = onClick, + interactionSource = interactionSource, ) { - Box(modifier = Modifier.fillMaxSize()) { + Box(modifier = Modifier) { AsyncImage( model = imageUrl, contentDescription = null, contentScale = ContentScale.Fit, - modifier = Modifier.fillMaxSize(), + modifier = Modifier, ) if (timeLeft != null && timeLeft > Duration.ZERO) { Box( diff --git a/app/src/main/java/com/github/damontecres/dolphin/ui/playback/PlaybackContent.kt b/app/src/main/java/com/github/damontecres/dolphin/ui/playback/PlaybackContent.kt index acb67742..ede7409a 100644 --- a/app/src/main/java/com/github/damontecres/dolphin/ui/playback/PlaybackContent.kt +++ b/app/src/main/java/com/github/damontecres/dolphin/ui/playback/PlaybackContent.kt @@ -62,6 +62,7 @@ import com.github.damontecres.dolphin.ui.components.LoadingPage import com.github.damontecres.dolphin.ui.nav.Destination import com.github.damontecres.dolphin.ui.nav.NavigationManager import com.github.damontecres.dolphin.ui.tryRequestFocus +import com.github.damontecres.dolphin.util.seasonEpisode import kotlinx.coroutines.delay import org.jellyfin.sdk.model.api.DeviceProfile import kotlin.time.Duration.Companion.milliseconds @@ -356,7 +357,11 @@ fun PlaybackContent( } } NextUpEpisode( - title = it.name, + title = + listOfNotNull( + it.data.seasonEpisode, + it.name, + ).joinToString(" - "), description = it.data.overview, imageUrl = it.imageUrl, aspectRatio = it.data.primaryImageAspectRatio?.toFloat() ?: (16f / 9), @@ -366,8 +371,8 @@ fun PlaybackContent( Modifier .padding(8.dp) // .height(128.dp) - .fillMaxHeight(.3f) - .fillMaxWidth(.5f) + .fillMaxHeight(.5f) + .fillMaxWidth(.66f) .align(Alignment.BottomCenter) .background( MaterialTheme.colorScheme.surfaceColorAtElevation(2.dp), diff --git a/app/src/main/java/com/github/damontecres/dolphin/ui/playback/PlaybackViewModel.kt b/app/src/main/java/com/github/damontecres/dolphin/ui/playback/PlaybackViewModel.kt index 5571dd10..d7cbddef 100644 --- a/app/src/main/java/com/github/damontecres/dolphin/ui/playback/PlaybackViewModel.kt +++ b/app/src/main/java/com/github/damontecres/dolphin/ui/playback/PlaybackViewModel.kt @@ -26,6 +26,7 @@ import com.github.damontecres.dolphin.util.TrackActivityPlaybackListener import com.github.damontecres.dolphin.util.TrackSupport import com.github.damontecres.dolphin.util.checkForSupport import com.github.damontecres.dolphin.util.formatDateTime +import com.github.damontecres.dolphin.util.seasonEpisodePadded import com.github.damontecres.dolphin.util.subtitleMimeTypes import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.qualifiers.ApplicationContext @@ -126,13 +127,8 @@ class PlaybackViewModel } val subtitle = if (base.type == BaseItemKind.EPISODE) { - val season = base.parentIndexNumber?.toString()?.padStart(2, '0') - val episode = base.indexNumber?.toString()?.padStart(2, '0') - // TODO multi episode support buildList { - if (season != null && episode != null) { - add("S${season}E$episode") - } + add(base.seasonEpisodePadded) add(base.name) add(base.premiereDate?.let { formatDateTime(it) }) }.filterNotNull().joinToString(" - ") diff --git a/app/src/main/java/com/github/damontecres/dolphin/util/Formatting.kt b/app/src/main/java/com/github/damontecres/dolphin/util/Formatting.kt index 205aefd0..f6064ee9 100644 --- a/app/src/main/java/com/github/damontecres/dolphin/util/Formatting.kt +++ b/app/src/main/java/com/github/damontecres/dolphin/util/Formatting.kt @@ -1,6 +1,7 @@ package com.github.damontecres.dolphin.util import android.os.Build +import org.jellyfin.sdk.model.api.BaseItemDto import java.time.LocalDateTime import java.time.format.DateTimeFormatter @@ -13,3 +14,22 @@ fun formatDateTime(dateTime: LocalDateTime): String = } else { dateTime.toString() } + +// TODO multi episode support +val BaseItemDto.seasonEpisode: String? + get() = + if (parentIndexNumber != null && indexNumber != null) { + "S$parentIndexNumber E$indexNumber" + } else { + null + } + +val BaseItemDto.seasonEpisodePadded: String? + get() = + if (parentIndexNumber != null && indexNumber != null) { + val season = parentIndexNumber?.toString()?.padStart(2, '0') + val episode = indexNumber?.toString()?.padStart(2, '0') + "S${season}E$episode" + } else { + null + }