mirror of
https://github.com/owenlejeune/TVTime.git
synced 2025-11-19 10:11:13 -05:00
refact detail screen composables
This commit is contained in:
@@ -9,5 +9,6 @@ abstract class DetailedItem(
|
|||||||
@Transient open val overview: String?,
|
@Transient open val overview: String?,
|
||||||
@Transient open val productionCompanies: List<ProductionCompany>,
|
@Transient open val productionCompanies: List<ProductionCompany>,
|
||||||
@Transient open val status: String,
|
@Transient open val status: String,
|
||||||
@Transient open val tagline: String?
|
@Transient open val tagline: String?,
|
||||||
|
@Transient open val voteAverage: Float
|
||||||
): TmdbItem(id, title, posterPath)
|
): TmdbItem(id, title, posterPath)
|
||||||
@@ -12,9 +12,10 @@ class DetailedMovie(
|
|||||||
@SerializedName("production_companies") override val productionCompanies: List<ProductionCompany>,
|
@SerializedName("production_companies") override val productionCompanies: List<ProductionCompany>,
|
||||||
@SerializedName("status") override val status: String,
|
@SerializedName("status") override val status: String,
|
||||||
@SerializedName("tagline") override val tagline: String?,
|
@SerializedName("tagline") override val tagline: String?,
|
||||||
|
@SerializedName("vote_average") override val voteAverage: Float,
|
||||||
@SerializedName("adult") val isAdult: Boolean,
|
@SerializedName("adult") val isAdult: Boolean,
|
||||||
@SerializedName("budget") val budget: Int,
|
@SerializedName("budget") val budget: Int,
|
||||||
@SerializedName("release_date") val releaseDate: String,
|
@SerializedName("release_date") val releaseDate: String,
|
||||||
@SerializedName("revenue") val revenue: Int,
|
@SerializedName("revenue") val revenue: Int,
|
||||||
@SerializedName("runtime") val runtime: Int?
|
@SerializedName("runtime") val runtime: Int?
|
||||||
): DetailedItem(id, title, posterPath, backdropPath, genres, overview, productionCompanies, status, tagline)
|
): DetailedItem(id, title, posterPath, backdropPath, genres, overview, productionCompanies, status, tagline, voteAverage)
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ class DetailedTv(
|
|||||||
@SerializedName("production_companies") override val productionCompanies: List<ProductionCompany>,
|
@SerializedName("production_companies") override val productionCompanies: List<ProductionCompany>,
|
||||||
@SerializedName("status") override val status: String,
|
@SerializedName("status") override val status: String,
|
||||||
@SerializedName("tagline") override val tagline: String?,
|
@SerializedName("tagline") override val tagline: String?,
|
||||||
|
@SerializedName("vote_average") override val voteAverage: Float,
|
||||||
@SerializedName("created_by") val createdBy: List<Person>,
|
@SerializedName("created_by") val createdBy: List<Person>,
|
||||||
@SerializedName("first_air_date") val firstAirDate: String,
|
@SerializedName("first_air_date") val firstAirDate: String,
|
||||||
@SerializedName("in_production") val inProduction: Boolean,
|
@SerializedName("in_production") val inProduction: Boolean,
|
||||||
@@ -19,4 +20,4 @@ class DetailedTv(
|
|||||||
@SerializedName("number_of_episodes") val numberOfEpisodes: Int,
|
@SerializedName("number_of_episodes") val numberOfEpisodes: Int,
|
||||||
@SerializedName("number_of_seasons") val numberOfSeasons: Int,
|
@SerializedName("number_of_seasons") val numberOfSeasons: Int,
|
||||||
@SerializedName("seasons") val seasons: List<Season>
|
@SerializedName("seasons") val seasons: List<Season>
|
||||||
): DetailedItem(id, title, posterPath, backdropPath, genres, overview, productionCompanies, status, tagline)
|
): DetailedItem(id, title, posterPath, backdropPath, genres, overview, productionCompanies, status, tagline, voteAverage)
|
||||||
@@ -10,10 +10,7 @@ import androidx.compose.foundation.shape.RoundedCornerShape
|
|||||||
import androidx.compose.material.Card
|
import androidx.compose.material.Card
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.Search
|
import androidx.compose.material.icons.filled.Search
|
||||||
import androidx.compose.material3.FloatingActionButton
|
import androidx.compose.material3.*
|
||||||
import androidx.compose.material3.Icon
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.MutableState
|
import androidx.compose.runtime.MutableState
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
@@ -23,10 +20,20 @@ import androidx.compose.ui.Modifier
|
|||||||
import androidx.compose.ui.draw.scale
|
import androidx.compose.ui.draw.scale
|
||||||
import androidx.compose.ui.geometry.CornerRadius
|
import androidx.compose.ui.geometry.CornerRadius
|
||||||
import androidx.compose.ui.geometry.Offset
|
import androidx.compose.ui.geometry.Offset
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.input.pointer.pointerInput
|
import androidx.compose.ui.input.pointer.pointerInput
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.platform.LocalDensity
|
import androidx.compose.ui.platform.LocalDensity
|
||||||
|
import androidx.compose.ui.text.TextLayoutResult
|
||||||
|
import androidx.compose.ui.text.TextStyle
|
||||||
|
import androidx.compose.ui.text.font.FontFamily
|
||||||
|
import androidx.compose.ui.text.font.FontStyle
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
import androidx.compose.ui.text.style.TextDecoration
|
||||||
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
|
import androidx.compose.ui.unit.TextUnit
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
|
|
||||||
@@ -155,3 +162,48 @@ fun SearchFab() {
|
|||||||
fun SearchFabPreview() {
|
fun SearchFabPreview() {
|
||||||
SearchFab()
|
SearchFab()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun MinLinesText(
|
||||||
|
text: String,
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
minLines: Int = 1,
|
||||||
|
color: Color = Color.Unspecified,
|
||||||
|
fontSize: TextUnit = TextUnit.Unspecified,
|
||||||
|
fontStyle: FontStyle? = null,
|
||||||
|
fontWeight: FontWeight? = null,
|
||||||
|
fontFamily: FontFamily? = null,
|
||||||
|
letterSpacing: TextUnit = TextUnit.Unspecified,
|
||||||
|
textDecoration: TextDecoration? = null,
|
||||||
|
textAlign: TextAlign? = null,
|
||||||
|
overflow: TextOverflow = TextOverflow.Clip,
|
||||||
|
softWrap: Boolean = true,
|
||||||
|
maxLines: Int = Int.MAX_VALUE,
|
||||||
|
onTextLayout: (TextLayoutResult) -> Unit = {},
|
||||||
|
style: TextStyle = LocalTextStyle.current
|
||||||
|
) {
|
||||||
|
val lineHeight = style.fontSize*4/3
|
||||||
|
|
||||||
|
Text(
|
||||||
|
modifier = modifier
|
||||||
|
.sizeIn(
|
||||||
|
minHeight = with(LocalDensity.current) {
|
||||||
|
(lineHeight * minLines).toDp()
|
||||||
|
}
|
||||||
|
),
|
||||||
|
text = text,
|
||||||
|
color = color,
|
||||||
|
fontSize = fontSize,
|
||||||
|
fontStyle = fontStyle,
|
||||||
|
fontWeight = fontWeight,
|
||||||
|
fontFamily = fontFamily,
|
||||||
|
letterSpacing = letterSpacing,
|
||||||
|
textDecoration = textDecoration,
|
||||||
|
textAlign = textAlign,
|
||||||
|
overflow = overflow,
|
||||||
|
softWrap = softWrap,
|
||||||
|
maxLines = maxLines,
|
||||||
|
onTextLayout = onTextLayout,
|
||||||
|
style = style
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -14,18 +14,13 @@ import androidx.compose.material3.Icon
|
|||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.*
|
||||||
import androidx.compose.runtime.MutableState
|
|
||||||
import androidx.compose.runtime.mutableStateOf
|
|
||||||
import androidx.compose.runtime.remember
|
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Brush
|
import androidx.compose.ui.graphics.Brush
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.platform.LocalDensity
|
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
|
||||||
import androidx.constraintlayout.compose.ConstraintLayout
|
import androidx.constraintlayout.compose.ConstraintLayout
|
||||||
import androidx.navigation.NavController
|
import androidx.navigation.NavController
|
||||||
import coil.compose.rememberImagePainter
|
import coil.compose.rememberImagePainter
|
||||||
@@ -35,11 +30,10 @@ import com.owenlejeune.tvtime.api.tmdb.DetailService
|
|||||||
import com.owenlejeune.tvtime.api.tmdb.MoviesService
|
import com.owenlejeune.tvtime.api.tmdb.MoviesService
|
||||||
import com.owenlejeune.tvtime.api.tmdb.TmdbUtils
|
import com.owenlejeune.tvtime.api.tmdb.TmdbUtils
|
||||||
import com.owenlejeune.tvtime.api.tmdb.TvService
|
import com.owenlejeune.tvtime.api.tmdb.TvService
|
||||||
import com.owenlejeune.tvtime.api.tmdb.model.CastAndCrew
|
import com.owenlejeune.tvtime.api.tmdb.model.*
|
||||||
import com.owenlejeune.tvtime.api.tmdb.model.DetailedItem
|
|
||||||
import com.owenlejeune.tvtime.api.tmdb.model.ImageCollection
|
|
||||||
import com.owenlejeune.tvtime.extensions.dpToPx
|
import com.owenlejeune.tvtime.extensions.dpToPx
|
||||||
import com.owenlejeune.tvtime.ui.components.BackdropImage
|
import com.owenlejeune.tvtime.ui.components.BackdropImage
|
||||||
|
import com.owenlejeune.tvtime.ui.components.MinLinesText
|
||||||
import com.owenlejeune.tvtime.ui.components.PosterItem
|
import com.owenlejeune.tvtime.ui.components.PosterItem
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
@@ -65,13 +59,6 @@ fun DetailView(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val images = remember { mutableStateOf<ImageCollection?>(null) }
|
|
||||||
itemId?.let {
|
|
||||||
if (images.value == null) {
|
|
||||||
fetchImages(itemId, service, images)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val scrollState = rememberScrollState()
|
val scrollState = rememberScrollState()
|
||||||
|
|
||||||
ConstraintLayout(
|
ConstraintLayout(
|
||||||
@@ -81,23 +68,15 @@ fun DetailView(
|
|||||||
.verticalScroll(state = scrollState)
|
.verticalScroll(state = scrollState)
|
||||||
) {
|
) {
|
||||||
val (
|
val (
|
||||||
backButton,
|
backButton, backdropImage, posterImage, titleText, contentColumn
|
||||||
backdropImage,
|
|
||||||
posterImage,
|
|
||||||
titleText,
|
|
||||||
contentColumn
|
|
||||||
) = createRefs()
|
) = createRefs()
|
||||||
|
|
||||||
BackdropImage(
|
Backdrop(
|
||||||
modifier = Modifier
|
modifier = Modifier.constrainAs(backdropImage) {
|
||||||
.constrainAs(backdropImage) {
|
top.linkTo(parent.top)
|
||||||
top.linkTo(parent.top)
|
start.linkTo(parent.start)
|
||||||
start.linkTo(parent.start)
|
},
|
||||||
}
|
mediaItem = mediaItem
|
||||||
.fillMaxWidth()
|
|
||||||
.height(280.dp),
|
|
||||||
imageUrl = TmdbUtils.getFullBackdropPath(mediaItem.value),
|
|
||||||
// collection = images.value
|
|
||||||
)
|
)
|
||||||
|
|
||||||
PosterItem(
|
PosterItem(
|
||||||
@@ -110,151 +89,204 @@ fun DetailView(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
Text(
|
TitleText(
|
||||||
text = mediaItem.value?.title ?: "",
|
modifier = Modifier.constrainAs(titleText) {
|
||||||
color = MaterialTheme.colorScheme.primary,
|
bottom.linkTo(posterImage.bottom)
|
||||||
modifier = Modifier
|
start.linkTo(posterImage.end, margin = 8.dp)
|
||||||
.constrainAs(titleText) {
|
end.linkTo(parent.end, margin = 16.dp)
|
||||||
bottom.linkTo(posterImage.bottom)
|
},
|
||||||
start.linkTo(posterImage.end, margin = 8.dp)
|
mediaItem = mediaItem
|
||||||
end.linkTo(parent.end, margin = 16.dp)
|
|
||||||
}
|
|
||||||
.padding(start = 16.dp, end = 16.dp)
|
|
||||||
.fillMaxWidth(.6f),
|
|
||||||
style = MaterialTheme.typography.headlineMedium,
|
|
||||||
textAlign = TextAlign.Start,
|
|
||||||
softWrap = true
|
|
||||||
)
|
)
|
||||||
|
|
||||||
IconButton(
|
BackButton(
|
||||||
onClick = { appNavController.popBackStack() },
|
modifier = Modifier.constrainAs(backButton) {
|
||||||
modifier = Modifier
|
top.linkTo(parent.top)//, 8.dp)
|
||||||
.constrainAs(backButton) {
|
start.linkTo(parent.start, 12.dp)
|
||||||
top.linkTo(parent.top)//, 8.dp)
|
bottom.linkTo(posterImage.top)
|
||||||
start.linkTo(parent.start, 12.dp)
|
},
|
||||||
bottom.linkTo(posterImage.top)
|
appNavController = appNavController
|
||||||
}
|
)
|
||||||
.background(
|
|
||||||
brush = Brush.radialGradient(
|
ContentColumn(
|
||||||
colors = listOf(
|
modifier = Modifier.constrainAs(contentColumn) {
|
||||||
Color.Black,
|
top.linkTo(backdropImage.bottom, margin = 8.dp)
|
||||||
Color.Transparent
|
},
|
||||||
)
|
itemId = itemId,
|
||||||
|
mediaItem = mediaItem,
|
||||||
|
service = service
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun Backdrop(modifier: Modifier, mediaItem: MutableState<DetailedItem?>) {
|
||||||
|
// val images = remember { mutableStateOf<ImageCollection?>(null) }
|
||||||
|
// itemId?.let {
|
||||||
|
// if (images.value == null) {
|
||||||
|
// fetchImages(itemId, service, images)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
BackdropImage(
|
||||||
|
modifier = modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.height(280.dp),
|
||||||
|
imageUrl = TmdbUtils.getFullBackdropPath(mediaItem.value),
|
||||||
|
// collection = images.value
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun TitleText(modifier: Modifier, mediaItem: MutableState<DetailedItem?>) {
|
||||||
|
Text(
|
||||||
|
text = mediaItem.value?.title ?: "",
|
||||||
|
color = MaterialTheme.colorScheme.primary,
|
||||||
|
modifier = modifier
|
||||||
|
.padding(start = 16.dp, end = 16.dp)
|
||||||
|
.fillMaxWidth(.6f),
|
||||||
|
style = MaterialTheme.typography.headlineMedium,
|
||||||
|
textAlign = TextAlign.Start,
|
||||||
|
softWrap = true
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun BackButton(modifier: Modifier, appNavController: NavController) {
|
||||||
|
IconButton(
|
||||||
|
onClick = { appNavController.popBackStack() },
|
||||||
|
modifier = modifier
|
||||||
|
.background(
|
||||||
|
brush = Brush.radialGradient(
|
||||||
|
colors = listOf(
|
||||||
|
Color.Black,
|
||||||
|
Color.Transparent
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.wrapContentSize()
|
|
||||||
) {
|
|
||||||
Icon(
|
|
||||||
imageVector = Icons.Filled.ArrowBack,
|
|
||||||
contentDescription = "Back",
|
|
||||||
tint = MaterialTheme.colorScheme.primary
|
|
||||||
)
|
)
|
||||||
}
|
.wrapContentSize()
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Filled.ArrowBack,
|
||||||
|
contentDescription = "Back",
|
||||||
|
tint = MaterialTheme.colorScheme.primary
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val castAndCrew = remember { mutableStateOf<CastAndCrew?>(null) }
|
@Composable
|
||||||
itemId?.let {
|
private fun ContentColumn(modifier: Modifier,
|
||||||
if (castAndCrew.value == null) {
|
itemId: Int?,
|
||||||
fetchCastAndCrew(itemId, service, castAndCrew)
|
mediaItem: MutableState<DetailedItem?>,
|
||||||
}
|
service: DetailService
|
||||||
}
|
) {
|
||||||
|
Column(
|
||||||
|
modifier = modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.wrapContentHeight()
|
||||||
|
.padding(horizontal = 16.dp)
|
||||||
|
) {
|
||||||
|
OverviewCard(mediaItem = mediaItem)
|
||||||
|
|
||||||
Column(
|
CastCard(itemId = itemId, service = service)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun OverviewCard(mediaItem: MutableState<DetailedItem?>) {
|
||||||
|
Card(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.wrapContentHeight()
|
||||||
|
.padding(bottom = 12.dp),
|
||||||
|
shape = RoundedCornerShape(10.dp),
|
||||||
|
backgroundColor = MaterialTheme.colorScheme.surfaceVariant,
|
||||||
|
elevation = 8.dp
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.wrapContentHeight()
|
.wrapContentHeight()
|
||||||
.padding(horizontal = 16.dp)
|
.padding(vertical = 12.dp, horizontal = 16.dp),
|
||||||
.constrainAs(contentColumn) {
|
text = mediaItem.value?.overview ?: "",
|
||||||
top.linkTo(backdropImage.bottom, margin = 8.dp)
|
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||||
}
|
style = MaterialTheme.typography.bodyMedium
|
||||||
) {
|
)
|
||||||
Card(
|
}
|
||||||
modifier = Modifier
|
}
|
||||||
.fillMaxWidth()
|
|
||||||
.wrapContentHeight()
|
|
||||||
.padding(bottom = 12.dp),
|
|
||||||
shape = RoundedCornerShape(10.dp),
|
|
||||||
backgroundColor = MaterialTheme.colorScheme.surfaceVariant,
|
|
||||||
elevation = 8.dp
|
|
||||||
) {
|
|
||||||
Text(
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.wrapContentHeight()
|
|
||||||
.padding(vertical = 12.dp, horizontal = 16.dp),
|
|
||||||
text = mediaItem.value?.overview ?: "",
|
|
||||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
|
||||||
style = MaterialTheme.typography.bodyMedium
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
Card(
|
@Composable
|
||||||
modifier = Modifier
|
private fun CastCard(itemId: Int?, service: DetailService) {
|
||||||
.fillMaxWidth()
|
val castAndCrew = remember { mutableStateOf<CastAndCrew?>(null) }
|
||||||
.wrapContentHeight(),
|
itemId?.let {
|
||||||
shape = RoundedCornerShape(10.dp),
|
if (castAndCrew.value == null) {
|
||||||
backgroundColor = MaterialTheme.colorScheme.primary,
|
fetchCastAndCrew(itemId, service, castAndCrew)
|
||||||
elevation = 8.dp
|
}
|
||||||
) {
|
}
|
||||||
LazyRow(modifier = Modifier
|
|
||||||
.fillMaxSize()
|
Card(
|
||||||
.padding(12.dp)
|
modifier = Modifier
|
||||||
) {
|
.fillMaxWidth()
|
||||||
items(castAndCrew.value?.cast?.size ?: 0) { i ->
|
.wrapContentHeight(),
|
||||||
val castMember = castAndCrew.value!!.cast[i]
|
shape = RoundedCornerShape(10.dp),
|
||||||
Column(
|
backgroundColor = MaterialTheme.colorScheme.primary,
|
||||||
modifier = Modifier
|
elevation = 8.dp
|
||||||
.width(124.dp)
|
) {
|
||||||
.wrapContentHeight()
|
LazyRow(modifier = Modifier
|
||||||
.padding(end = 12.dp)
|
.fillMaxSize()
|
||||||
) {
|
.padding(12.dp)
|
||||||
Image(
|
) {
|
||||||
modifier = Modifier
|
items(castAndCrew.value?.cast?.size ?: 0) { i ->
|
||||||
.size(width = 120.dp, height = 180.dp),
|
val castMember = castAndCrew.value!!.cast[i]
|
||||||
painter = rememberImagePainter(
|
|
||||||
data = TmdbUtils.getFullPersonImagePath(castMember),
|
CastCrewCard(person = castMember)
|
||||||
builder = {
|
|
||||||
transformations(RoundedCornersTransformation(5f.dpToPx(context)))
|
|
||||||
placeholder(R.drawable.placeholder)
|
|
||||||
}
|
|
||||||
),
|
|
||||||
contentDescription = ""
|
|
||||||
)
|
|
||||||
val nameLineHeight = MaterialTheme.typography.bodyMedium.fontSize*4/3
|
|
||||||
Text(
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.padding(top = 5.dp)
|
|
||||||
.sizeIn(
|
|
||||||
minHeight = with(LocalDensity.current) {
|
|
||||||
(nameLineHeight * 2).toDp()
|
|
||||||
}
|
|
||||||
),
|
|
||||||
text = castMember.name,
|
|
||||||
color = MaterialTheme.colorScheme.onPrimary,
|
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
|
||||||
lineHeight = nameLineHeight
|
|
||||||
)
|
|
||||||
val characterLineHeight = MaterialTheme.typography.bodySmall.fontSize*4/3
|
|
||||||
Text(
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.sizeIn(
|
|
||||||
minHeight = with(LocalDensity.current) {
|
|
||||||
(characterLineHeight * 2).toDp()
|
|
||||||
}
|
|
||||||
),
|
|
||||||
text = castMember.character,
|
|
||||||
style = MaterialTheme.typography.bodySmall,
|
|
||||||
lineHeight = characterLineHeight
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun CastCrewCard(person: Person) {
|
||||||
|
val context = LocalContext.current
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.width(124.dp)
|
||||||
|
.wrapContentHeight()
|
||||||
|
.padding(end = 12.dp)
|
||||||
|
) {
|
||||||
|
Image(
|
||||||
|
modifier = Modifier
|
||||||
|
.size(width = 120.dp, height = 180.dp),
|
||||||
|
painter = rememberImagePainter(
|
||||||
|
data = TmdbUtils.getFullPersonImagePath(person),
|
||||||
|
builder = {
|
||||||
|
transformations(RoundedCornersTransformation(5f.dpToPx(context)))
|
||||||
|
placeholder(R.drawable.placeholder)
|
||||||
|
}
|
||||||
|
),
|
||||||
|
contentDescription = ""
|
||||||
|
)
|
||||||
|
MinLinesText(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(top = 5.dp),
|
||||||
|
minLines = 2,
|
||||||
|
text = person.name,
|
||||||
|
color = MaterialTheme.colorScheme.onPrimary,
|
||||||
|
style = MaterialTheme.typography.bodyMedium
|
||||||
|
)
|
||||||
|
MinLinesText(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth(),
|
||||||
|
minLines = 2,
|
||||||
|
text = when (person) {
|
||||||
|
is CastMember -> person.character
|
||||||
|
is CrewMember -> person.job
|
||||||
|
else -> ""
|
||||||
|
},
|
||||||
|
style = MaterialTheme.typography.bodySmall
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun fetchMediaItem(id: Int, service: DetailService, mediaItem: MutableState<DetailedItem?>) {
|
private fun fetchMediaItem(id: Int, service: DetailService, mediaItem: MutableState<DetailedItem?>) {
|
||||||
CoroutineScope(Dispatchers.IO).launch {
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
val response = service.getById(id)
|
val response = service.getById(id)
|
||||||
|
|||||||
Reference in New Issue
Block a user