refactor common details view code

This commit is contained in:
Owen LeJeune
2022-02-19 22:41:11 -05:00
parent e346f1ebd7
commit ac469b081c
9 changed files with 298 additions and 190 deletions

View File

@@ -3,6 +3,7 @@ package com.owenlejeune.tvtime.api.tmdb
import com.owenlejeune.tvtime.api.tmdb.model.CastAndCrew import com.owenlejeune.tvtime.api.tmdb.model.CastAndCrew
import com.owenlejeune.tvtime.api.tmdb.model.ImageCollection import com.owenlejeune.tvtime.api.tmdb.model.ImageCollection
import com.owenlejeune.tvtime.api.tmdb.model.DetailedItem import com.owenlejeune.tvtime.api.tmdb.model.DetailedItem
import com.owenlejeune.tvtime.api.tmdb.model.HomePageResponse
import retrofit2.Response import retrofit2.Response
interface DetailService { interface DetailService {
@@ -13,4 +14,6 @@ interface DetailService {
suspend fun getCastAndCrew(id: Int): Response<CastAndCrew> suspend fun getCastAndCrew(id: Int): Response<CastAndCrew>
suspend fun getSimilar(id: Int, page: Int): Response<out HomePageResponse>
} }

View File

@@ -32,4 +32,7 @@ interface MoviesApi {
@GET("movie/{id}/release_dates") @GET("movie/{id}/release_dates")
suspend fun getReleaseDates(@Path("id") id: Int): Response<MovieReleaseResults> suspend fun getReleaseDates(@Path("id") id: Int): Response<MovieReleaseResults>
@GET("movie/{id}/recommendations")
suspend fun getSimilarMovies(@Path("id") id: Int, @Query("page") page: Int = 1): Response<HomePageMoviesResponse>
} }

View File

@@ -40,4 +40,8 @@ class MoviesService: KoinComponent, DetailService, HomePageService {
return service.getCastAndCrew(id) return service.getCastAndCrew(id)
} }
override suspend fun getSimilar(id: Int, page: Int): Response<out HomePageResponse> {
return service.getSimilarMovies(id, page)
}
} }

View File

@@ -32,4 +32,7 @@ interface TvApi {
@GET("tv/{id}/content_ratings") @GET("tv/{id}/content_ratings")
suspend fun getContentRatings(@Path("id") id: Int): Response<TvContentRatings> suspend fun getContentRatings(@Path("id") id: Int): Response<TvContentRatings>
@GET("tv/{id}/similar")
suspend fun getSimilarTvShows(@Path("id") id: Int, @Query("page") page: Int = 1): Response<HomePageTvResponse>
} }

View File

@@ -39,4 +39,8 @@ class TvService: KoinComponent, DetailService, HomePageService {
suspend fun getContentRatings(id: Int): Response<TvContentRatings> { suspend fun getContentRatings(id: Int): Response<TvContentRatings> {
return service.getContentRatings(id) return service.getContentRatings(id)
} }
override suspend fun getSimilar(id: Int, page: Int): Response<out HomePageResponse> {
return service.getSimilarTvShows(id, page)
}
} }

View File

