diff --git a/Jetcaster/gradle/libs.versions.toml b/Jetcaster/gradle/libs.versions.toml index 4a02af961..c4c2a6612 100644 --- a/Jetcaster/gradle/libs.versions.toml +++ b/Jetcaster/gradle/libs.versions.toml @@ -11,7 +11,7 @@ androidx-appcompat = "1.7.1" androidx-compose-bom = "2025.09.00" androidx-constraintlayout = "1.1.1" androidx-core-splashscreen = "1.0.1" -androidx-corektx = "1.16.0" +androidx-corektx = "1.17.0" androidx-glance = "1.1.1" androidx-lifecycle = "2.8.2" androidx-lifecycle-compose = "2.9.1" diff --git a/Jetcaster/mobile/src/main/java/com/example/jetcaster/ui/MainActivity.kt b/Jetcaster/mobile/src/main/java/com/example/jetcaster/ui/MainActivity.kt index d7cfca1a7..e01cdab3d 100644 --- a/Jetcaster/mobile/src/main/java/com/example/jetcaster/ui/MainActivity.kt +++ b/Jetcaster/mobile/src/main/java/com/example/jetcaster/ui/MainActivity.kt @@ -19,7 +19,7 @@ package com.example.jetcaster.ui import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent -import androidx.activity.enableEdgeToEdge +import androidx.core.view.WindowCompat import com.example.jetcaster.glancewidget.updateWidgetPreview import com.example.jetcaster.ui.theme.JetcasterTheme import com.google.accompanist.adaptive.calculateDisplayFeatures @@ -30,7 +30,7 @@ class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - enableEdgeToEdge() + WindowCompat.enableEdgeToEdge(window) updateWidgetPreview(this) setContent { val displayFeatures = calculateDisplayFeatures(this) diff --git a/Jetcaster/mobile/src/main/java/com/example/jetcaster/ui/home/Home.kt b/Jetcaster/mobile/src/main/java/com/example/jetcaster/ui/home/Home.kt index 7b363bfce..5dd9a5a57 100644 --- a/Jetcaster/mobile/src/main/java/com/example/jetcaster/ui/home/Home.kt +++ b/Jetcaster/mobile/src/main/java/com/example/jetcaster/ui/home/Home.kt @@ -28,10 +28,12 @@ import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.asPaddingValues import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.navigationBars +import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.windowInsetsPadding @@ -84,6 +86,7 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.geometry.Rect import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalLayoutDirection import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow @@ -393,9 +396,7 @@ private fun HomeScreen( val coroutineScope = rememberCoroutineScope() val snackbarHostState = remember { SnackbarHostState() } - HomeScreenBackground( - modifier = modifier.windowInsetsPadding(WindowInsets.navigationBars), - ) { + HomeScreenBackground { Scaffold( topBar = { Column { @@ -418,6 +419,7 @@ private fun HomeScreen( containerColor = Color.Transparent, ) { contentPadding -> // Main Content + val layoutDirection = LocalLayoutDirection.current val snackBarText = stringResource(id = R.string.episode_added_to_your_queue) val showHomeCategoryTabs = featuredPodcasts.isNotEmpty() && homeCategories.isNotEmpty() HomeContent( @@ -426,7 +428,19 @@ private fun HomeScreen( filterableCategoriesModel = filterableCategoriesModel, podcastCategoryFilterResult = podcastCategoryFilterResult, library = library, - modifier = Modifier.padding(contentPadding), + /** + * Edge-to-edge: + * Handles start, end and top insets allowing content to scroll behind the system navigation bar for an edge-to-edge look. + * Bottom insets are applied to the last list item in [HomeContentGrid]. + */ + modifier = modifier.padding( + PaddingValues( + start = contentPadding.calculateLeftPadding(layoutDirection), + end = contentPadding.calculateRightPadding(layoutDirection), + top = contentPadding.calculateTopPadding(), + bottom = 0.dp, + ) + ), onHomeAction = { action -> if (action is HomeAction.QueueEpisode) { coroutineScope.launch { @@ -454,7 +468,7 @@ private fun HomeScreen( @Composable fun PillToolbar(selectedHomeCategory: HomeCategory, onHomeAction: (HomeAction) -> Unit, modifier: Modifier = Modifier) { HorizontalFloatingToolbar( - modifier = modifier, + modifier = modifier.navigationBarsPadding(), colors = FloatingToolbarColors( toolbarContainerColor = MaterialTheme.colorScheme.surfaceContainerHighest, toolbarContentColor = MaterialTheme.colorScheme.onSurfaceVariant, @@ -585,6 +599,12 @@ private fun HomeContentGrid( LazyVerticalGrid( columns = GridCells.Adaptive(362.dp), modifier = modifier.fillMaxSize(), + /** + * Edge-to-edge: + * Allows content to scroll behind the system navigation bar while ensuring the last list item is still accessible. + * Top, start and end insets are handled in [HomeScreen]. + */ + contentPadding = WindowInsets.navigationBars.asPaddingValues() ) { when (selectedHomeCategory) { HomeCategory.Library -> { diff --git a/Jetcaster/mobile/src/main/java/com/example/jetcaster/ui/player/PlayerScreen.kt b/Jetcaster/mobile/src/main/java/com/example/jetcaster/ui/player/PlayerScreen.kt index 77536537f..551cc9fc1 100644 --- a/Jetcaster/mobile/src/main/java/com/example/jetcaster/ui/player/PlayerScreen.kt +++ b/Jetcaster/mobile/src/main/java/com/example/jetcaster/ui/player/PlayerScreen.kt @@ -29,7 +29,6 @@ import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.BoxWithConstraints import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.WindowInsets @@ -167,7 +166,7 @@ private fun PlayerScreen( SnackbarHost(hostState = snackbarHostState) }, modifier = modifier, - ) { contentPadding -> + ) { _ -> if (uiState.episodePlayerState.currentEpisode != null) { PlayerContentWithBackground( uiState = uiState, @@ -181,7 +180,6 @@ private fun PlayerScreen( onAddToQueue() }, playerControlActions = playerControlActions, - contentPadding = contentPadding, ) } else { FullScreenLoading() @@ -207,14 +205,11 @@ fun PlayerContentWithBackground( onAddToQueue: () -> Unit, playerControlActions: PlayerControlActions, modifier: Modifier = Modifier, - contentPadding: PaddingValues = PaddingValues(0.dp), ) { Box(modifier = modifier, contentAlignment = Alignment.Center) { PlayerBackground( episode = uiState.episodePlayerState.currentEpisode, - modifier = Modifier - .fillMaxSize() - .padding(contentPadding), + modifier = modifier.fillMaxSize() ) PlayerContent( uiState = uiState,