feat: Add NuvioBackButton component for consistent back navigation across screens

This commit is contained in:
tapframe 2026-03-28 21:13:32 +05:30
parent 36552b4237
commit 8cb71ff91a
8 changed files with 88 additions and 105 deletions

View file

@ -20,6 +20,7 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.statusBars
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
@ -41,7 +42,9 @@ import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
@ -200,6 +203,34 @@ fun NuvioIconActionButton(
}
}
@Composable
fun NuvioBackButton(
onClick: () -> Unit,
modifier: Modifier = Modifier,
shape: Shape = CircleShape,
containerColor: Color = MaterialTheme.colorScheme.surface,
contentColor: Color = MaterialTheme.colorScheme.onSurface,
buttonSize: Dp = 40.dp,
iconSize: Dp = 22.dp,
contentDescription: String = "Back",
) {
Box(
modifier = modifier
.size(buttonSize)
.clip(shape)
.background(containerColor)
.clickable(onClick = onClick),
contentAlignment = Alignment.Center,
) {
Icon(
imageVector = Icons.AutoMirrored.Rounded.ArrowBack,
contentDescription = contentDescription,
tint = contentColor,
modifier = Modifier.size(iconSize),
)
}
}
@Composable
fun NuvioPrimaryButton(
text: String,

View file

@ -1,7 +1,9 @@
package com.nuvio.app.core.ui
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material3.LocalRippleConfiguration
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.RippleConfiguration
import androidx.compose.material3.Typography
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.material3.darkColorScheme
@ -130,6 +132,10 @@ private val NuvioTypeTokens = NuvioTypeScale(
),
)
private val NuvioRippleConfiguration = RippleConfiguration(
color = Color.Black,
)
@Composable
fun NuvioTheme(
darkTheme: Boolean = isSystemInDarkTheme(),
@ -142,6 +148,7 @@ fun NuvioTheme(
fontScale = 1f,
),
LocalNuvioTypeScale provides NuvioTypeTokens,
LocalRippleConfiguration provides NuvioRippleConfiguration,
) {
MaterialTheme(
colorScheme = if (darkTheme) NuvioDarkColors else NuvioDarkColors,

View file

@ -1,7 +1,6 @@
package com.nuvio.app.features.catalog
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
@ -18,12 +17,8 @@ import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.lazy.grid.GridItemSpan
import androidx.compose.foundation.lazy.grid.items
import androidx.compose.foundation.lazy.grid.rememberLazyGridState
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.rounded.ArrowBack
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
@ -44,6 +39,7 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import coil3.compose.AsyncImage
import com.nuvio.app.core.ui.NuvioBackButton
import com.nuvio.app.core.ui.posterCardClickable
import com.nuvio.app.core.ui.nuvioPlatformExtraBottomPadding
import com.nuvio.app.features.home.MetaPreview
@ -158,20 +154,14 @@ private fun CatalogHeader(
.padding(horizontal = 16.dp)
.padding(top = 52.dp, bottom = 12.dp),
) {
Box(
NuvioBackButton(
onClick = onBack,
modifier = Modifier
.size(40.dp)
.clip(CircleShape)
.background(MaterialTheme.colorScheme.surface)
.clickable(onClick = onBack),
contentAlignment = Alignment.Center,
) {
Icon(
imageVector = Icons.AutoMirrored.Rounded.ArrowBack,
contentDescription = "Back",
tint = MaterialTheme.colorScheme.onSurface,
)
}
.size(40.dp),
containerColor = MaterialTheme.colorScheme.surface,
contentColor = MaterialTheme.colorScheme.onSurface,
iconSize = 24.dp,
)
Spacer(modifier = Modifier.height(16.dp))
Text(
text = title,

View file

@ -3,7 +3,6 @@ package com.nuvio.app.features.details
import androidx.compose.animation.core.Animatable
import androidx.compose.animation.core.tween
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
@ -19,13 +18,9 @@ import androidx.compose.foundation.layout.safeDrawing
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.rounded.ArrowBack
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
@ -37,6 +32,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.nuvio.app.core.ui.NuvioBackButton
import com.nuvio.app.core.ui.nuvioPlatformExtraBottomPadding
import com.nuvio.app.features.details.components.DetailActionButtons
import com.nuvio.app.features.details.components.DetailCastSection
@ -246,24 +242,14 @@ fun MetaDetailsScreen(
}
// Back button overlay
Box(
NuvioBackButton(
onClick = onBack,
modifier = Modifier
.windowInsetsPadding(WindowInsets.safeDrawing.only(WindowInsetsSides.Top))
.padding(start = 12.dp, top = 8.dp)
.size(40.dp)
.background(
color = MaterialTheme.colorScheme.background.copy(alpha = 0.5f),
shape = CircleShape,
)
.clickable(onClick = onBack),
contentAlignment = Alignment.Center,
) {
Icon(
imageVector = Icons.AutoMirrored.Rounded.ArrowBack,
contentDescription = "Back",
tint = MaterialTheme.colorScheme.onBackground,
modifier = Modifier.size(22.dp),
)
}
,
containerColor = MaterialTheme.colorScheme.background.copy(alpha = 0.5f),
contentColor = MaterialTheme.colorScheme.onBackground,
)
}
}

View file

@ -20,7 +20,6 @@ import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.rounded.ArrowBack
import androidx.compose.material.icons.rounded.AspectRatio
import androidx.compose.material.icons.rounded.Forward10
import androidx.compose.material.icons.rounded.Pause
@ -46,6 +45,7 @@ import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import com.nuvio.app.core.ui.NuvioBackButton
import com.nuvio.app.core.ui.nuvioTypeScale
@Composable
@ -240,21 +240,14 @@ private fun PlayerHeader(
)
}
Box(
modifier = Modifier
.clip(CircleShape)
.background(Color.Black.copy(alpha = 0.35f))
.clickable(onClick = onBack)
.padding(8.dp),
contentAlignment = Alignment.Center,
) {
Icon(
imageVector = Icons.AutoMirrored.Rounded.ArrowBack,
contentDescription = "Close player",
tint = Color.White,
modifier = Modifier.size(metrics.headerIconSize),
)
}
NuvioBackButton(
onClick = onBack,
containerColor = Color.Black.copy(alpha = 0.35f),
contentColor = Color.White,
buttonSize = metrics.headerIconSize + 16.dp,
iconSize = metrics.headerIconSize,
contentDescription = "Close player",
)
}
}
}