@@ -0,0 +1,96 @@
package com.owenlejeune.tvtime.ui.components
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Card
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import coil.compose.rememberImagePainter
import coil.transform.RoundedCornersTransformation
import com.owenlejeune.tvtime.R
import com.owenlejeune.tvtime.extensions.dpToPx
@Composable
fun ContentCard(
modifier: Modifier = Modifier,
title: String? = null,
backgroundColor: Color = MaterialTheme.colorScheme.surfaceVariant,
textColor: Color = MaterialTheme.colorScheme.onSurfaceVariant,
content: @Composable () -> Unit = {}
) {
Card(
modifier = modifier
.fillMaxWidth()
.wrapContentHeight(),
shape = RoundedCornerShape(10.dp),
backgroundColor = backgroundColor,
elevation = 8.dp
) {
Column(modifier = Modifier.fillMaxSize()) {
title?.let {
Text(
text = title,
style = MaterialTheme.typography.titleLarge,
modifier = Modifier.padding(start = 12.dp, top = 8.dp),
color = textColor
)
}
content()
}
}
}
@Composable
fun ImageTextCard(
title: String,
modifier: Modifier = Modifier,
subtitle: String? = null,
imageUrl: String? = null,
noDataImage: Int = R.drawable.placeholder,
placeholder: Int = R.drawable.placeholder,
titleTextColor: Color = MaterialTheme.colorScheme.onSurfaceVariant,
subtitleTextColor: Color = MaterialTheme.colorScheme.onSurfaceVariant
) {
val context = LocalContext.current
Column(
modifier = modifier
.padding(end = 12.dp)
) {
Image(
modifier = Modifier
.size(width = 120.dp, height = 180.dp),
painter = rememberImagePainter(
data = imageUrl ?: noDataImage,
builder = {
transformations(RoundedCornersTransformation(5f.dpToPx(context)))
placeholder(placeholder)
}
),
contentDescription = ""
)
MinLinesText(
modifier = Modifier
.fillMaxWidth()
.padding(top = 5.dp),
minLines = 2,
text = title,
color = titleTextColor,
style = MaterialTheme.typography.bodyMedium
)
subtitle?.let {
MinLinesText(
modifier = Modifier.fillMaxWidth(),
minLines = 2,
text = subtitle,
style = MaterialTheme.typography.bodySmall,
color = subtitleTextColor
)
}
}
}

View File

@@ -0,0 +1,103 @@
package com.owenlejeune.tvtime.ui.components
import androidx.compose.material.ContentAlpha
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.compositeOver
class CustomSwitchColors private constructor(
val lightUncheckedTrackColor: Color,
val darkUncheckedTrackColor: Color,
val lightUncheckedThumbColor: Color,
val darkUncheckedThumbColor: Color,
val lightCheckedTrackColor: Color,
val darkCheckedTrackColor: Color,
val lightCheckedThumbColor: Color,
val darkCheckedThumbColor: Color,
val lightDisabledTrackColor: Color,
val darkDisabledTrackColor: Color,
val lightDisabledThumbColor: Color,
val darkDisabledThumbColor: Color
){
companion object {
@Composable
fun topLevelColors(
lightUncheckedTrackColor: Color = MaterialTheme.colorScheme.outline,
darkUncheckedTrackColor: Color = MaterialTheme.colorScheme.surfaceVariant,
lightUncheckedThumbColor: Color = MaterialTheme.colorScheme.surfaceVariant,
darkUncheckedThumbColor: Color = MaterialTheme.colorScheme.outline,
lightCheckedTrackColor: Color = MaterialTheme.colorScheme.primary,
darkCheckedTrackColor: Color = MaterialTheme.colorScheme.outline,
lightCheckedThumbColor: Color = MaterialTheme.colorScheme.primaryContainer,
darkCheckedThumbColor: Color = MaterialTheme.colorScheme.primary,
lightDisabledTrackColor: Color = lightUncheckedTrackColor
.copy(alpha = ContentAlpha.disabled)
.compositeOver(MaterialTheme.colorScheme.surface),
darkDisabledTrackColor: Color = darkUncheckedTrackColor
.copy(alpha = ContentAlpha.disabled)
.compositeOver(MaterialTheme.colorScheme.surface),
lightDisabledThumbColor: Color = lightUncheckedThumbColor
.copy(alpha = ContentAlpha.disabled)
.compositeOver(MaterialTheme.colorScheme.surface),
darkDisabledThumbColor: Color = darkUncheckedThumbColor
.copy(alpha = ContentAlpha.disabled)
.compositeOver(MaterialTheme.colorScheme.surface)
): CustomSwitchColors {
return CustomSwitchColors(
lightUncheckedTrackColor,
darkUncheckedTrackColor,
lightUncheckedThumbColor,
darkUncheckedThumbColor,
lightCheckedTrackColor,
darkCheckedTrackColor,
lightCheckedThumbColor,
darkCheckedThumbColor,
lightDisabledTrackColor,
darkDisabledTrackColor,
lightDisabledThumbColor,
darkDisabledThumbColor
)
}
@Composable
fun standardColors(
lightUncheckedTrackColor: Color = MaterialTheme.colorScheme.outline,
darkUncheckedTrackColor: Color = MaterialTheme.colorScheme.surfaceVariant,
lightUncheckedThumbColor: Color = MaterialTheme.colorScheme.surfaceVariant,
darkUncheckedThumbColor: Color = MaterialTheme.colorScheme.outline,
lightCheckedTrackColor: Color = MaterialTheme.colorScheme.primary,
darkCheckedTrackColor: Color = MaterialTheme.colorScheme.secondaryContainer,
lightCheckedThumbColor: Color = MaterialTheme.colorScheme.primaryContainer,
darkCheckedThumbColor: Color = MaterialTheme.colorScheme.primary,
lightDisabledTrackColor: Color = lightUncheckedTrackColor
.copy(alpha = ContentAlpha.disabled)
.compositeOver(MaterialTheme.colorScheme.surface),
darkDisabledTrackColor: Color = darkUncheckedTrackColor
.copy(alpha = ContentAlpha.disabled)
.compositeOver(MaterialTheme.colorScheme.surface),
lightDisabledThumbColor: Color = lightUncheckedThumbColor
.copy(alpha = ContentAlpha.disabled)
.compositeOver(MaterialTheme.colorScheme.surface),
darkDisabledThumbColor: Color = darkUncheckedThumbColor
.copy(alpha = ContentAlpha.disabled)
.compositeOver(MaterialTheme.colorScheme.surface)
): CustomSwitchColors {
return CustomSwitchColors(
lightUncheckedTrackColor,
darkUncheckedTrackColor,
lightUncheckedThumbColor,
darkUncheckedThumbColor,
lightCheckedTrackColor,
darkCheckedTrackColor,
lightCheckedThumbColor,
darkCheckedThumbColor,
lightDisabledTrackColor,
darkDisabledTrackColor,
lightDisabledThumbColor,
darkDisabledThumbColor
)
}
}
}

