mirror of
https://github.com/owenlejeune/TVTime.git
synced 2025-11-24 12:32:25 -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.api.tmdb.api.v3.model.*
|
||||||
import com.owenlejeune.tvtime.extensions.listItems
|
import com.owenlejeune.tvtime.extensions.listItems
|
||||||
import com.owenlejeune.tvtime.ui.navigation.MainNavItem
|
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.ui.screens.main.MediaViewType
|
||||||
import com.owenlejeune.tvtime.utils.TmdbUtils
|
import com.owenlejeune.tvtime.utils.TmdbUtils
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
@@ -221,70 +222,15 @@ private fun <T: SortableSearchResult> SearchResultItemView(
|
|||||||
backdropModel: (T) -> Any?,
|
backdropModel: (T) -> Any?,
|
||||||
additionalDetails: (T) -> List<String> = { emptyList() }
|
additionalDetails: (T) -> List<String> = { emptyList() }
|
||||||
) {
|
) {
|
||||||
Card(
|
MediaResultCard(
|
||||||
modifier = Modifier
|
appNavController = appNavController,
|
||||||
.fillMaxWidth()
|
mediaViewType = mediaViewType,
|
||||||
.clickable(
|
id = searchResult.id,
|
||||||
onClick = {
|
backdropPath = backdropModel(searchResult),
|
||||||
appNavController.navigate("${MainNavItem.DetailView.route}/${mediaViewType}/${searchResult.id}")
|
posterPath = posterModel(searchResult),
|
||||||
}
|
title = searchResult.name,
|
||||||
),
|
additionalDetails = additionalDetails(searchResult)
|
||||||
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
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
|||||||
@@ -254,108 +254,17 @@ private fun MediaItemRow(
|
|||||||
backdropPath: String? = null,
|
backdropPath: String? = null,
|
||||||
rating: Float? = null
|
rating: Float? = null
|
||||||
) {
|
) {
|
||||||
Card(
|
MediaResultCard(
|
||||||
shape = RoundedCornerShape(10.dp),
|
appNavController = appNavController,
|
||||||
elevation = CardDefaults.cardElevation(defaultElevation = 10.dp),
|
mediaViewType = mediaViewType,
|
||||||
modifier = Modifier
|
id = id,
|
||||||
.background(color = MaterialTheme.colorScheme.surface)
|
backdropPath = backdropPath,
|
||||||
.fillMaxWidth()
|
posterPath = posterPath,
|
||||||
.clickable(
|
title = "$name (${date.split("-")[0]})",
|
||||||
onClick = {
|
additionalDetails = listOf(description),
|
||||||
appNavController.navigate(
|
rating = rating
|
||||||
"${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)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun AccountDropdownMenu(
|
private fun AccountDropdownMenu(
|
||||||
|
|||||||
@@ -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