diff --git a/app/src/main/kotlin/com/imashnake/animite/features/MainActivity.kt b/app/src/main/kotlin/com/imashnake/animite/features/MainActivity.kt index af8bb3f6..1af57c0e 100644 --- a/app/src/main/kotlin/com/imashnake/animite/features/MainActivity.kt +++ b/app/src/main/kotlin/com/imashnake/animite/features/MainActivity.kt @@ -1,5 +1,6 @@ package com.imashnake.animite.features +import android.content.res.Configuration import android.os.Build import android.os.Bundle import android.view.WindowManager @@ -8,11 +9,16 @@ import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.SharedTransitionLayout +import androidx.compose.animation.slideInHorizontally import androidx.compose.animation.slideInVertically +import androidx.compose.animation.slideOutHorizontally import androidx.compose.animation.slideOutVertically import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.ExperimentalLayoutApi +import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.isImeVisible import androidx.compose.foundation.layout.padding import androidx.compose.material3.LocalContentColor import androidx.compose.material3.MaterialTheme @@ -22,12 +28,14 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalConfiguration import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.rememberNavController import androidx.navigation.navDeepLink import com.imashnake.animite.api.anilist.sanitize.media.MediaList +import com.imashnake.animite.core.extensions.orFalse import com.imashnake.animite.core.ui.LocalPaddings import com.imashnake.animite.features.home.HomeScreen import com.imashnake.animite.features.searchbar.SearchFrontDrop @@ -36,6 +44,7 @@ import com.imashnake.animite.media.MediaPage import com.imashnake.animite.navigation.HomeRoute import com.imashnake.animite.navigation.NavigationBar import com.imashnake.animite.navigation.NavigationBarPaths +import com.imashnake.animite.navigation.NavigationRail import com.imashnake.animite.navigation.ProfileRoute import com.imashnake.animite.navigation.SocialRoute import com.imashnake.animite.profile.ProfileScreen @@ -67,17 +76,18 @@ class MainActivity : ComponentActivity() { } } +@OptIn(ExperimentalLayoutApi::class) @Composable fun MainScreen(modifier: Modifier = Modifier) { val navController = rememberNavController() val currentBackStackEntry by navController.currentBackStackEntryAsState() val isNavBarVisible = remember(currentBackStackEntry) { - if (currentBackStackEntry != null) { - NavigationBarPaths.entries.any { it.matchesDestination(currentBackStackEntry!!) } - } else { - false - } + currentBackStackEntry?.let { + NavigationBarPaths.entries.any { path -> + path.matchesDestination(it) + } + }.orFalse() } // TODO: Refactor to use Scaffold once AnimatedVisibility issues are fixed; @@ -120,7 +130,8 @@ fun MainScreen(modifier: Modifier = Modifier) { } SearchFrontDrop( - hasExtraPadding = isNavBarVisible, + hasExtraPadding = isNavBarVisible && + (LocalConfiguration.current.orientation == Configuration.ORIENTATION_PORTRAIT), onItemClick = { id, mediaType -> navController.navigate( MediaPage( @@ -139,13 +150,23 @@ fun MainScreen(modifier: Modifier = Modifier) { ) ) - AnimatedVisibility( - visible = isNavBarVisible, - modifier = Modifier.align(Alignment.BottomCenter), - enter = slideInVertically { it }, - exit = slideOutVertically { it } - ) { - NavigationBar(navController = navController) + when(LocalConfiguration.current.orientation) { + Configuration.ORIENTATION_LANDSCAPE -> { + AnimatedVisibility( + visible = isNavBarVisible && !WindowInsets.isImeVisible, + modifier = Modifier.align(Alignment.CenterStart), + enter = slideInHorizontally { -it }, + exit = slideOutHorizontally { -it } + ) { NavigationRail(navController = navController) } + } + else -> { + AnimatedVisibility( + visible = isNavBarVisible, + modifier = Modifier.align(Alignment.BottomCenter), + enter = slideInVertically { it }, + exit = slideOutVertically { it } + ) { NavigationBar(navController = navController) } + } } } } diff --git a/app/src/main/kotlin/com/imashnake/animite/features/home/HomeScreen.kt b/app/src/main/kotlin/com/imashnake/animite/features/home/HomeScreen.kt index df5f739a..a0fd4a48 100644 --- a/app/src/main/kotlin/com/imashnake/animite/features/home/HomeScreen.kt +++ b/app/src/main/kotlin/com/imashnake/animite/features/home/HomeScreen.kt @@ -1,6 +1,7 @@ package com.imashnake.animite.features.home import android.annotation.SuppressLint +import android.content.res.Configuration import android.graphics.RuntimeShader import android.os.Build import androidx.compose.animation.AnimatedContent @@ -53,6 +54,7 @@ import androidx.compose.ui.graphics.ShaderBrush import androidx.compose.ui.graphics.toArgb import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource @@ -181,6 +183,9 @@ fun HomeScreen( start = LocalPaddings.current.large, bottom = LocalPaddings.current.medium ) + .thenIf(LocalConfiguration.current.orientation == Configuration.ORIENTATION_LANDSCAPE) { + padding(start = dimensionResource(navigationR.dimen.navigation_rail_width)) + } .landscapeCutoutPadding() .weight(1f, fill = false), maxLines = 1 @@ -240,8 +245,11 @@ fun HomeScreen( }, contentModifier = Modifier.padding( top = LocalPaddings.current.large / 2, - bottom = LocalPaddings.current.large / 2 + - dimensionResource(navigationR.dimen.navigation_bar_height) + bottom = LocalPaddings.current.large / 2, + ).thenIf( + condition = LocalConfiguration.current.orientation == Configuration.ORIENTATION_LANDSCAPE, + other = { padding(start = dimensionResource(navigationR.dimen.navigation_rail_width)) }, + elseOther = { padding(bottom = dimensionResource(navigationR.dimen.navigation_bar_height)) } ), verticalArrangement = Arrangement.spacedBy(0.dp) ) diff --git a/core/src/main/kotlin/com/imashnake/animite/core/extensions/BooleanExt.kt b/core/src/main/kotlin/com/imashnake/animite/core/extensions/BooleanExt.kt new file mode 100644 index 00000000..bad2644e --- /dev/null +++ b/core/src/main/kotlin/com/imashnake/animite/core/extensions/BooleanExt.kt @@ -0,0 +1,12 @@ +package com.imashnake.animite.core.extensions + +import kotlin.contracts.ExperimentalContracts +import kotlin.contracts.contract + +@OptIn(ExperimentalContracts::class) +fun Boolean?.orFalse(): Boolean { + contract { + returns(true) implies (this@orFalse != null) + } + return this == true +} diff --git a/core/src/main/kotlin/com/imashnake/animite/core/extensions/ModifierExt.kt b/core/src/main/kotlin/com/imashnake/animite/core/extensions/ModifierExt.kt index 815437b4..eaf8c271 100644 --- a/core/src/main/kotlin/com/imashnake/animite/core/extensions/ModifierExt.kt +++ b/core/src/main/kotlin/com/imashnake/animite/core/extensions/ModifierExt.kt @@ -4,6 +4,7 @@ import android.content.res.Configuration import androidx.compose.foundation.ScrollState import androidx.compose.foundation.layout.displayCutoutPadding import androidx.compose.foundation.layout.heightIn +import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.composed import androidx.compose.ui.graphics.graphicsLayer @@ -28,7 +29,9 @@ fun Modifier.maxHeight(max: Dp) = heightIn(0.dp, max) /** * [Adding modifiers conditionally in Jetpack Compose](https://patrickmichalik.com/blog/adding-modifiers-conditionally-in-jetpack-compose). */ +@Composable fun Modifier.thenIf( condition: Boolean, - other: Modifier.() -> Modifier, -) = if (condition) other() else this + elseOther: @Composable Modifier.() -> Modifier = { this }, + other: @Composable Modifier.() -> Modifier, +) = if (condition) other() else elseOther() diff --git a/core/src/main/kotlin/com/imashnake/animite/core/ui/layouts/BannerLayout.kt b/core/src/main/kotlin/com/imashnake/animite/core/ui/layouts/BannerLayout.kt index 40af740a..497315a6 100644 --- a/core/src/main/kotlin/com/imashnake/animite/core/ui/layouts/BannerLayout.kt +++ b/core/src/main/kotlin/com/imashnake/animite/core/ui/layouts/BannerLayout.kt @@ -50,7 +50,6 @@ fun BannerLayout( .fillMaxSize() .padding(top = bannerHeight) .background(MaterialTheme.colorScheme.background) - .navigationBarsPadding() .then(contentModifier), verticalArrangement = verticalArrangement ) { content() } diff --git a/navigation/src/main/kotlin/com/imashnake/animite/navigation/NavigationBar.kt b/navigation/src/main/kotlin/com/imashnake/animite/navigation/NavigationBar.kt index b33c2d83..f35f4265 100644 --- a/navigation/src/main/kotlin/com/imashnake/animite/navigation/NavigationBar.kt +++ b/navigation/src/main/kotlin/com/imashnake/animite/navigation/NavigationBar.kt @@ -1,48 +1,38 @@ package com.imashnake.animite.navigation import android.content.res.Configuration -import androidx.annotation.StringRes import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.asPaddingValues import androidx.compose.foundation.layout.displayCutout import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.navigationBars import androidx.compose.foundation.layout.navigationBarsPadding -import androidx.compose.material3.Icon import androidx.compose.material3.NavigationBar import androidx.compose.material3.NavigationBarItem import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.res.dimensionResource -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.res.vectorResource import androidx.compose.ui.unit.dp -import androidx.navigation.NavBackStackEntry import androidx.navigation.NavController -import androidx.navigation.NavDestination.Companion.hasRoute -import androidx.navigation.NavDestination.Companion.hierarchy -import androidx.navigation.NavGraph.Companion.findStartDestination import androidx.navigation.compose.currentBackStackEntryAsState @Composable fun NavigationBar( - navController: NavController + navController: NavController, + modifier: Modifier = Modifier, ) { val currentBackStackEntry by navController.currentBackStackEntryAsState() - - // TODO: Can we use `navigationBarsPadding()` instead? NavigationBar( - Modifier.height( + modifier = modifier.height( dimensionResource(R.dimen.navigation_bar_height) + WindowInsets .navigationBars .asPaddingValues() .calculateBottomPadding() ), - // TODO: Use a `NavigationRail` instead. + // TODO: Remove this after adding the rail. windowInsets = if (LocalConfiguration.current.orientation == Configuration.ORIENTATION_LANDSCAPE ) { WindowInsets.displayCutout } else { WindowInsets(0.dp) } @@ -52,74 +42,11 @@ fun NavigationBar( currentBackStackEntry?.let { destination.matchesDestination(it) } ?: false } NavigationBarItem( - modifier = Modifier.navigationBarsPadding(), selected = selected, - onClick = { - if (!selected) destination.navigateTo(navController) - }, - icon = destination.icon + onClick = { if (!selected) destination.navigateTo(navController) }, + icon = destination.icon, + modifier = Modifier.navigationBarsPadding(), ) } } } - -enum class NavigationBarPaths( - val navigateTo: (NavController) -> Unit, - val matchesDestination: (NavBackStackEntry) -> Boolean, - val icon: @Composable () -> Unit, - @StringRes val labelRes: Int -) { - Social( - navigateTo = { - it.navigate(SocialRoute) { - popUpTo(id = it.graph.findStartDestination().id) { - saveState = true - } - launchSingleTop = true - } - }, - matchesDestination = { - it.destination.hierarchy.any { it.hasRoute(SocialRoute::class) } - }, - icon = { - Icon(ImageVector.vectorResource(R.drawable.social), contentDescription = stringResource(R.string.social)) - }, - labelRes = R.string.social - ), - Home( - navigateTo = { - it.navigate(HomeRoute) { - popUpTo(id = it.graph.findStartDestination().id) { - saveState = true - inclusive = true - } - launchSingleTop = true - } - }, - matchesDestination = { - it.destination.hierarchy.any { it.hasRoute(HomeRoute::class) } - }, - icon = { - Icon(ImageVector.vectorResource(R.drawable.home), contentDescription = stringResource(R.string.home)) - }, - labelRes = R.string.home - ), - - Profile( - navigateTo = { - it.navigate(ProfileRoute()) { - popUpTo(id = it.graph.findStartDestination().id) { - saveState = true - } - launchSingleTop = true - } - }, - matchesDestination = { - it.destination.hierarchy.any { it.hasRoute(ProfileRoute::class) } - }, - icon = { - Icon(ImageVector.vectorResource(R.drawable.profile), contentDescription = stringResource(R.string.profile)) - }, - labelRes = R.string.profile - ), -} \ No newline at end of file diff --git a/navigation/src/main/kotlin/com/imashnake/animite/navigation/NavigationPaths.kt b/navigation/src/main/kotlin/com/imashnake/animite/navigation/NavigationPaths.kt new file mode 100644 index 00000000..b3cb9673 --- /dev/null +++ b/navigation/src/main/kotlin/com/imashnake/animite/navigation/NavigationPaths.kt @@ -0,0 +1,74 @@ +package com.imashnake.animite.navigation + +import androidx.annotation.StringRes +import androidx.compose.material3.Icon +import androidx.compose.runtime.Composable +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.res.vectorResource +import androidx.navigation.NavBackStackEntry +import androidx.navigation.NavController +import androidx.navigation.NavDestination.Companion.hasRoute +import androidx.navigation.NavDestination.Companion.hierarchy +import androidx.navigation.NavGraph.Companion.findStartDestination + +enum class NavigationBarPaths( + val navigateTo: (NavController) -> Unit, + val matchesDestination: (NavBackStackEntry) -> Boolean, + val icon: @Composable () -> Unit, + @StringRes val labelRes: Int +) { + Social( + navigateTo = { + it.navigate(SocialRoute) { + popUpTo(id = it.graph.findStartDestination().id) { + saveState = true + } + launchSingleTop = true + } + }, + matchesDestination = { + it.destination.hierarchy.any { it.hasRoute(SocialRoute::class) } + }, + icon = { + Icon(ImageVector.vectorResource(R.drawable.social), contentDescription = stringResource(R.string.social)) + }, + labelRes = R.string.social + ), + Home( + navigateTo = { + it.navigate(HomeRoute) { + popUpTo(id = it.graph.findStartDestination().id) { + saveState = true + inclusive = true + } + launchSingleTop = true + } + }, + matchesDestination = { + it.destination.hierarchy.any { it.hasRoute(HomeRoute::class) } + }, + icon = { + Icon(ImageVector.vectorResource(R.drawable.home), contentDescription = stringResource(R.string.home)) + }, + labelRes = R.string.home + ), + + Profile( + navigateTo = { + it.navigate(ProfileRoute()) { + popUpTo(id = it.graph.findStartDestination().id) { + saveState = true + } + launchSingleTop = true + } + }, + matchesDestination = { + it.destination.hierarchy.any { it.hasRoute(ProfileRoute::class) } + }, + icon = { + Icon(ImageVector.vectorResource(R.drawable.profile), contentDescription = stringResource(R.string.profile)) + }, + labelRes = R.string.profile + ), +} diff --git a/navigation/src/main/kotlin/com/imashnake/animite/navigation/NavigationRail.kt b/navigation/src/main/kotlin/com/imashnake/animite/navigation/NavigationRail.kt new file mode 100644 index 00000000..bfcfb137 --- /dev/null +++ b/navigation/src/main/kotlin/com/imashnake/animite/navigation/NavigationRail.kt @@ -0,0 +1,51 @@ +package com.imashnake.animite.navigation + +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.WindowInsetsSides +import androidx.compose.foundation.layout.add +import androidx.compose.foundation.layout.asPaddingValues +import androidx.compose.foundation.layout.displayCutout +import androidx.compose.foundation.layout.navigationBarsPadding +import androidx.compose.foundation.layout.only +import androidx.compose.foundation.layout.statusBars +import androidx.compose.foundation.layout.width +import androidx.compose.material3.NavigationRailItem +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.dimensionResource +import androidx.compose.ui.unit.LayoutDirection +import androidx.navigation.NavController +import androidx.navigation.compose.currentBackStackEntryAsState +import androidx.compose.material3.NavigationRail as M3NavigationRail + +@Composable +fun NavigationRail( + navController: NavController, + modifier: Modifier = Modifier, +) { + val currentBackStackEntry by navController.currentBackStackEntryAsState() + // TODO: This uses `background` as `containerColor`, I have no idea why. + M3NavigationRail( + modifier = modifier.width( + dimensionResource(R.dimen.navigation_rail_width) + WindowInsets + .displayCutout + .asPaddingValues() + .calculateLeftPadding(LayoutDirection.Ltr) + ), + windowInsets = WindowInsets.displayCutout.only(WindowInsetsSides.Left).add(WindowInsets.statusBars) + ) { + NavigationBarPaths.entries.forEach { destination -> + val selected = remember(destination, currentBackStackEntry) { + currentBackStackEntry?.let { destination.matchesDestination(it) } ?: false + } + NavigationRailItem( + selected = selected, + onClick = { if (!selected) destination.navigateTo(navController) }, + icon = destination.icon, + modifier = Modifier.navigationBarsPadding(), + ) + } + } +} diff --git a/navigation/src/main/res/values/dimens.xml b/navigation/src/main/res/values/dimens.xml index cd4adde5..e109066e 100644 --- a/navigation/src/main/res/values/dimens.xml +++ b/navigation/src/main/res/values/dimens.xml @@ -1,4 +1,5 @@ 65dp + 80dp diff --git a/profile/src/main/kotlin/com/imashnake/animite/profile/ProfileScreen.kt b/profile/src/main/kotlin/com/imashnake/animite/profile/ProfileScreen.kt index eeb3656f..a0f43a91 100644 --- a/profile/src/main/kotlin/com/imashnake/animite/profile/ProfileScreen.kt +++ b/profile/src/main/kotlin/com/imashnake/animite/profile/ProfileScreen.kt @@ -1,11 +1,13 @@ package com.imashnake.animite.profile +import android.content.res.Configuration import androidx.compose.animation.AnimatedVisibilityScope import androidx.compose.animation.SharedTransitionScope import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.displayCutoutPadding import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size @@ -27,6 +29,7 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow @@ -40,10 +43,9 @@ import com.imashnake.animite.core.data.Resource import com.imashnake.animite.core.extensions.animiteBlockQuoteStyle import com.imashnake.animite.core.extensions.animiteCodeBlockStyle import com.imashnake.animite.core.extensions.crossfadeModel -import com.imashnake.animite.core.extensions.landscapeCutoutPadding import com.imashnake.animite.core.extensions.maxHeight +import com.imashnake.animite.core.extensions.thenIf import com.imashnake.animite.core.ui.FallbackMessage -import com.imashnake.animite.core.ui.FallbackScreen import com.imashnake.animite.core.ui.LocalPaddings import com.imashnake.animite.core.ui.NestedScrollableContent import com.imashnake.animite.core.ui.ProgressIndicatorScreen @@ -72,74 +74,78 @@ fun ProfileScreen( val data = listOf(viewer, viewerAnimeLists, viewerMangaLists) - Box( - contentAlignment = Alignment.Center, - modifier = Modifier - .fillMaxSize() - .background(MaterialTheme.colorScheme.background) - ) { - when { - isLoggedIn -> when { - data.all { it is Resource.Success } -> viewer.data?.run { - BannerLayout( - banner = { - Box { - AsyncImage( - model = crossfadeModel(banner), - contentDescription = "banner", - modifier = it, - contentScale = ContentScale.Crop - ) - AsyncImage( - model = crossfadeModel(avatar), - contentDescription = "avatar", - modifier = Modifier - .align(Alignment.BottomStart) - .landscapeCutoutPadding() - .padding(start = LocalPaddings.current.medium) - .size(100.dp) - ) - } - }, - content = { - Column { - Text( - text = name, - color = MaterialTheme.colorScheme.onBackground, - style = MaterialTheme.typography.titleLarge, - overflow = TextOverflow.Ellipsis, - modifier = Modifier - .padding(horizontal = LocalPaddings.current.large) - .landscapeCutoutPadding() - ) - UserDescription( - description = description, - modifier = Modifier - .maxHeight(dimensionResource(R.dimen.user_about_height)) - .padding(horizontal = LocalPaddings.current.large) - .landscapeCutoutPadding() - ) - Spacer(Modifier.size(LocalPaddings.current.medium)) - UserTabs( - user = this@run, - animeCollection = viewerAnimeLists.data, - mangaCollection = viewerMangaLists.data, - onNavigateToMediaItem = onNavigateToMediaItem, - sharedTransitionScope = sharedTransitionScope, - animatedVisibilityScope = animatedVisibilityScope, - ) - } - }, - contentModifier = Modifier.padding( - top = LocalPaddings.current.large, - bottom = dimensionResource(navigationR.dimen.navigation_bar_height) - ) - ) - } - else -> ProgressIndicatorScreen() + when { + isLoggedIn -> when { + data.all { it is Resource.Success } -> viewer.data?.run { + BannerLayout( + banner = { + Box { + AsyncImage( + model = crossfadeModel(banner), + contentDescription = "banner", + modifier = it, + contentScale = ContentScale.Crop + ) + AsyncImage( + model = crossfadeModel(avatar), + contentDescription = "avatar", + modifier = Modifier + .align(Alignment.BottomStart) + .padding(start = LocalPaddings.current.medium) + .thenIf(LocalConfiguration.current.orientation == Configuration.ORIENTATION_LANDSCAPE) { + padding(start = dimensionResource(navigationR.dimen.navigation_rail_width)) + .displayCutoutPadding() + } + .size(100.dp) + ) + } + }, + content = { + Column { + Text( + text = name, + color = MaterialTheme.colorScheme.onBackground, + style = MaterialTheme.typography.titleLarge, + overflow = TextOverflow.Ellipsis, + modifier = Modifier + .padding(horizontal = LocalPaddings.current.large) + .thenIf(LocalConfiguration.current.orientation == Configuration.ORIENTATION_LANDSCAPE) { + padding(start = dimensionResource(navigationR.dimen.navigation_rail_width)) + .displayCutoutPadding() + } + ) + UserDescription( + description = description, + modifier = Modifier + .maxHeight(dimensionResource(R.dimen.user_about_height)) + .padding(horizontal = LocalPaddings.current.large) + .thenIf(LocalConfiguration.current.orientation == Configuration.ORIENTATION_LANDSCAPE) { + padding(start = dimensionResource(navigationR.dimen.navigation_rail_width)) + .displayCutoutPadding() + } + ) + Spacer(Modifier.size(LocalPaddings.current.medium)) + UserTabs( + user = this@run, + animeCollection = viewerAnimeLists.data, + mangaCollection = viewerMangaLists.data, + onNavigateToMediaItem = onNavigateToMediaItem, + sharedTransitionScope = sharedTransitionScope, + animatedVisibilityScope = animatedVisibilityScope, + ) + } + }, + contentModifier = Modifier + .padding(top = LocalPaddings.current.large) + .thenIf( + condition = LocalConfiguration.current.orientation == Configuration.ORIENTATION_PORTRAIT, + other = { padding(bottom = dimensionResource(navigationR.dimen.navigation_bar_height)) } + ), + ) } - else -> Login() + else -> ProgressIndicatorScreen() } + else -> Login() } } @@ -184,7 +190,10 @@ private fun UserTabs( Column(modifier) { PrimaryTabRow( selectedTabIndex = pagerState.currentPage, - modifier = Modifier.landscapeCutoutPadding(), + modifier = Modifier.thenIf(LocalConfiguration.current.orientation == Configuration.ORIENTATION_LANDSCAPE) { + padding(start = dimensionResource(navigationR.dimen.navigation_rail_width)) + .displayCutoutPadding() + }, containerColor = MaterialTheme.colorScheme.background, divider = {} ) { diff --git a/profile/src/main/kotlin/com/imashnake/animite/profile/tabs/About.kt b/profile/src/main/kotlin/com/imashnake/animite/profile/tabs/About.kt index e4f87184..4b2ef9c8 100644 --- a/profile/src/main/kotlin/com/imashnake/animite/profile/tabs/About.kt +++ b/profile/src/main/kotlin/com/imashnake/animite/profile/tabs/About.kt @@ -69,7 +69,6 @@ fun AboutTab( stats = statsLabelToValue, modifier = Modifier .fillMaxWidth() - .landscapeCutoutPadding() ) { Text( text = it.first, diff --git a/profile/src/main/kotlin/com/imashnake/animite/profile/tabs/Media.kt b/profile/src/main/kotlin/com/imashnake/animite/profile/tabs/Media.kt index 38dc7bb2..5a73b4ce 100644 --- a/profile/src/main/kotlin/com/imashnake/animite/profile/tabs/Media.kt +++ b/profile/src/main/kotlin/com/imashnake/animite/profile/tabs/Media.kt @@ -13,6 +13,7 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.util.fastForEach import com.imashnake.animite.api.anilist.sanitize.media.Media import com.imashnake.animite.api.anilist.sanitize.profile.User +import com.imashnake.animite.core.extensions.orFalse import com.imashnake.animite.core.ui.FallbackScreen import com.imashnake.animite.core.ui.LocalPaddings import com.imashnake.animite.core.ui.MediaCard @@ -42,7 +43,7 @@ fun MediaTab( val scrollState = rememberScrollState() when { - mediaCollection?.namedLists?.isEmpty() == true -> { + mediaCollection?.namedLists?.isEmpty().orFalse() -> { FallbackScreen( stringResource( when (mediaCollection.type) { @@ -58,10 +59,9 @@ fun MediaTab( .verticalScroll(scrollState) .padding(vertical = LocalPaddings.current.large) ) { - // TODO: Why is this not smart-casting? if (!mediaCollection?.namedLists.isNullOrEmpty()) { UserMediaLists( - lists = mediaCollection!!.namedLists, + lists = mediaCollection.namedLists, onNavigateToMediaItem = onNavigateToMediaItem, sharedTransitionScope = sharedTransitionScope, animatedVisibilityScope = animatedVisibilityScope,