mirror of
https://github.com/bbara04/Purefin.git
synced 2026-03-31 17:10:08 +02:00
implement reusable MediaSynopsis component
- Create `MediaSynopsis` as a common UI component with support for expandable text, custom styling, and overflow detection. - Refactor `EpisodeComponents`, `MovieComponents`, and `SeriesScreen` to use the new `MediaSynopsis` component. - Standardize the synopsis layout across different media detail screens.
This commit is contained in:
@@ -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))
|
||||
|
||||
|
||||
@@ -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))
|
||||
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user