mirror of
https://github.com/owenlejeune/TVTime.git
synced 2025-11-24 04:30:54 -05:00
refactor search views
This commit is contained in:
@@ -33,6 +33,7 @@ import com.owenlejeune.tvtime.api.tmdb.api.v3.TvService
|
||||
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.*
|
||||
import com.owenlejeune.tvtime.extensions.listItems
|
||||
import com.owenlejeune.tvtime.ui.navigation.MainNavItem
|
||||
import com.owenlejeune.tvtime.ui.screens.main.MediaResultCard
|
||||
import com.owenlejeune.tvtime.ui.screens.main.MediaViewType
|
||||
import com.owenlejeune.tvtime.utils.TmdbUtils
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
@@ -221,70 +222,15 @@ private fun <T: SortableSearchResult> SearchResultItemView(
|
||||
backdropModel: (T) -> Any?,
|
||||
additionalDetails: (T) -> List<String> = { emptyList() }
|
||||
) {
|
||||
Card(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clickable(
|
||||
onClick = {
|
||||
appNavController.navigate("${MainNavItem.DetailView.route}/${mediaViewType}/${searchResult.id}")
|
||||
}
|
||||
),
|
||||
shape = RoundedCornerShape(10.dp),
|
||||
elevation = 8.dp
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier.height(112.dp)
|
||||
) {
|
||||
AsyncImage(
|
||||
model = backdropModel(searchResult),
|
||||
contentDescription = null,
|
||||
contentScale = ContentScale.FillWidth,
|
||||
modifier = Modifier
|
||||
.blur(radius = 10.dp)
|
||||
.fillMaxWidth()
|
||||
)
|
||||
|
||||
Box(modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.background(Color.Black.copy(alpha = 0.7f))
|
||||
.blur(radius = 10.dp)
|
||||
)
|
||||
|
||||
Row(
|
||||
modifier = Modifier.padding(8.dp)
|
||||
) {
|
||||
AsyncImage(
|
||||
model = posterModel(searchResult),
|
||||
contentDescription = null,
|
||||
modifier = Modifier
|
||||
.padding(end = 8.dp)
|
||||
.size(width = 75.dp, height = 112.dp)
|
||||
)
|
||||
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(4.dp),
|
||||
modifier = Modifier
|
||||
.align(Alignment.CenterVertically)
|
||||
) {
|
||||
Text(
|
||||
text = searchResult.name,
|
||||
color = MaterialTheme.colorScheme.onBackground,
|
||||
fontSize = 18.sp
|
||||
)
|
||||
|
||||
additionalDetails(searchResult)
|
||||
.filter { it.isNotEmpty() }
|
||||
.forEach { item ->
|
||||
Text(
|
||||
text = item,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
fontSize = 16.sp
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
MediaResultCard(
|
||||
appNavController = appNavController,
|
||||
mediaViewType = mediaViewType,
|
||||
id = searchResult.id,
|
||||
backdropPath = backdropModel(searchResult),
|
||||
posterPath = posterModel(searchResult),
|
||||
title = searchResult.name,
|
||||
additionalDetails = additionalDetails(searchResult)
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
||||
@@ -254,107 +254,16 @@ private fun MediaItemRow(
|
||||
backdropPath: String? = null,
|
||||
rating: Float? = null
|
||||
) {
|
||||
Card(
|
||||
shape = RoundedCornerShape(10.dp),
|
||||
elevation = CardDefaults.cardElevation(defaultElevation = 10.dp),
|
||||
modifier = Modifier
|
||||
.background(color = MaterialTheme.colorScheme.surface)
|
||||
.fillMaxWidth()
|
||||
.clickable(
|
||||
onClick = {
|
||||
appNavController.navigate(
|
||||
"${MainNavItem.DetailView.route}/${mediaViewType}/${id}"
|
||||
)
|
||||
}
|
||||
)
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.height(112.dp)
|
||||
) {
|
||||
AsyncImage(
|
||||
model = backdropPath,
|
||||
contentDescription = null,
|
||||
contentScale = ContentScale.FillWidth,
|
||||
modifier = Modifier
|
||||
.blur(radius = 10.dp)
|
||||
.fillMaxWidth()
|
||||
.wrapContentHeight()
|
||||
)
|
||||
|
||||
backdropPath?.let {
|
||||
Box(modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.background(Color.Black.copy(alpha = 0.7f))
|
||||
.blur(radius = 10.dp)
|
||||
)
|
||||
}
|
||||
|
||||
ConstraintLayout(
|
||||
modifier = Modifier
|
||||
.padding(8.dp)
|
||||
.fillMaxSize()
|
||||
) {
|
||||
val (poster, content, ratingView) = createRefs()
|
||||
|
||||
AsyncImage(
|
||||
modifier = Modifier
|
||||
.constrainAs(poster) {
|
||||
start.linkTo(parent.start)
|
||||
top.linkTo(parent.top)
|
||||
bottom.linkTo(parent.bottom)
|
||||
height = Dimension.fillToConstraints
|
||||
}
|
||||
.clip(RoundedCornerShape(10.dp)),
|
||||
model = posterPath,
|
||||
contentDescription = "",
|
||||
)
|
||||
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(4.dp),
|
||||
modifier = Modifier
|
||||
.constrainAs(content) {
|
||||
end.linkTo(
|
||||
rating?.let { ratingView.start } ?: parent.end,
|
||||
margin = 8.dp
|
||||
)
|
||||
start.linkTo(poster.end, margin = 8.dp)
|
||||
top.linkTo(parent.top)
|
||||
bottom.linkTo(parent.bottom)
|
||||
width = Dimension.fillToConstraints
|
||||
height = Dimension.fillToConstraints
|
||||
}
|
||||
) {
|
||||
val releaseYear = date.split("-")[0]
|
||||
Text(
|
||||
text = "$name (${releaseYear})",
|
||||
color = MaterialTheme.colorScheme.onBackground,
|
||||
fontSize = 18.sp,
|
||||
fontWeight = FontWeight.Bold
|
||||
)
|
||||
|
||||
Text(
|
||||
text = description,
|
||||
color = MaterialTheme.colorScheme.onBackground,
|
||||
fontSize = 14.sp,
|
||||
overflow = TextOverflow.Ellipsis
|
||||
)
|
||||
}
|
||||
|
||||
rating?.let {
|
||||
RatingView(
|
||||
progress = rating/10,
|
||||
modifier = Modifier
|
||||
.constrainAs(ratingView) {
|
||||
end.linkTo(parent.end)
|
||||
top.linkTo(parent.top)
|
||||
bottom.linkTo(parent.bottom)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
MediaResultCard(
|
||||
appNavController = appNavController,
|
||||
mediaViewType = mediaViewType,
|
||||
id = id,
|
||||
backdropPath = backdropPath,
|
||||
posterPath = posterPath,
|
||||
title = "$name (${date.split("-")[0]})",
|
||||
additionalDetails = listOf(description),
|
||||
rating = rating
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
package com.owenlejeune.tvtime.ui.screens.main
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.blur
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
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.sp
|
||||
import androidx.constraintlayout.compose.ConstraintLayout
|
||||
import androidx.constraintlayout.compose.Dimension
|
||||
import androidx.navigation.NavController
|
||||
import coil.compose.AsyncImage
|
||||
import com.owenlejeune.tvtime.ui.navigation.MainNavItem
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun MediaResultCard(
|
||||
appNavController: NavController,
|
||||
mediaViewType: MediaViewType,
|
||||
id: Int,
|
||||
backdropPath: Any?,
|
||||
posterPath: Any?,
|
||||
title: String,
|
||||
additionalDetails: List<String>,
|
||||
rating: Float? = null
|
||||
) {
|
||||
Card(
|
||||
shape = RoundedCornerShape(10.dp),
|
||||
elevation = CardDefaults.cardElevation(defaultElevation = 10.dp),
|
||||
modifier = Modifier
|
||||
.background(color = MaterialTheme.colorScheme.surface)
|
||||
.fillMaxWidth()
|
||||
.clickable(
|
||||
onClick = {
|
||||
appNavController.navigate(
|
||||
"${MainNavItem.DetailView.route}/${mediaViewType}/${id}"
|
||||
)
|
||||
}
|
||||
)
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier.height(112.dp)
|
||||
) {
|
||||
backdropPath?.let {
|
||||
AsyncImage(
|
||||
model = backdropPath,
|
||||
contentDescription = null,
|
||||
contentScale = ContentScale.FillWidth,
|
||||
modifier = Modifier
|
||||
.blur(radius = 10.dp)
|
||||
.fillMaxWidth()
|
||||
.wrapContentHeight()
|
||||
)
|
||||
|
||||
Box(modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.background(Color.Black.copy(alpha = 0.7f))
|
||||
.blur(radius = 10.dp)
|
||||
)
|
||||
}
|
||||
|
||||
ConstraintLayout(
|
||||
modifier = Modifier
|
||||
.padding(8.dp)
|
||||
.fillMaxSize()
|
||||
) {
|
||||
val (poster, content, ratingView) = createRefs()
|
||||
|
||||
AsyncImage(
|
||||
modifier = Modifier
|
||||
.constrainAs(poster) {
|
||||
start.linkTo(parent.start)
|
||||
top.linkTo(parent.top)
|
||||
bottom.linkTo(parent.bottom)
|
||||
height = Dimension.fillToConstraints
|
||||
}
|
||||
.clip(RoundedCornerShape(10.dp)),
|
||||
model = posterPath,
|
||||
contentDescription = title
|
||||
)
|
||||
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(4.dp),
|
||||
modifier = Modifier
|
||||
.constrainAs(content) {
|
||||
end.linkTo(
|
||||
rating?.let { ratingView.start } ?: parent.end,
|
||||
margin = 12.dp
|
||||
)
|
||||
start.linkTo(poster.end, margin = 12.dp)
|
||||
width = Dimension.fillToConstraints
|
||||
height = Dimension.matchParent
|
||||
}
|
||||
) {
|
||||
Text(
|
||||
text = title,
|
||||
color = MaterialTheme.colorScheme.onBackground,
|
||||
fontSize = 18.sp,
|
||||
fontWeight = FontWeight.Bold
|
||||
)
|
||||
|
||||
additionalDetails.forEach {
|
||||
Text(
|
||||
text = it,
|
||||
color = MaterialTheme.colorScheme.onBackground,
|
||||
fontSize = 14.sp,
|
||||
overflow = TextOverflow.Ellipsis
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
rating?.let {
|
||||
RatingView(
|
||||
progress = rating / 10f,
|
||||
modifier = Modifier
|
||||
.constrainAs(ratingView) {
|
||||
end.linkTo(parent.end)
|
||||
top.linkTo(parent.top)
|
||||
bottom.linkTo(parent.bottom)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user