View file

@ -21,7 +21,6 @@ import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.rounded.ArrowBack
import androidx.compose.material.icons.rounded.ErrorOutline
import androidx.compose.material.icons.rounded.Speed
import androidx.compose.material3.CircularProgressIndicator
@ -43,6 +42,7 @@ import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import coil3.compose.AsyncImage
import com.nuvio.app.core.ui.NuvioBackButton
import com.nuvio.app.core.ui.nuvioTypeScale
import kotlin.math.max
@ -81,24 +81,19 @@ internal fun OpeningOverlay(
)
}
Box(
NuvioBackButton(
onClick = onBack,
modifier = Modifier
.align(Alignment.TopEnd)
.windowInsetsPadding(WindowInsets.safeContent.only(WindowInsetsSides.Top))
.padding(top = 20.dp, start = horizontalSafePadding, end = horizontalSafePadding + 20.dp)
.clip(CircleShape)
.background(Color.Black.copy(alpha = 0.3f))
.clickable(onClick = onBack)
.padding(10.dp),
contentAlignment = Alignment.Center,
) {
Icon(
imageVector = Icons.AutoMirrored.Rounded.ArrowBack,
contentDescription = "Close player",
tint = Color.White,
modifier = Modifier.size(24.dp),
)
}
,
containerColor = Color.Black.copy(alpha = 0.3f),
contentColor = Color.White,
buttonSize = 44.dp,
iconSize = 24.dp,
contentDescription = "Close player",
)
Column(
modifier = Modifier

View file

@ -17,7 +17,6 @@ import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.widthIn
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.rounded.ArrowBack
import androidx.compose.material.icons.automirrored.rounded.ArrowForward
import androidx.compose.material.icons.rounded.KeyboardArrowDown
import androidx.compose.material.icons.rounded.KeyboardArrowUp
@ -39,6 +38,7 @@ import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import com.nuvio.app.core.ui.NuvioBackButton
import com.nuvio.app.core.ui.NuvioSectionLabel
import com.nuvio.app.features.home.HomeCatalogSettingsItem
@ -96,25 +96,16 @@ internal fun TabletPageHeader(
horizontalArrangement = Arrangement.spacedBy(12.dp),
) {
if (showBack) {
Surface(
NuvioBackButton(
onClick = onBack,
modifier = Modifier
.size(36.dp)
.clickable(onClick = onBack),
color = MaterialTheme.colorScheme.surface,
.size(36.dp),
shape = RoundedCornerShape(12.dp),
) {
Row(
modifier = Modifier.fillMaxSize(),
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically,
) {
Icon(
imageVector = Icons.AutoMirrored.Rounded.ArrowBack,
contentDescription = "Back",
tint = MaterialTheme.colorScheme.onSurface,
)
}
}
containerColor = MaterialTheme.colorScheme.surface,
contentColor = MaterialTheme.colorScheme.onSurface,
buttonSize = 36.dp,
iconSize = 20.dp,
)
}
Text(
text = title,

View file

@ -33,7 +33,6 @@ import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.rounded.ArrowBack
import androidx.compose.material.icons.rounded.Refresh
import androidx.compose.material.icons.rounded.SearchOff
import androidx.compose.material3.CircularProgressIndicator
@ -58,6 +57,7 @@ import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.nuvio.app.core.ui.NuvioBackButton
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import coil3.compose.AsyncImage
import com.nuvio.app.core.ui.nuvioPlatformExtraBottomPadding
@ -210,23 +210,13 @@ fun StreamsScreen(
.padding(start = 12.dp, top = 8.dp),
horizontalArrangement = Arrangement.spacedBy(8.dp),
) {
Box(
NuvioBackButton(
onClick = onBack,
modifier = Modifier
.size(40.dp)
.background(
color = MaterialTheme.colorScheme.background.copy(alpha = 0.45f),
shape = CircleShape,
)
.clickable(onClick = onBack),
contentAlignment = Alignment.Center,
) {
Icon(
imageVector = Icons.AutoMirrored.Rounded.ArrowBack,
contentDescription = "Back",
tint = MaterialTheme.colorScheme.onBackground,
modifier = Modifier.size(22.dp),
)
}
.size(40.dp),
containerColor = MaterialTheme.colorScheme.background.copy(alpha = 0.45f),
contentColor = MaterialTheme.colorScheme.onBackground,
)
Box(
modifier = Modifier