remove debug isTv hardcode, update ui

This commit is contained in:
2026-07-27 20:43:02 +03:00
parent 14a10e6d08
commit 9915e4ddd5
4 changed files with 19 additions and 34 deletions
@@ -150,18 +150,14 @@ fun VideosInfo(
val requester = remember { FocusRequester() } val requester = remember { FocusRequester() }
val blur = LocalBlurState.current val blur = LocalBlurState.current
val gridState = rememberLazyGridState() val gridState = rememberLazyGridState()
Box(modifier = Modifier.fillMaxSize().padding(4.dp)) {
Box(modifier = Modifier.fillMaxSize()) {
if (items.isNotEmpty()) { if (items.isNotEmpty()) {
LazyVerticalGrid( LazyVerticalGrid(
columns = GridCells.Adaptive(minSize = 130.dp), columns = GridCells.Adaptive(minSize = 130.dp),
modifier = Modifier modifier = Modifier.fillMaxSize().applyBlurSource(blur),
.fillMaxSize()
.padding(8.dp)
.applyBlurSource(blur),
contentPadding = paddingValues, contentPadding = paddingValues,
verticalArrangement = Arrangement.spacedBy(12.dp), verticalArrangement = Arrangement.spacedBy(4.dp),
horizontalArrangement = Arrangement.spacedBy(12.dp), horizontalArrangement = Arrangement.spacedBy(4.dp),
state = gridState state = gridState
) { ) {
itemsIndexed( itemsIndexed(
@@ -181,8 +177,6 @@ fun VideosInfo(
VideosNotFound(emptyResource) VideosNotFound(emptyResource)
} }
} }
// Мягкий фокус без withFrameNanos, реагирующий на появление данных
LaunchedEffect(items.isNotEmpty()) { LaunchedEffect(items.isNotEmpty()) {
if (items.isNotEmpty()) { if (items.isNotEmpty()) {
requester.requestFocus() requester.requestFocus()
@@ -199,21 +193,18 @@ fun Poster(
) { ) {
var isFocused by remember { mutableStateOf(false) } var isFocused by remember { mutableStateOf(false) }
// Анимируем увеличение карточки при фокусе (эффект для ТВ)
val scale by animateFloatAsState( val scale by animateFloatAsState(
targetValue = if (isFocused) 1.08f else 1.0f, targetValue = if (isFocused) 1.0f else 0.92f,
animationSpec = spring(stiffness = Spring.StiffnessMediumLow), animationSpec = spring(stiffness = Spring.StiffnessMediumLow),
label = "scale" label = "scale"
) )
// Плавная анимация цвета обводки
val borderColor by animateColorAsState( val borderColor by animateColorAsState(
targetValue = if (isFocused) MaterialTheme.colorScheme.primary else Color.Transparent, targetValue = if (isFocused) MaterialTheme.colorScheme.primary else Color.Transparent,
animationSpec = tween(200), animationSpec = tween(200),
label = "borderColor" label = "borderColor"
) )
// Плавная анимация толщины обводки
val borderWidth by animateDpAsState( val borderWidth by animateDpAsState(
targetValue = if (isFocused) 3.dp else 0.dp, targetValue = if (isFocused) 3.dp else 0.dp,
animationSpec = tween(200), animationSpec = tween(200),
@@ -222,9 +213,8 @@ fun Poster(
Box( Box(
modifier = modifier modifier = modifier
.aspectRatio(0.7f) // Стандартное кинематографическое соотношение для постеров .aspectRatio(0.7f)
.graphicsLayer { .graphicsLayer {
// Применяем масштаб и скругление на уровне слоя (работает максимально быстро)
scaleX = scale scaleX = scale
scaleY = scale scaleY = scale
clip = true clip = true
@@ -238,27 +228,22 @@ fun Poster(
) )
.clickable(onClick = onClick) .clickable(onClick = onClick)
) { ) {
// Картинка постера
Image( Image(
painter = rememberImagePainter(imageUrl), painter = rememberImagePainter(imageUrl),
contentDescription = null, contentDescription = null,
contentScale = ContentScale.Crop, contentScale = ContentScale.Crop,
modifier = Modifier.fillMaxSize() modifier = Modifier.fillMaxSize()
) )
// Оптимизированный затемняющий градиент (снизу вверх)
Box( Box(
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
.background( .background(
Brush.verticalGradient( Brush.verticalGradient(
0.4f to Color.Transparent, // До 40% высоты прозрачно 0.4f to Color.Transparent,
1.0f to Color.Black.copy(alpha = 0.85f) // К низу плотное затемнение 1.0f to Color.Black.copy(alpha = 0.85f)
) )
) )
) )
// Текст названия фильма/сериала
Text( Text(
text = label, text = label,
style = MaterialTheme.typography.bodyMedium.copy( style = MaterialTheme.typography.bodyMedium.copy(
@@ -4,11 +4,14 @@ import android.app.UiModeManager
import android.content.Context import android.content.Context
import android.content.res.Configuration import android.content.res.Configuration
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
@Composable @Composable
actual fun isTv(): Boolean { actual fun isTv(): Boolean {
val context = LocalContext.current val context = LocalContext.current
return remember(context) {
val uiModeManager = context.getSystemService(Context.UI_MODE_SERVICE) as UiModeManager val uiModeManager = context.getSystemService(Context.UI_MODE_SERVICE) as UiModeManager
return uiModeManager.currentModeType == Configuration.UI_MODE_TYPE_TELEVISION uiModeManager.currentModeType == Configuration.UI_MODE_TYPE_TELEVISION
}
} }
@@ -17,7 +17,6 @@ import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialExpressiveTheme import androidx.compose.material3.MaterialExpressiveTheme
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.NavigationBar import androidx.compose.material3.NavigationBar
import androidx.compose.material3.NavigationBarItem import androidx.compose.material3.NavigationBarItem
import androidx.compose.material3.NavigationRail import androidx.compose.material3.NavigationRail
@@ -161,10 +160,7 @@ private fun <T : Route> ExpandedContent(
val bottomPadding = values.calculateBottomPadding() val bottomPadding = values.calculateBottomPadding()
val endPadding = values.calculateEndPadding(LayoutDirection.Ltr) val endPadding = values.calculateEndPadding(LayoutDirection.Ltr)
Row(modifier = Modifier.fillMaxSize()) { Row(modifier = Modifier.fillMaxSize()) {
NavigationRail( NavigationRail(modifier = Modifier.padding(start = 4.dp, end = 4.dp, top = topPadding)) {
modifier = Modifier.padding(start = 4.dp, end = 4.dp, top = topPadding),
containerColor = MaterialTheme.colorScheme.surfaceContainerLow
) {
navigationEntries.forEach { entry -> navigationEntries.forEach { entry ->
NavigationRailItem( NavigationRailItem(
selected = currentRoute == entry.route, selected = currentRoute == entry.route,
@@ -27,7 +27,7 @@ fun AlertContent(
@Composable @Composable
fun BaseDialogLayout() { fun BaseDialogLayout() {
Column( Column(
modifier = Modifier.padding(8.dp), modifier = Modifier.padding(16.dp),
verticalArrangement = Arrangement.spacedBy(6.dp) verticalArrangement = Arrangement.spacedBy(6.dp)
) { ) {
title?.let { title?.let {
@@ -51,9 +51,10 @@ fun AlertContent(
) { ) {
Surface( Surface(
shape = MaterialTheme.shapes.extraLarge, shape = MaterialTheme.shapes.extraLarge,
color = MaterialTheme.colorScheme.surface, color = MaterialTheme.colorScheme.surface
tonalElevation = 6.dp ) {
) { BaseDialogLayout() } BaseDialogLayout()
}
} }
} else { } else {
ModalBottomSheet( ModalBottomSheet(