diff --git a/app/src/main/java/hu/bbara/purefin/app/content/episode/EpisodeComponents.kt b/app/src/main/java/hu/bbara/purefin/app/content/episode/EpisodeComponents.kt index e3ee450..1db7d8f 100644 --- a/app/src/main/java/hu/bbara/purefin/app/content/episode/EpisodeComponents.kt +++ b/app/src/main/java/hu/bbara/purefin/app/content/episode/EpisodeComponents.kt @@ -33,6 +33,7 @@ import hu.bbara.purefin.common.ui.MediaCastMember import hu.bbara.purefin.common.ui.MediaCastRow import hu.bbara.purefin.common.ui.MediaGhostIconButton import hu.bbara.purefin.common.ui.MediaMetaChip +import hu.bbara.purefin.common.ui.MediaSynopsis import hu.bbara.purefin.common.ui.components.MediaActionButton import hu.bbara.purefin.common.ui.components.MediaPlayButton import hu.bbara.purefin.common.ui.components.MediaPlaybackSettings @@ -105,18 +106,8 @@ internal fun EpisodeDetails( } Spacer(modifier = Modifier.height(24.dp)) - Text( - text = "Synopsis", - color = scheme.onBackground, - fontSize = 18.sp, - fontWeight = FontWeight.Bold - ) - Spacer(modifier = Modifier.height(12.dp)) - Text( - text = episode.synopsis, - color = scheme.onSurfaceVariant, - fontSize = 15.sp, - lineHeight = 22.sp + MediaSynopsis( + synopsis = episode.synopsis ) Spacer(modifier = Modifier.height(24.dp)) diff --git a/app/src/main/java/hu/bbara/purefin/app/content/movie/MovieComponents.kt b/app/src/main/java/hu/bbara/purefin/app/content/movie/MovieComponents.kt index 07bb5df..a8686fb 100644 --- a/app/src/main/java/hu/bbara/purefin/app/content/movie/MovieComponents.kt +++ b/app/src/main/java/hu/bbara/purefin/app/content/movie/MovieComponents.kt @@ -33,6 +33,7 @@ import hu.bbara.purefin.common.ui.MediaCastMember import hu.bbara.purefin.common.ui.MediaCastRow import hu.bbara.purefin.common.ui.MediaGhostIconButton import hu.bbara.purefin.common.ui.MediaMetaChip +import hu.bbara.purefin.common.ui.MediaSynopsis import hu.bbara.purefin.common.ui.components.MediaActionButton import hu.bbara.purefin.common.ui.components.MediaPlayButton import hu.bbara.purefin.common.ui.components.MediaPlaybackSettings @@ -106,18 +107,8 @@ internal fun MovieDetails( } Spacer(modifier = Modifier.height(24.dp)) - Text( - text = "Synopsis", - color = scheme.onBackground, - fontSize = 18.sp, - fontWeight = FontWeight.Bold - ) - Spacer(modifier = Modifier.height(12.dp)) - Text( - text = movie.synopsis, - color = scheme.onSurfaceVariant, - fontSize = 15.sp, - lineHeight = 22.sp + MediaSynopsis( + synopsis = movie.synopsis ) Spacer(modifier = Modifier.height(24.dp)) diff --git a/app/src/main/java/hu/bbara/purefin/app/content/series/SeriesScreen.kt b/app/src/main/java/hu/bbara/purefin/app/content/series/SeriesScreen.kt index c695d93..12ba41f 100644 --- a/app/src/main/java/hu/bbara/purefin/app/content/series/SeriesScreen.kt +++ b/app/src/main/java/hu/bbara/purefin/app/content/series/SeriesScreen.kt @@ -22,6 +22,7 @@ import androidx.compose.ui.unit.sp import androidx.hilt.navigation.compose.hiltViewModel import hu.bbara.purefin.app.content.ContentMockData import hu.bbara.purefin.common.ui.PurefinWaitingScreen +import hu.bbara.purefin.common.ui.MediaSynopsis import hu.bbara.purefin.common.ui.components.MediaHero import hu.bbara.purefin.navigation.ItemDto @@ -96,17 +97,12 @@ private fun SeriesScreenInternal( Spacer(modifier = Modifier.height(24.dp)) SeriesActionButtons() Spacer(modifier = Modifier.height(24.dp)) - Text( - text = "Synopsis", - color = scheme.onBackground, - fontSize = 18.sp, - fontWeight = FontWeight.Bold - ) - Spacer(modifier = Modifier.height(8.dp)) - Text( - text = series.synopsis, - color = textMutedStrong, - fontSize = 13.sp, + MediaSynopsis( + synopsis = series.synopsis, + bodyColor = textMutedStrong, + bodyFontSize = 13.sp, + bodyLineHeight = null, + titleSpacing = 8.dp ) Spacer(modifier = Modifier.height(28.dp)) Text( diff --git a/app/src/main/java/hu/bbara/purefin/common/ui/MediaSynopsis.kt b/app/src/main/java/hu/bbara/purefin/common/ui/MediaSynopsis.kt new file mode 100644 index 0000000..729931d --- /dev/null +++ b/app/src/main/java/hu/bbara/purefin/common/ui/MediaSynopsis.kt @@ -0,0 +1,75 @@ +package hu.bbara.purefin.common.ui + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.height +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.semantics.Role +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.TextUnit +import androidx.compose.ui.unit.TextUnit.Companion.Unspecified +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp + +@Composable +fun MediaSynopsis( + synopsis: String, + modifier: Modifier = Modifier, + title: String = "Synopsis", + titleColor: Color = MaterialTheme.colorScheme.onBackground, + bodyColor: Color = MaterialTheme.colorScheme.onSurfaceVariant, + titleFontSize: TextUnit = 18.sp, + bodyFontSize: TextUnit = 15.sp, + bodyLineHeight: TextUnit? = 22.sp, + titleSpacing: Dp = 12.dp, + collapsedLines: Int = 3, + collapseInitially: Boolean = true +) { + var isExpanded by remember(synopsis) { mutableStateOf(!collapseInitially) } + var isOverflowing by remember(synopsis) { mutableStateOf(false) } + + val containerModifier = if (isOverflowing) { + modifier.clickable(role = Role.Button) { isExpanded = !isExpanded } + } else { + modifier + } + + Column(modifier = containerModifier) { + Text( + text = title, + color = titleColor, + fontSize = titleFontSize, + fontWeight = FontWeight.Bold + ) + Spacer(modifier = Modifier.height(titleSpacing)) + Text( + text = synopsis, + color = bodyColor, + fontSize = bodyFontSize, + lineHeight = bodyLineHeight ?: Unspecified, + maxLines = if (isExpanded) Int.MAX_VALUE else collapsedLines, + overflow = if (isExpanded) TextOverflow.Clip else TextOverflow.Ellipsis, + onTextLayout = { result -> + val overflowed = if (isExpanded) { + result.lineCount > collapsedLines + } else { + result.hasVisualOverflow || result.lineCount > collapsedLines + } + if (overflowed != isOverflowing) { + isOverflowing = overflowed + } + } + ) + } +}