update poster in overview

This commit is contained in:
2026-07-27 21:49:23 +03:00
parent 32667ca9f3
commit 93a53967e3
@@ -13,7 +13,6 @@ import androiddev.apps.vbox.client.shared.generated.resources.star
import androiddev.apps.vbox.client.shared.generated.resources.star_unchecked import androiddev.apps.vbox.client.shared.generated.resources.star_unchecked
import androiddev.apps.vbox.client.shared.generated.resources.user_tags import androiddev.apps.vbox.client.shared.generated.resources.user_tags
import androiddev.apps.vbox.client.shared.generated.resources.watch import androiddev.apps.vbox.client.shared.generated.resources.watch
import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.animateContentSize import androidx.compose.animation.animateContentSize
import androidx.compose.animation.core.Spring import androidx.compose.animation.core.Spring
@@ -21,14 +20,21 @@ import androidx.compose.animation.core.spring
import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut import androidx.compose.animation.fadeOut
import androidx.compose.foundation.Image import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Button import androidx.compose.material3.Button
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.DropdownMenu import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
@@ -50,11 +56,13 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.runtime.withFrameNanos
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
@@ -100,7 +108,6 @@ fun OverviewScreen(component: OverviewComponent) {
scrollBehavior = scrollBehavior, scrollBehavior = scrollBehavior,
snackbarState = snackbarState, snackbarState = snackbarState,
content = { padding -> content = { padding ->
AnimatedContent(details) {
when { when {
errorState != null -> ErrorAndRetry( errorState != null -> ErrorAndRetry(
@@ -115,7 +122,6 @@ fun OverviewScreen(component: OverviewComponent) {
else -> Loading() else -> Loading()
} }
}
if (tagsBottomSheetVisible) { if (tagsBottomSheetVisible) {
val allTags by component.allTags.collectAsState(null) val allTags by component.allTags.collectAsState(null)
@@ -261,7 +267,7 @@ fun DetailsInfo(
modifier = Modifier.applyBlurSource(blur), modifier = Modifier.applyBlurSource(blur),
contentPadding = paddingValues contentPadding = paddingValues
) { ) {
item { OverviewTitle(details) } item { Poster(details.poster) }
item { OverviewDescription(details, showDetails) } item { OverviewDescription(details, showDetails) }
item { item {
Button( Button(
@@ -274,8 +280,8 @@ fun DetailsInfo(
Text(stringResource(Res.string.watch)) Text(stringResource(Res.string.watch))
} }
// Чистый фокус без сдвига кадров через withFrameNanos
LaunchedEffect(Unit) { LaunchedEffect(Unit) {
withFrameNanos {}
requester.requestFocus() requester.requestFocus()
} }
} }
@@ -291,7 +297,6 @@ private fun OverviewDescription(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(4.dp) .padding(4.dp)
// Самая важная магия: плавно анимирует высоту колонки при изменении maxLines текста
.animateContentSize(animationSpec = spring(stiffness = Spring.StiffnessMediumLow)) .animateContentSize(animationSpec = spring(stiffness = Spring.StiffnessMediumLow))
) { ) {
Text( Text(
@@ -307,7 +312,6 @@ private fun OverviewDescription(
overflow = TextOverflow.Ellipsis overflow = TextOverflow.Ellipsis
) )
// Вместо резкого 'if' плавно убираем кнопку разворачивания
AnimatedVisibility( AnimatedVisibility(
visible = !showDetails.value, visible = !showDetails.value,
enter = fadeIn(), enter = fadeIn(),
@@ -319,7 +323,7 @@ private fun OverviewDescription(
style = MaterialTheme.typography.bodyLarge, style = MaterialTheme.typography.bodyLarge,
color = MaterialTheme.colorScheme.primary, color = MaterialTheme.colorScheme.primary,
modifier = Modifier modifier = Modifier
.padding(top = 8.dp) // Небольшой отступ сверху от основного текста .padding(top = 8.dp)
.clickable { showDetails.value = true } .clickable { showDetails.value = true }
) )
} }
@@ -327,16 +331,49 @@ private fun OverviewDescription(
} }
@Composable @Composable
private fun OverviewTitle(details: VideoDetails) { private fun Poster(posterUrl: String, modifier: Modifier = Modifier) {
Box(contentAlignment = Alignment.Center, modifier = Modifier.fillMaxWidth()) { Box(
contentAlignment = Alignment.Center,
modifier = Modifier.fillMaxWidth()
) {
Card(
shape = RoundedCornerShape(12.dp),
colors = CardDefaults.cardColors(
containerColor = MaterialTheme.colorScheme.surfaceContainerLow
),
elevation = CardDefaults.cardElevation(
defaultElevation = 4.dp
),
modifier = modifier.height(200.dp)
.aspectRatio(0.7f)
) {
Box(modifier = Modifier.fillMaxSize()) {
Image( Image(
painter = rememberImagePainter(details.poster), painter = rememberImagePainter(posterUrl),
contentDescription = null, contentDescription = null,
modifier = Modifier
.padding(8.dp) // Добавим легкий отступ, чтобы картинка не липла к краям экрана
.clip(RoundedCornerShape(12.dp)), // На современных девайсах 12.dp выглядит аккуратнее, чем 8%
contentScale = ContentScale.Crop, contentScale = ContentScale.Crop,
modifier = Modifier.fillMaxSize()
)
Box(
modifier = Modifier.fillMaxSize()
.background(
Brush.verticalGradient(
0.6f to Color.Transparent,
1.0f to Color.Black.copy(alpha = 0.6f)
)
)
)
Box(
modifier = Modifier.fillMaxSize()
.border(
width = 1.dp,
color = Color.White.copy(alpha = 0.15f),
shape = RoundedCornerShape(12.dp)
)
) )
} }
} }
}
}