From 07dabee8b9edb265f648e51ff04809c6dbcedb3e Mon Sep 17 00:00:00 2001 From: Damontecres Date: Mon, 13 Oct 2025 14:33:12 -0400 Subject: [PATCH] Reuse overview text composable --- .../dolphin/ui/components/OverviewText.kt | 69 +++++++++++++++++++ .../dolphin/ui/detail/SeriesDetails.kt | 50 ++------------ .../ui/detail/movie/MovieDetailsHeader.kt | 52 +++----------- .../ui/detail/series/FocusedEpisodeHeader.kt | 55 ++------------- 4 files changed, 91 insertions(+), 135 deletions(-) create mode 100644 app/src/main/java/com/github/damontecres/dolphin/ui/components/OverviewText.kt diff --git a/app/src/main/java/com/github/damontecres/dolphin/ui/components/OverviewText.kt b/app/src/main/java/com/github/damontecres/dolphin/ui/components/OverviewText.kt new file mode 100644 index 00000000..c14e916e --- /dev/null +++ b/app/src/main/java/com/github/damontecres/dolphin/ui/components/OverviewText.kt @@ -0,0 +1,69 @@ +package com.github.damontecres.dolphin.ui.components + +import androidx.compose.foundation.LocalIndication +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.interaction.collectIsFocusedAsState +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.times +import androidx.tv.material3.MaterialTheme +import androidx.tv.material3.Text +import com.github.damontecres.dolphin.ui.playOnClickSound +import com.github.damontecres.dolphin.ui.playSoundOnFocus + +@Composable +fun OverviewText( + overview: String, + maxLines: Int, + onClick: () -> Unit, + modifier: Modifier = Modifier, + interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, + textBoxHeight: Dp = maxLines * 20.dp, +) { + val context = LocalContext.current + val isFocused = interactionSource.collectIsFocusedAsState().value + val bgColor = + if (isFocused) { + MaterialTheme.colorScheme.onPrimary.copy(alpha = .4f) + } else { + Color.Unspecified + } + Box( + modifier = + modifier + .background(bgColor, shape = RoundedCornerShape(8.dp)) + .playSoundOnFocus(true) + .clickable( + enabled = true, + interactionSource = interactionSource, + indication = LocalIndication.current, + ) { + playOnClickSound(context) + onClick.invoke() + }, + ) { + Text( + text = overview, + style = MaterialTheme.typography.bodyMedium, + color = MaterialTheme.colorScheme.onSurface, + maxLines = maxLines, + overflow = TextOverflow.Ellipsis, + modifier = + Modifier + .padding(8.dp) + .height(textBoxHeight), + ) + } +} diff --git a/app/src/main/java/com/github/damontecres/dolphin/ui/detail/SeriesDetails.kt b/app/src/main/java/com/github/damontecres/dolphin/ui/detail/SeriesDetails.kt index 8f492df1..1aa5c8bb 100644 --- a/app/src/main/java/com/github/damontecres/dolphin/ui/detail/SeriesDetails.kt +++ b/app/src/main/java/com/github/damontecres/dolphin/ui/detail/SeriesDetails.kt @@ -1,10 +1,5 @@ package com.github.damontecres.dolphin.ui.detail -import androidx.compose.foundation.LocalIndication -import androidx.compose.foundation.background -import androidx.compose.foundation.clickable -import androidx.compose.foundation.interaction.MutableInteractionSource -import androidx.compose.foundation.interaction.collectIsFocusedAsState import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -18,7 +13,6 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.relocation.BringIntoViewRequester import androidx.compose.foundation.relocation.bringIntoViewRequester -import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.PlayArrow import androidx.compose.runtime.Composable @@ -38,7 +32,6 @@ import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel @@ -62,6 +55,7 @@ import com.github.damontecres.dolphin.ui.components.ErrorMessage import com.github.damontecres.dolphin.ui.components.ExpandableFaButton import com.github.damontecres.dolphin.ui.components.ExpandablePlayButton import com.github.damontecres.dolphin.ui.components.LoadingPage +import com.github.damontecres.dolphin.ui.components.OverviewText import com.github.damontecres.dolphin.ui.components.StarRating import com.github.damontecres.dolphin.ui.components.StarRatingPrecision import com.github.damontecres.dolphin.ui.data.ItemDetailsDialog @@ -71,8 +65,6 @@ import com.github.damontecres.dolphin.ui.ifElse import com.github.damontecres.dolphin.ui.isNotNullOrBlank import com.github.damontecres.dolphin.ui.letNotEmpty import com.github.damontecres.dolphin.ui.nav.Destination -import com.github.damontecres.dolphin.ui.playOnClickSound -import com.github.damontecres.dolphin.ui.playSoundOnFocus import com.github.damontecres.dolphin.ui.rememberPosition import com.github.damontecres.dolphin.ui.roundMinutes import com.github.damontecres.dolphin.ui.tryRequestFocus @@ -362,40 +354,12 @@ fun SeriesDetailsHeader( } dto.overview?.let { overview -> - val interactionSource = remember { MutableInteractionSource() } - val isFocused = interactionSource.collectIsFocusedAsState().value - val bgColor = - if (isFocused) { - MaterialTheme.colorScheme.onPrimary.copy(alpha = .4f) - } else { - Color.Unspecified - } - Box( - modifier = - Modifier - .background(bgColor, shape = RoundedCornerShape(8.dp)) - .playSoundOnFocus(true) - .clickable( - enabled = true, - interactionSource = interactionSource, - indication = LocalIndication.current, - ) { - playOnClickSound(context) - overviewOnClick.invoke() - }, - ) { - Text( - text = overview, - style = MaterialTheme.typography.bodyMedium, - color = MaterialTheme.colorScheme.onSurface, - maxLines = 3, - overflow = TextOverflow.Ellipsis, - modifier = - Modifier - .padding(8.dp) - .height(60.dp), - ) - } + OverviewText( + overview = overview, + maxLines = 3, + onClick = overviewOnClick, + textBoxHeight = Dp.Unspecified, + ) } Row( horizontalArrangement = Arrangement.spacedBy(16.dp), diff --git a/app/src/main/java/com/github/damontecres/dolphin/ui/detail/movie/MovieDetailsHeader.kt b/app/src/main/java/com/github/damontecres/dolphin/ui/detail/movie/MovieDetailsHeader.kt index 7f636fd9..7d133b7c 100644 --- a/app/src/main/java/com/github/damontecres/dolphin/ui/detail/movie/MovieDetailsHeader.kt +++ b/app/src/main/java/com/github/damontecres/dolphin/ui/detail/movie/MovieDetailsHeader.kt @@ -1,12 +1,6 @@ package com.github.damontecres.dolphin.ui.detail.movie -import androidx.compose.foundation.LocalIndication -import androidx.compose.foundation.background -import androidx.compose.foundation.clickable -import androidx.compose.foundation.interaction.MutableInteractionSource -import androidx.compose.foundation.interaction.collectIsFocusedAsState import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer @@ -15,9 +9,7 @@ import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.widthIn import androidx.compose.foundation.relocation.BringIntoViewRequester -import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.runtime.Composable -import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Modifier import androidx.compose.ui.draw.alpha @@ -27,18 +19,18 @@ import androidx.compose.ui.graphics.Shadow import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.tv.material3.MaterialTheme import androidx.tv.material3.Text import com.github.damontecres.dolphin.R import com.github.damontecres.dolphin.data.model.BaseItem import com.github.damontecres.dolphin.ui.components.DotSeparatedRow +import com.github.damontecres.dolphin.ui.components.OverviewText import com.github.damontecres.dolphin.ui.components.StarRating import com.github.damontecres.dolphin.ui.components.StarRatingPrecision import com.github.damontecres.dolphin.ui.components.TitleValueText import com.github.damontecres.dolphin.ui.isNotNullOrBlank -import com.github.damontecres.dolphin.ui.playOnClickSound -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.formatSubtitleLang @@ -120,40 +112,12 @@ fun MovieDetailsHeader( // Description dto.overview?.let { overview -> - val interactionSource = remember { MutableInteractionSource() } - val isFocused = interactionSource.collectIsFocusedAsState().value - val bgColor = - if (isFocused) { - MaterialTheme.colorScheme.onPrimary.copy(alpha = .4f) - } else { - Color.Unspecified - } - Box( - modifier = - Modifier - .background(bgColor, shape = RoundedCornerShape(8.dp)) - .playSoundOnFocus(true) - .clickable( - enabled = true, - interactionSource = interactionSource, - indication = LocalIndication.current, - ) { - playOnClickSound(context) - overviewOnClick.invoke() - }, - ) { - Text( - text = overview, - style = MaterialTheme.typography.bodyMedium, - color = MaterialTheme.colorScheme.onSurface, - maxLines = 3, - overflow = TextOverflow.Ellipsis, - modifier = - Modifier - .padding(8.dp), -// .height(60.dp), - ) - } + OverviewText( + overview = overview, + maxLines = 3, + onClick = overviewOnClick, + textBoxHeight = Dp.Unspecified, + ) } movie.data.people ?.filter { it.type == PersonKind.DIRECTOR && it.name.isNotNullOrBlank() } 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 be1212ab..59722721 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 @@ -1,23 +1,13 @@ package com.github.damontecres.dolphin.ui.detail.series -import androidx.compose.foundation.LocalIndication -import androidx.compose.foundation.background -import androidx.compose.foundation.clickable -import androidx.compose.foundation.interaction.MutableInteractionSource -import androidx.compose.foundation.interaction.collectIsFocusedAsState import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.runtime.Composable -import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp @@ -25,10 +15,9 @@ import androidx.tv.material3.MaterialTheme import androidx.tv.material3.Text import com.github.damontecres.dolphin.data.model.BaseItem import com.github.damontecres.dolphin.ui.components.DotSeparatedRow +import com.github.damontecres.dolphin.ui.components.OverviewText import com.github.damontecres.dolphin.ui.components.StarRating import com.github.damontecres.dolphin.ui.components.StarRatingPrecision -import com.github.damontecres.dolphin.ui.playOnClickSound -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 @@ -93,42 +82,12 @@ fun FocusedEpisodeHeader( } else { Spacer(Modifier.height(24.dp)) } - } - } - - val interactionSource = remember { MutableInteractionSource() } - val isFocused = interactionSource.collectIsFocusedAsState().value - val bgColor = - if (isFocused) { - MaterialTheme.colorScheme.onPrimary.copy(alpha = .4f) - } else { - Color.Unspecified - } - Box( - modifier = - Modifier - .background(bgColor, shape = RoundedCornerShape(8.dp)) - .playSoundOnFocus(true) - .clickable( - enabled = true, - interactionSource = interactionSource, - indication = LocalIndication.current, - ) { - playOnClickSound(context) - overviewOnClick.invoke() - }, - ) { - Text( - text = dto.overview ?: "", - style = MaterialTheme.typography.bodyMedium, - color = MaterialTheme.colorScheme.onSurface, - maxLines = 3, - overflow = TextOverflow.Ellipsis, - modifier = - Modifier - .padding(8.dp) - .height(60.dp), - ) + } ?: Spacer(Modifier.height(24.dp)) } + OverviewText( + overview = dto.overview ?: "", + maxLines = 3, + onClick = overviewOnClick, + ) } }