View File

@@ -13,8 +13,6 @@ import androidx.compose.foundation.text.BasicTextField
import androidx.compose.foundation.text.KeyboardActions import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.Card import androidx.compose.material.Card
import androidx.compose.material.ContentAlpha
import androidx.compose.material.Switch
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.* import androidx.compose.material3.*
@@ -28,7 +26,6 @@ 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.graphics.Color
import androidx.compose.ui.graphics.SolidColor import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.graphics.compositeOver
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
@@ -95,101 +92,6 @@ fun TopLevelSwitch(
} }
} }
class CustomSwitchColors private constructor(
val lightUncheckedTrackColor: Color,
val darkUncheckedTrackColor: Color,
val lightUncheckedThumbColor: Color,
val darkUncheckedThumbColor: Color,
val lightCheckedTrackColor: Color,
val darkCheckedTrackColor: Color,
val lightCheckedThumbColor: Color,
val darkCheckedThumbColor: Color,
val lightDisabledTrackColor: Color,
val darkDisabledTrackColor: Color,
val lightDisabledThumbColor: Color,
val darkDisabledThumbColor: Color
){
companion object {
@Composable
fun topLevelColors(
lightUncheckedTrackColor: Color = MaterialTheme.colorScheme.outline,
darkUncheckedTrackColor: Color =MaterialTheme.colorScheme.surfaceVariant,
lightUncheckedThumbColor: Color = MaterialTheme.colorScheme.surfaceVariant,
darkUncheckedThumbColor: Color = MaterialTheme.colorScheme.outline,
lightCheckedTrackColor: Color = MaterialTheme.colorScheme.primary,
darkCheckedTrackColor: Color = MaterialTheme.colorScheme.outline,
lightCheckedThumbColor: Color = MaterialTheme.colorScheme.primaryContainer,
darkCheckedThumbColor: Color = MaterialTheme.colorScheme.primary,
lightDisabledTrackColor: Color = lightUncheckedTrackColor
.copy(alpha = ContentAlpha.disabled)
.compositeOver(MaterialTheme.colorScheme.surface),
darkDisabledTrackColor: Color = darkUncheckedTrackColor
.copy(alpha = ContentAlpha.disabled)
.compositeOver(MaterialTheme.colorScheme.surface),
lightDisabledThumbColor: Color = lightUncheckedThumbColor
.copy(alpha = ContentAlpha.disabled)
.compositeOver(MaterialTheme.colorScheme.surface),
darkDisabledThumbColor: Color = darkUncheckedThumbColor
.copy(alpha = ContentAlpha.disabled)
.compositeOver(MaterialTheme.colorScheme.surface)
): CustomSwitchColors {
return CustomSwitchColors(
lightUncheckedTrackColor,
darkUncheckedTrackColor,
lightUncheckedThumbColor,
darkUncheckedThumbColor,
lightCheckedTrackColor,
darkCheckedTrackColor,
lightCheckedThumbColor,
darkCheckedThumbColor,
lightDisabledTrackColor,
darkDisabledTrackColor,
lightDisabledThumbColor,
darkDisabledThumbColor
)
}
@Composable
fun standardColors(
lightUncheckedTrackColor: Color = MaterialTheme.colorScheme.outline,
darkUncheckedTrackColor: Color = MaterialTheme.colorScheme.surfaceVariant,
lightUncheckedThumbColor: Color = MaterialTheme.colorScheme.surfaceVariant,
darkUncheckedThumbColor: Color = MaterialTheme.colorScheme.outline,
lightCheckedTrackColor: Color = MaterialTheme.colorScheme.primary,
darkCheckedTrackColor: Color = MaterialTheme.colorScheme.secondaryContainer,
lightCheckedThumbColor: Color = MaterialTheme.colorScheme.primaryContainer,
darkCheckedThumbColor: Color = MaterialTheme.colorScheme.primary,
lightDisabledTrackColor: Color = lightUncheckedTrackColor
.copy(alpha = ContentAlpha.disabled)
.compositeOver(MaterialTheme.colorScheme.surface),
darkDisabledTrackColor: Color = darkUncheckedTrackColor
.copy(alpha = ContentAlpha.disabled)
.compositeOver(MaterialTheme.colorScheme.surface),
lightDisabledThumbColor: Color = lightUncheckedThumbColor
.copy(alpha = ContentAlpha.disabled)
.compositeOver(MaterialTheme.colorScheme.surface),
darkDisabledThumbColor: Color = darkUncheckedThumbColor
.copy(alpha = ContentAlpha.disabled)
.compositeOver(MaterialTheme.colorScheme.surface)
): CustomSwitchColors {
return CustomSwitchColors(
lightUncheckedTrackColor,
darkUncheckedTrackColor,
lightUncheckedThumbColor,
darkUncheckedThumbColor,
lightCheckedTrackColor,
darkCheckedTrackColor,
lightCheckedThumbColor,
darkCheckedThumbColor,
lightDisabledTrackColor,
darkDisabledTrackColor,
lightDisabledThumbColor,
darkDisabledThumbColor
)
}
}
}
@Composable @Composable
fun CustomSwitch( fun CustomSwitch(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,

View File

@@ -1,13 +1,10 @@
package com.owenlejeune.tvtime.ui.screens package com.owenlejeune.tvtime.ui.screens
import androidx.compose.foundation.Image
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import androidx.compose.material.Card
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
@@ -21,24 +18,17 @@ 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.res.stringResource import androidx.compose.ui.res.stringResource
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.constraintlayout.compose.ConstraintLayout import androidx.constraintlayout.compose.ConstraintLayout
import androidx.navigation.NavController import androidx.navigation.NavController
import coil.compose.rememberImagePainter
import coil.transform.RoundedCornersTransformation
import com.owenlejeune.tvtime.R import com.owenlejeune.tvtime.R
import com.owenlejeune.tvtime.api.tmdb.DetailService 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.TvService import com.owenlejeune.tvtime.api.tmdb.TvService
import com.owenlejeune.tvtime.api.tmdb.model.* import com.owenlejeune.tvtime.api.tmdb.model.*
import com.owenlejeune.tvtime.extensions.dpToPx import com.owenlejeune.tvtime.ui.components.*
import com.owenlejeune.tvtime.ui.components.BackdropImage
import com.owenlejeune.tvtime.ui.components.ChipGroup
import com.owenlejeune.tvtime.ui.components.MinLinesText
import com.owenlejeune.tvtime.ui.components.PosterItem
import com.owenlejeune.tvtime.utils.TmdbUtils import com.owenlejeune.tvtime.utils.TmdbUtils
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@@ -160,12 +150,7 @@ private fun BackButton(modifier: Modifier, appNavController: NavController) {
onClick = { appNavController.popBackStack() }, onClick = { appNavController.popBackStack() },
modifier = modifier modifier = modifier
.background( .background(
brush = Brush.radialGradient( brush = Brush.radialGradient(colors = listOf(Color.Black, Color.Transparent))
colors = listOf(
Color.Black,
Color.Transparent
)
)
) )
.wrapContentSize() .wrapContentSize()
) { ) {
@@ -178,7 +163,8 @@ private fun BackButton(modifier: Modifier, appNavController: NavController) {
} }
@Composable @Composable
private fun ContentColumn(modifier: Modifier, private fun ContentColumn(
modifier: Modifier,
itemId: Int?, itemId: Int?,
mediaItem: MutableState<DetailedItem?>, mediaItem: MutableState<DetailedItem?>,
service: DetailService, service: DetailService,
@@ -190,7 +176,6 @@ private fun ContentColumn(modifier: Modifier,
.wrapContentHeight() .wrapContentHeight()
.padding(start = 16.dp, end = 16.dp, bottom = 16.dp) .padding(start = 16.dp, end = 16.dp, bottom = 16.dp)
) { ) {
if (mediaType == MediaViewType.MOVIE) { if (mediaType == MediaViewType.MOVIE) {
MiscMovieDetails(mediaItem = mediaItem, service as MoviesService) MiscMovieDetails(mediaItem = mediaItem, service as MoviesService)
} else { } else {
@@ -198,10 +183,12 @@ private fun ContentColumn(modifier: Modifier,
} }
if (mediaItem.value?.overview?.isNotEmpty() == true) { if (mediaItem.value?.overview?.isNotEmpty() == true) {
OverviewCard(mediaItem = mediaItem) OverviewCard(mediaItem = mediaItem, modifier = Modifier.padding(bottom = 16.dp))
} }
CastCard(itemId = itemId, service = service) CastCard(itemId = itemId, service = service, modifier = Modifier.padding(bottom = 16.dp))
SimilarContent(itemId = itemId, service = service)//, modifier = Modifier.padding(bottom = 16.dp))
} }
} }
@@ -286,15 +273,9 @@ private fun MiscDetails(
} }
@Composable @Composable
private fun OverviewCard(mediaItem: MutableState<DetailedItem?>) { private fun OverviewCard(mediaItem: MutableState<DetailedItem?>, modifier: Modifier = Modifier) {
Card( ContentCard(
modifier = Modifier modifier = modifier
.fillMaxWidth()
.wrapContentHeight()
.padding(bottom = 16.dp),
shape = RoundedCornerShape(10.dp),
backgroundColor = MaterialTheme.colorScheme.surfaceVariant,
elevation = 8.dp
) { ) {
Text( Text(
modifier = Modifier modifier = Modifier
@@ -309,7 +290,7 @@ private fun OverviewCard(mediaItem: MutableState<DetailedItem?>) {
} }
@Composable @Composable
private fun CastCard(itemId: Int?, service: DetailService) { private fun CastCard(itemId: Int?, service: DetailService, modifier: Modifier = Modifier) {
val castAndCrew = remember { mutableStateOf<CastAndCrew?>(null) } val castAndCrew = remember { mutableStateOf<CastAndCrew?>(null) }
itemId?.let { itemId?.let {
if (castAndCrew.value == null) { if (castAndCrew.value == null) {
@@ -317,76 +298,74 @@ private fun CastCard(itemId: Int?, service: DetailService) {
} }
} }
Card( ContentCard(
modifier = Modifier modifier = modifier,
.fillMaxWidth() title = stringResource(R.string.cast_label),
.wrapContentHeight(),
shape = RoundedCornerShape(10.dp),
backgroundColor = MaterialTheme.colorScheme.primary, backgroundColor = MaterialTheme.colorScheme.primary,
elevation = 8.dp textColor = MaterialTheme.colorScheme.background
) { ) {
Column(modifier = Modifier.fillMaxSize()) {
Text(
text = stringResource(R.string.cast_label),
style = MaterialTheme.typography.titleLarge,
modifier = Modifier.padding(start = 12.dp, top = 12.dp)
)
LazyRow(modifier = Modifier LazyRow(modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(12.dp) .padding(12.dp)
) { ) {
items(castAndCrew.value?.cast?.size ?: 0) { i -> items(castAndCrew.value?.cast?.size ?: 0) { i ->
val castMember = castAndCrew.value!!.cast[i] val castMember = castAndCrew.value!!.cast[i]
CastCrewCard(person = castMember) CastCrewCard(person = castMember)
} }
} }
} }
} }
}
@Composable @Composable
private fun CastCrewCard(person: Person) { private fun CastCrewCard(person: Person) {
val context = LocalContext.current ImageTextCard(
Column( title = person.name,
modifier = Modifier modifier = Modifier
.width(124.dp) .width(124.dp)
.wrapContentHeight() .wrapContentHeight(),
.padding(end = 12.dp) subtitle = when (person) {
) {
Image(
modifier = Modifier
.size(width = 120.dp, height = 180.dp),
painter = rememberImagePainter(
data = TmdbUtils.getFullPersonImagePath(person) ?: R.drawable.no_person_photo,
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 CastMember -> person.character
is CrewMember -> person.job is CrewMember -> person.job
else -> "" else -> null
}, },
style = MaterialTheme.typography.bodySmall imageUrl = TmdbUtils.getFullPersonImagePath(person),
noDataImage = R.drawable.no_person_photo,
titleTextColor = MaterialTheme.colorScheme.onPrimary,
subtitleTextColor = Color.Unspecified
) )
} }
@Composable
fun SimilarContent(itemId: Int?, service: DetailService, modifier: Modifier = Modifier) {
val similarContent = remember { mutableStateOf<HomePageResponse?>(null) }
itemId?.let {
if (similarContent.value == null) {
fetchSimilarContent(itemId, service, similarContent)
}
}
ContentCard(
modifier = modifier,
title = "Recommended"
) {
LazyRow(modifier = Modifier
.fillMaxWidth()
.wrapContentHeight()
.padding(12.dp)
) {
items(similarContent.value?.results?.size ?: 0) { i ->
val content = similarContent.value!!.results[i]
ImageTextCard(
title = content.title,
modifier = Modifier
.width(124.dp)
.wrapContentHeight(),
imageUrl = TmdbUtils.getFullPosterPath(content)
)
}
}
}
} }
private fun fetchMediaItem(id: Int, service: DetailService, mediaItem: MutableState<DetailedItem?>) { private fun fetchMediaItem(id: Int, service: DetailService, mediaItem: MutableState<DetailedItem?>) {
@@ -445,3 +424,14 @@ private fun fetchTvContentRating(id: Int, service: TvService, contentRating: Mut
} }
} }
} }
private fun fetchSimilarContent(id: Int, service: DetailService, similarContent: MutableState<HomePageResponse?>) {
CoroutineScope(Dispatchers.IO).launch {
val results = service.getSimilar(id, 1)
if (results.isSuccessful) {
withContext(Dispatchers.Main) {
similarContent.value = results.body()
}
}
}
}