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.MediaCastRow
|
||||||
import hu.bbara.purefin.common.ui.MediaGhostIconButton
|
import hu.bbara.purefin.common.ui.MediaGhostIconButton
|
||||||
import hu.bbara.purefin.common.ui.MediaMetaChip
|
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.MediaActionButton
|
||||||
import hu.bbara.purefin.common.ui.components.MediaPlayButton
|
import hu.bbara.purefin.common.ui.components.MediaPlayButton
|
||||||
import hu.bbara.purefin.common.ui.components.MediaPlaybackSettings
|
import hu.bbara.purefin.common.ui.components.MediaPlaybackSettings
|
||||||
@@ -105,18 +106,8 @@ internal fun EpisodeDetails(
|
|||||||
}
|
}
|
||||||
Spacer(modifier = Modifier.height(24.dp))
|
Spacer(modifier = Modifier.height(24.dp))
|
||||||
|
|
||||||
Text(
|
MediaSynopsis(
|
||||||
text = "Synopsis",
|
synopsis = episode.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
|
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.height(24.dp))
|
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.MediaCastRow
|
||||||
import hu.bbara.purefin.common.ui.MediaGhostIconButton
|
import hu.bbara.purefin.common.ui.MediaGhostIconButton
|
||||||
import hu.bbara.purefin.common.ui.MediaMetaChip
|
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.MediaActionButton
|
||||||
import hu.bbara.purefin.common.ui.components.MediaPlayButton
|
import hu.bbara.purefin.common.ui.components.MediaPlayButton
|
||||||
import hu.bbara.purefin.common.ui.components.MediaPlaybackSettings
|
import hu.bbara.purefin.common.ui.components.MediaPlaybackSettings
|
||||||
@@ -106,18 +107,8 @@ internal fun MovieDetails(
|
|||||||
}
|
}
|
||||||
Spacer(modifier = Modifier.height(24.dp))
|
Spacer(modifier = Modifier.height(24.dp))
|
||||||
|
|
||||||
Text(
|
MediaSynopsis(
|
||||||
text = "Synopsis",
|
synopsis = movie.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
|
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.height(24.dp))
|
Spacer(modifier = Modifier.height(24.dp))
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import androidx.compose.ui.unit.sp
|
|||||||
import androidx.hilt.navigation.compose.hiltViewModel
|
import androidx.hilt.navigation.compose.hiltViewModel
|
||||||
import hu.bbara.purefin.app.content.ContentMockData
|
import hu.bbara.purefin.app.content.ContentMockData
|
||||||
import hu.bbara.purefin.common.ui.PurefinWaitingScreen
|
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.common.ui.components.MediaHero
|
||||||
import hu.bbara.purefin.navigation.ItemDto
|
import hu.bbara.purefin.navigation.ItemDto
|
||||||
|
|
||||||
@@ -96,17 +97,12 @@ private fun SeriesScreenInternal(
|
|||||||
Spacer(modifier = Modifier.height(24.dp))
|
Spacer(modifier = Modifier.height(24.dp))
|
||||||
SeriesActionButtons()
|
SeriesActionButtons()
|
||||||
Spacer(modifier = Modifier.height(24.dp))
|
Spacer(modifier = Modifier.height(24.dp))
|
||||||
Text(
|
MediaSynopsis(
|
||||||
text = "Synopsis",
|
synopsis = series.synopsis,
|
||||||
color = scheme.onBackground,
|
bodyColor = textMutedStrong,
|
||||||
fontSize = 18.sp,
|
bodyFontSize = 13.sp,
|
||||||
fontWeight = FontWeight.Bold
|
bodyLineHeight = null,
|
||||||
)
|
titleSpacing = 8.dp
|
||||||
Spacer(modifier = Modifier.height(8.dp))
|
|
||||||
Text(
|
|
||||||
text = series.synopsis,
|
|
||||||
color = textMutedStrong,
|
|
||||||
fontSize = 13.sp,
|
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.height(28.dp))
|
Spacer(modifier = Modifier.height(28.dp))
|
||||||
Text(
|
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