mirror of
https://github.com/owenlejeune/TVTime.git
synced 2025-11-22 11:40:54 -05:00
show known for roles on person card
This commit is contained in:
@@ -1,13 +1,14 @@
|
||||
package com.owenlejeune.tvtime.api.tmdb.model
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.owenlejeune.tvtime.ui.screens.MediaViewType
|
||||
|
||||
class DetailCast(
|
||||
@SerializedName("id") val id: Int,
|
||||
@SerializedName("episode_count") val episodeCount: Int,
|
||||
@SerializedName("overview") val overview: String,
|
||||
@SerializedName("name") val name: String,
|
||||
@SerializedName("media_type") val mediaType: String,
|
||||
@SerializedName("media_type") val mediaType: MediaViewType,
|
||||
@SerializedName("poster_path") val posterPath: String?,
|
||||
@SerializedName("first_air_date") val firstAirDate: String,
|
||||
@SerializedName("character") val character: String,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.owenlejeune.tvtime.api.tmdb.model
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.owenlejeune.tvtime.ui.screens.MediaViewType
|
||||
|
||||
class DetailCrew(
|
||||
@SerializedName("id") val id: Int,
|
||||
@@ -9,7 +10,7 @@ class DetailCrew(
|
||||
@SerializedName("job") val job: String,
|
||||
@SerializedName("overview") val overview: String,
|
||||
@SerializedName("name") val name: String,
|
||||
@SerializedName("media_type") val mediaType: String,
|
||||
@SerializedName("media_type") val mediaType: MediaViewType,
|
||||
@SerializedName("first_air_date") val firstAirDate: String,
|
||||
@SerializedName("poster_path") val posterPath: String,
|
||||
@SerializedName("title") val title: String,
|
||||
|
||||
@@ -81,7 +81,7 @@ fun ExpandableContentCard(
|
||||
color = toggleTextColor,
|
||||
fontSize = 12.sp,
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 12.dp, vertical = 8.dp)
|
||||
.padding(horizontal = 16.dp, vertical = 8.dp)
|
||||
.clickable(
|
||||
onClick = {
|
||||
expandedState = !expandedState
|
||||
@@ -93,7 +93,7 @@ fun ExpandableContentCard(
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ImageTextCard(
|
||||
fun TwoLineImageTextCard(
|
||||
title: String,
|
||||
modifier: Modifier = Modifier,
|
||||
subtitle: String? = null,
|
||||
|
||||
@@ -21,6 +21,7 @@ import androidx.compose.ui.graphics.Brush
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.constraintlayout.compose.ConstraintLayout
|
||||
import androidx.navigation.NavController
|
||||
@@ -96,7 +97,6 @@ fun DetailView(
|
||||
end.linkTo(parent.end, margin = 16.dp)
|
||||
},
|
||||
title = mediaItem.value?.title ?: ""
|
||||
// mediaItem = mediaItem
|
||||
)
|
||||
|
||||
BackButton(
|
||||
@@ -194,17 +194,56 @@ fun PersonDetailView(
|
||||
},
|
||||
verticalArrangement = Arrangement.spacedBy(16.dp)
|
||||
) {
|
||||
ContentCard {
|
||||
ExpandableContentCard { isExpanded ->
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.wrapContentHeight()
|
||||
.padding(vertical = 12.dp, horizontal = 16.dp),
|
||||
.padding(top = 12.dp, start = 16.dp, end = 16.dp),
|
||||
text = person.value?.biography ?: "",
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
style = MaterialTheme.typography.bodyMedium
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
maxLines = if (isExpanded) Int.MAX_VALUE else 3,
|
||||
overflow = TextOverflow.Ellipsis
|
||||
)
|
||||
}
|
||||
|
||||
val credits = remember { mutableStateOf<PersonCreditsResponse?>(null) }
|
||||
personId?.let {
|
||||
if (credits.value == null) {
|
||||
fetchCredits(personId, credits)
|
||||
}
|
||||
}
|
||||
|
||||
ContentCard(title = stringResource(R.string.known_for_label)) {
|
||||
LazyRow(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.wrapContentHeight()
|
||||
.padding(12.dp),
|
||||
horizontalArrangement = Arrangement.spacedBy(4.dp)
|
||||
) {
|
||||
items(credits.value?.cast?.size ?: 0) { i ->
|
||||
val content = credits.value!!.cast[i]
|
||||
|
||||
TwoLineImageTextCard(
|
||||
title = content.title,
|
||||
subtitle = content.character,
|
||||
modifier = Modifier
|
||||
.width(124.dp)
|
||||
.wrapContentHeight(),
|
||||
imageUrl = TmdbUtils.getFullPosterPath(content.posterPath),
|
||||
onItemClicked = {
|
||||
personId?.let {
|
||||
appNavController.navigate(
|
||||
"${MainNavItem.DetailView.route}/${content.mediaType}/${content.id}"
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -227,9 +266,9 @@ private fun Backdrop(modifier: Modifier, mediaItem: MutableState<DetailedItem?>)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun TitleText(modifier: Modifier, title: String/*mediaItem: MutableState<DetailedItem?>*/) {
|
||||
private fun TitleText(modifier: Modifier, title: String) {
|
||||
Text(
|
||||
text = title,//mediaItem.value?.title ?: "",
|
||||
text = title,
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
modifier = modifier
|
||||
.padding(start = 16.dp, end = 16.dp)
|
||||
@@ -252,7 +291,7 @@ private fun BackButton(modifier: Modifier, appNavController: NavController) {
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Filled.ArrowBack,
|
||||
contentDescription = "Back",
|
||||
contentDescription = stringResource(R.string.content_description_back_button),
|
||||
tint = MaterialTheme.colorScheme.primary
|
||||
)
|
||||
}
|
||||
@@ -286,7 +325,7 @@ private fun ContentColumn(
|
||||
|
||||
CastCard(itemId = itemId, service = service, appNavController = appNavController)
|
||||
|
||||
SimilarContentCard(itemId = itemId, service = service)
|
||||
SimilarContentCard(itemId = itemId, service = service, mediaType = mediaType, appNavController = appNavController)
|
||||
|
||||
VideosCard(itemId = itemId, service = service)
|
||||
}
|
||||
@@ -341,13 +380,14 @@ private fun MiscDetails(
|
||||
contentRating: MutableState<String>
|
||||
) {
|
||||
Column(
|
||||
modifier = modifier
|
||||
modifier = modifier,
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp)
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.wrapContentHeight()
|
||||
.padding(start = 8.dp, end = 10.dp, bottom = 8.dp)
|
||||
.padding(horizontal = 8.dp)
|
||||
) {
|
||||
Text(text = year, color = MaterialTheme.colorScheme.onBackground)
|
||||
Text(
|
||||
@@ -365,8 +405,7 @@ private fun MiscDetails(
|
||||
ChipGroup(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.wrapContentHeight()
|
||||
.padding(bottom = 8.dp),
|
||||
.wrapContentHeight(),
|
||||
chips = genres.map { it.name }
|
||||
)
|
||||
}
|
||||
@@ -405,8 +444,8 @@ private fun CastCard(itemId: Int?, service: DetailService, appNavController: Nav
|
||||
textColor = MaterialTheme.colorScheme.background
|
||||
) {
|
||||
LazyRow(modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(12.dp),
|
||||
.fillMaxWidth()
|
||||
.padding(12.dp),
|
||||
horizontalArrangement = Arrangement.spacedBy(4.dp)
|
||||
) {
|
||||
items(castAndCrew.value?.cast?.size ?: 0) { i ->
|
||||
@@ -419,7 +458,7 @@ private fun CastCard(itemId: Int?, service: DetailService, appNavController: Nav
|
||||
|
||||
@Composable
|
||||
private fun CastCrewCard(appNavController: NavController, person: Person) {
|
||||
ImageTextCard(
|
||||
TwoLineImageTextCard(
|
||||
title = person.name,
|
||||
modifier = Modifier
|
||||
.width(124.dp)
|
||||
@@ -442,7 +481,13 @@ private fun CastCrewCard(appNavController: NavController, person: Person) {
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun SimilarContentCard(itemId: Int?, service: DetailService, modifier: Modifier = Modifier) {
|
||||
fun SimilarContentCard(
|
||||
itemId: Int?,
|
||||
service: DetailService,
|
||||
mediaType: MediaViewType,
|
||||
appNavController: NavController,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
val similarContent = remember { mutableStateOf<HomePageResponse?>(null) }
|
||||
itemId?.let {
|
||||
if (similarContent.value == null) {
|
||||
@@ -457,17 +502,23 @@ fun SimilarContentCard(itemId: Int?, service: DetailService, modifier: Modifier
|
||||
LazyRow(modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.wrapContentHeight()
|
||||
.padding(12.dp)
|
||||
.padding(12.dp),
|
||||
horizontalArrangement = Arrangement.spacedBy(4.dp)
|
||||
) {
|
||||
items(similarContent.value?.results?.size ?: 0) { i ->
|
||||
val content = similarContent.value!!.results[i]
|
||||
|
||||
ImageTextCard(
|
||||
TwoLineImageTextCard(
|
||||
title = content.title,
|
||||
modifier = Modifier
|
||||
.width(124.dp)
|
||||
.wrapContentHeight(),
|
||||
imageUrl = TmdbUtils.getFullPosterPath(content)
|
||||
imageUrl = TmdbUtils.getFullPosterPath(content),
|
||||
onItemClicked = {
|
||||
appNavController.navigate(
|
||||
"${MainNavItem.DetailView.route}/${mediaType}/${content.id}"
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -492,7 +543,7 @@ fun VideosCard(itemId: Int?, service: DetailService, modifier: Modifier = Modifi
|
||||
Text(
|
||||
text = stringResource(id = R.string.videos_label),
|
||||
style = MaterialTheme.typography.titleLarge,
|
||||
modifier = Modifier.padding(start = 12.dp, top = 8.dp),
|
||||
modifier = Modifier.padding(start = 16.dp, top = 8.dp),
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||||
)
|
||||
},
|
||||
@@ -516,19 +567,20 @@ private fun VideoGroup(results: List<Video>, type: Video.Type, title: String) {
|
||||
Text(
|
||||
text = title,
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
modifier = Modifier.padding(start = 12.dp, top = 8.dp)
|
||||
modifier = Modifier.padding(start = 16.dp, top = 8.dp)
|
||||
)
|
||||
|
||||
val posterWidth = 120.dp
|
||||
LazyRow(modifier = Modifier
|
||||
.padding(horizontal = 8.dp, vertical = 8.dp)
|
||||
.padding(horizontal = 12.dp, vertical = 8.dp),
|
||||
horizontalArrangement = Arrangement.spacedBy(4.dp)
|
||||
) {
|
||||
listItems(videos) { video ->
|
||||
FullScreenThumbnailVideoPlayer(
|
||||
key = video.key,
|
||||
modifier = Modifier
|
||||
.width(posterWidth)
|
||||
.height(80.dp)
|
||||
.height(90.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -623,4 +675,15 @@ private fun fetchPerson(id: Int, person: MutableState<DetailPerson?>) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun fetchCredits(id: Int, credits: MutableState<PersonCreditsResponse?>) {
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
val result = PeopleService().getCredits(id)
|
||||
if (result.isSuccessful) {
|
||||
withContext(Dispatchers.Main) {
|
||||
credits.value = result.body()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,12 +15,14 @@ import androidx.compose.ui.focus.onFocusChanged
|
||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.navigation.NavController
|
||||
import androidx.navigation.NavHostController
|
||||
import androidx.navigation.compose.currentBackStackEntryAsState
|
||||
import androidx.navigation.compose.rememberNavController
|
||||
import com.google.accompanist.pager.ExperimentalPagerApi
|
||||
import com.owenlejeune.tvtime.R
|
||||
import com.owenlejeune.tvtime.preferences.AppPreferences
|
||||
import com.owenlejeune.tvtime.ui.components.RoundedTextField
|
||||
import com.owenlejeune.tvtime.ui.components.SearchFab
|
||||
@@ -137,7 +139,7 @@ private fun SearchTopBar(
|
||||
focusRequester = focusRequester,
|
||||
value = textState,
|
||||
onValueChange = { textState = it },
|
||||
placeHolder = "Search ${title.value}"
|
||||
placeHolder = stringResource(id = R.string.search_placeholder, title.value)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
package com.owenlejeune.tvtime.ui.screens
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
|
||||
enum class MediaViewType {
|
||||
@SerializedName("movie")
|
||||
MOVIE,
|
||||
@SerializedName("tv")
|
||||
TV,
|
||||
PERSON
|
||||
}
|
||||
Reference in New Issue
Block a user