diff --git a/app/build.gradle.kts b/app/build.gradle.kts index df150ca2..25718c62 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -59,8 +59,9 @@ kotlin { dependencies { implementation(projects.api.anilist) implementation(projects.core) + implementation(projects.navigation) implementation(projects.profile) - implementation(projects.rslash) + implementation(projects.social) implementation(projects.materialColorUtilities) // AndroidX diff --git a/app/src/main/java/com/imashnake/animite/features/MainActivity.kt b/app/src/main/java/com/imashnake/animite/features/MainActivity.kt index 397b0eb7..fd327a26 100644 --- a/app/src/main/java/com/imashnake/animite/features/MainActivity.kt +++ b/app/src/main/java/com/imashnake/animite/features/MainActivity.kt @@ -30,17 +30,17 @@ import androidx.navigation.compose.rememberNavController import androidx.navigation.navDeepLink import com.imashnake.animite.api.anilist.sanitize.media.MediaList import com.imashnake.animite.core.ui.LocalPaddings -import com.imashnake.animite.features.home.Home import com.imashnake.animite.features.home.HomeScreen import com.imashnake.animite.features.media.MediaPage -import com.imashnake.animite.features.navigationbar.NavigationBar -import com.imashnake.animite.features.navigationbar.NavigationBarPaths import com.imashnake.animite.features.searchbar.SearchFrontDrop import com.imashnake.animite.features.theme.AnimiteTheme -import com.imashnake.animite.profile.Profile +import com.imashnake.animite.navigation.HomeRoute +import com.imashnake.animite.navigation.NavigationBar +import com.imashnake.animite.navigation.NavigationBarPaths +import com.imashnake.animite.navigation.ProfileRoute +import com.imashnake.animite.navigation.SocialRoute import com.imashnake.animite.profile.ProfileScreen import com.imashnake.animite.profile.dev.internal.ANILIST_AUTH_DEEPLINK -import com.imashnake.animite.social.Social import com.imashnake.animite.social.SocialScreen import dagger.hilt.android.AndroidEntryPoint @@ -89,8 +89,8 @@ fun MainScreen(modifier: Modifier = Modifier) { LocalContentColor provides MaterialTheme.colorScheme.onBackground ) { SharedTransitionLayout { - NavHost(navController = navController, startDestination = Home) { - composable { + NavHost(navController = navController, startDestination = HomeRoute) { + composable { HomeScreen( onNavigateToMediaItem = { navController.navigate(it) }, sharedTransitionScope = this@SharedTransitionLayout, @@ -103,14 +103,14 @@ fun MainScreen(modifier: Modifier = Modifier) { animatedVisibilityScope = this, ) } - composable( + composable( deepLinks = listOf( navDeepLink { uriPattern = ANILIST_AUTH_DEEPLINK } ) ) { ProfileScreen() } - composable { + composable { SocialScreen() } } diff --git a/app/src/main/java/com/imashnake/animite/features/home/HomeScreen.kt b/app/src/main/java/com/imashnake/animite/features/home/HomeScreen.kt index 38015b28..6c250a4c 100644 --- a/app/src/main/java/com/imashnake/animite/features/home/HomeScreen.kt +++ b/app/src/main/java/com/imashnake/animite/features/home/HomeScreen.kt @@ -76,8 +76,8 @@ import com.imashnake.animite.dev.SharedContentKey.Component.Image import com.imashnake.animite.dev.SharedContentKey.Component.Page import com.imashnake.animite.dev.SharedContentKey.Component.Text import com.imashnake.animite.features.media.MediaPage -import kotlinx.serialization.Serializable import com.imashnake.animite.core.R as coreR +import com.imashnake.animite.navigation.R as navigationR @OptIn(ExperimentalSharedTransitionApi::class) @Composable @@ -124,17 +124,15 @@ fun HomeScreen( ) Box( - modifier = bannerModifier - .background( - Brush.verticalGradient( - listOf( - Color.Transparent, - MaterialTheme.colorScheme.secondaryContainer.copy( - alpha = 0.5f - ) - ) + modifier = bannerModifier.background( + Brush.verticalGradient( + listOf( + Color.Transparent, + MaterialTheme.colorScheme.secondaryContainer + .copy(alpha = 0.5f) ) ) + ) ) Row( @@ -194,7 +192,8 @@ fun HomeScreen( }, contentModifier = Modifier.padding( top = LocalPaddings.current.large, - bottom = dimensionResource(coreR.dimen.navigation_bar_height) + LocalPaddings.current.large + bottom = LocalPaddings.current.large + + dimensionResource(navigationR.dimen.navigation_bar_height) ), verticalArrangement = Arrangement.spacedBy(LocalPaddings.current.large) ) @@ -284,11 +283,10 @@ private fun MediaTypeSelector( viewModel: HomeViewModel ) { Box( - modifier = modifier - .background( - color = MaterialTheme.colorScheme.onBackground, - shape = CircleShape - ) + modifier = modifier.background( + color = MaterialTheme.colorScheme.onBackground, + shape = CircleShape + ) ) { val offset by animateDpAsState( targetValue = if (selectedOption.value == MediaType.ANIME) 0.dp else 40.dp, @@ -342,6 +340,3 @@ private fun MediaTypeSelector( } } } - -@Serializable -data object Home diff --git a/app/src/main/java/com/imashnake/animite/features/searchbar/SearchFrontDrop.kt b/app/src/main/java/com/imashnake/animite/features/searchbar/SearchFrontDrop.kt index 1bbeae2e..6c479700 100644 --- a/app/src/main/java/com/imashnake/animite/features/searchbar/SearchFrontDrop.kt +++ b/app/src/main/java/com/imashnake/animite/features/searchbar/SearchFrontDrop.kt @@ -7,7 +7,6 @@ import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.ExperimentalLayoutApi import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer @@ -17,18 +16,15 @@ import androidx.compose.foundation.layout.consumeWindowInsets import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.imeNestedScroll import androidx.compose.foundation.layout.imePadding 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.statusBars -import androidx.compose.foundation.layout.statusBarsPadding import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.ContentAlpha import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -49,22 +45,22 @@ import androidx.lifecycle.viewmodel.compose.viewModel import com.imashnake.animite.R import com.imashnake.animite.api.anilist.sanitize.search.Search import com.imashnake.animite.api.anilist.type.MediaType +import com.imashnake.animite.core.Constants import com.imashnake.animite.core.extensions.landscapeCutoutPadding import com.imashnake.animite.core.ui.LocalPaddings -import com.imashnake.animite.core.Constants import com.imashnake.animite.core.ui.MediaSmall import com.imashnake.animite.core.R as coreR +import com.imashnake.animite.navigation.R as navigationR /** * Search bar along with a Front Drop list. * * @param hasExtraPadding if the search bar should have extra bottom padding to accommodate the - * [com.imashnake.animite.features.navigationbar.NavigationBar]. + * [com.imashnake.animite.navigation.NavigationBar]. * @param onItemClick called when media with an ID and [MediaType] is clicked. * @param modifier the [Modifier] to be applied to this Front Drop. * @param viewModel [SearchViewModel] instance. */ -@OptIn(ExperimentalLayoutApi::class) @Composable fun SearchFrontDrop( hasExtraPadding: Boolean, @@ -79,7 +75,7 @@ fun SearchFrontDrop( var isExpanded by rememberSaveable { mutableStateOf(false) } val searchBarBottomPadding: Dp by animateDpAsState( targetValue = if (hasExtraPadding) { - dimensionResource(coreR.dimen.navigation_bar_height) + dimensionResource(navigationR.dimen.navigation_bar_height) } else 0.dp, label = "translate_search_bar" ) @@ -120,9 +116,7 @@ fun SearchFrontDrop( .landscapeCutoutPadding() .padding(bottom = searchBarBottomPadding) .navigationBarsPadding() - .consumeWindowInsets( - PaddingValues(bottom = searchBarBottomPadding) - ) + .consumeWindowInsets(PaddingValues(bottom = searchBarBottomPadding)) .imePadding() .height(dimensionResource(R.dimen.search_bar_height)) ) @@ -144,7 +138,7 @@ fun SearchList( bottom = dimensionResource(R.dimen.search_bar_height) + LocalPaddings.current.large + LocalPaddings.current.large - + dimensionResource(coreR.dimen.navigation_bar_height) + + dimensionResource(navigationR.dimen.navigation_bar_height) + WindowInsets.navigationBars.asPaddingValues().calculateBottomPadding() ), verticalArrangement = Arrangement.spacedBy(LocalPaddings.current.small) @@ -181,9 +175,7 @@ private fun SearchItem( Text( text = item.title.orEmpty(), color = MaterialTheme.colorScheme.onBackground, - style = MaterialTheme.typography.bodyMedium.copy( - fontWeight = FontWeight.Bold - ), + style = MaterialTheme.typography.bodyMedium.copy(fontWeight = FontWeight.Bold), maxLines = 2 ) if (item.seasonYear != null) { @@ -208,9 +200,7 @@ private fun SearchItem( item.format.string.takeIf { it.isNotEmpty() }, item.episodes?.let { "$it episodes" } ).joinToString(" ꞏ "), - color = MaterialTheme.colorScheme.onBackground.copy( - alpha = ContentAlpha.medium - ), + color = MaterialTheme.colorScheme.onSurfaceVariant, style = MaterialTheme.typography.bodyMedium, maxLines = 1, overflow = TextOverflow.Ellipsis diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b7b215c8..605c32d9 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,8 +1,5 @@ Animite - Home - Profile - Social おかえり diff --git a/core/src/main/res/values/dimens.xml b/core/src/main/res/values/dimens.xml index 8e9df500..9f28927c 100644 --- a/core/src/main/res/values/dimens.xml +++ b/core/src/main/res/values/dimens.xml @@ -9,8 +9,6 @@ 3dp - 65dp - 100dp 3dp diff --git a/navigation/build.gradle.kts b/navigation/build.gradle.kts new file mode 100644 index 00000000..18edb835 --- /dev/null +++ b/navigation/build.gradle.kts @@ -0,0 +1,36 @@ +plugins { + alias(libs.plugins.android.library) + alias(libs.plugins.kotlin) + alias(libs.plugins.kotlin.serialization) + alias(libs.plugins.composeCompiler) + alias(libs.plugins.detekt) +} + +android { + buildTypes { + release { + isMinifyEnabled = false + proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") + } + } + + buildFeatures { + compose = true + } + composeCompiler.enableStrongSkippingMode = true + + namespace = "com.imashnake.animite.navigation" +} + +kotlin { + jvmToolchain(17) +} + +dependencies { + api(libs.androidx.navigationCompose) + implementation(libs.bundles.compose) + implementation(libs.compose.material) + debugImplementation(libs.compose.ui.tooling) + implementation(libs.compose.ui.toolingPreview) + implementation(libs.kotlinx.serialization.core) +} diff --git a/app/src/main/java/com/imashnake/animite/features/navigationbar/NavigationBar.kt b/navigation/src/main/kotlin/com/imashnake/animite/navigation/NavigationBar.kt similarity index 85% rename from app/src/main/java/com/imashnake/animite/features/navigationbar/NavigationBar.kt rename to navigation/src/main/kotlin/com/imashnake/animite/navigation/NavigationBar.kt index 5c1dbebe..b33c2d83 100644 --- a/app/src/main/java/com/imashnake/animite/features/navigationbar/NavigationBar.kt +++ b/navigation/src/main/kotlin/com/imashnake/animite/navigation/NavigationBar.kt @@ -1,4 +1,4 @@ -package com.imashnake.animite.features.navigationbar +package com.imashnake.animite.navigation import android.content.res.Configuration import androidx.annotation.StringRes @@ -27,8 +27,6 @@ import androidx.navigation.NavDestination.Companion.hasRoute import androidx.navigation.NavDestination.Companion.hierarchy import androidx.navigation.NavGraph.Companion.findStartDestination import androidx.navigation.compose.currentBackStackEntryAsState -import com.imashnake.animite.R -import com.imashnake.animite.core.R as coreR @Composable fun NavigationBar( @@ -39,7 +37,7 @@ fun NavigationBar( // TODO: Can we use `navigationBarsPadding()` instead? NavigationBar( Modifier.height( - dimensionResource(coreR.dimen.navigation_bar_height) + WindowInsets + dimensionResource(R.dimen.navigation_bar_height) + WindowInsets .navigationBars .asPaddingValues() .calculateBottomPadding() @@ -73,7 +71,7 @@ enum class NavigationBarPaths( ) { Social( navigateTo = { - it.navigate(com.imashnake.animite.social.Social) { + it.navigate(SocialRoute) { popUpTo(id = it.graph.findStartDestination().id) { saveState = true } @@ -81,7 +79,7 @@ enum class NavigationBarPaths( } }, matchesDestination = { - it.destination.hierarchy.any { it.hasRoute(com.imashnake.animite.social.Social::class) } + it.destination.hierarchy.any { it.hasRoute(SocialRoute::class) } }, icon = { Icon(ImageVector.vectorResource(R.drawable.social), contentDescription = stringResource(R.string.social)) @@ -90,7 +88,7 @@ enum class NavigationBarPaths( ), Home( navigateTo = { - it.navigate(com.imashnake.animite.features.home.Home) { + it.navigate(HomeRoute) { popUpTo(id = it.graph.findStartDestination().id) { saveState = true inclusive = true @@ -99,7 +97,7 @@ enum class NavigationBarPaths( } }, matchesDestination = { - it.destination.hierarchy.any { it.hasRoute(com.imashnake.animite.features.home.Home::class) } + it.destination.hierarchy.any { it.hasRoute(HomeRoute::class) } }, icon = { Icon(ImageVector.vectorResource(R.drawable.home), contentDescription = stringResource(R.string.home)) @@ -109,7 +107,7 @@ enum class NavigationBarPaths( Profile( navigateTo = { - it.navigate(com.imashnake.animite.profile.Profile()) { + it.navigate(ProfileRoute()) { popUpTo(id = it.graph.findStartDestination().id) { saveState = true } @@ -117,7 +115,7 @@ enum class NavigationBarPaths( } }, matchesDestination = { - it.destination.hierarchy.any { it.hasRoute(com.imashnake.animite.profile.Profile::class) } + it.destination.hierarchy.any { it.hasRoute(ProfileRoute::class) } }, icon = { Icon(ImageVector.vectorResource(R.drawable.profile), contentDescription = stringResource(R.string.profile)) diff --git a/navigation/src/main/kotlin/com/imashnake/animite/navigation/TopLevelDestinations.kt b/navigation/src/main/kotlin/com/imashnake/animite/navigation/TopLevelDestinations.kt new file mode 100644 index 00000000..d67b3b4c --- /dev/null +++ b/navigation/src/main/kotlin/com/imashnake/animite/navigation/TopLevelDestinations.kt @@ -0,0 +1,20 @@ +package com.imashnake.animite.navigation + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class ProfileRoute( + @SerialName("accessToken") + val accessToken: String? = null, + @SerialName("tokenType") + val tokenType: String? = null, + @SerialName("expiresIn") + val expiresIn: Int = -1 +) + +@Serializable +data object SocialRoute + +@Serializable +data object HomeRoute diff --git a/app/src/main/res/drawable/home.xml b/navigation/src/main/res/drawable/home.xml similarity index 100% rename from app/src/main/res/drawable/home.xml rename to navigation/src/main/res/drawable/home.xml diff --git a/app/src/main/res/drawable/profile.xml b/navigation/src/main/res/drawable/profile.xml similarity index 100% rename from app/src/main/res/drawable/profile.xml rename to navigation/src/main/res/drawable/profile.xml diff --git a/app/src/main/res/drawable/social.xml b/navigation/src/main/res/drawable/social.xml similarity index 100% rename from app/src/main/res/drawable/social.xml rename to navigation/src/main/res/drawable/social.xml diff --git a/navigation/src/main/res/values/dimens.xml b/navigation/src/main/res/values/dimens.xml new file mode 100644 index 00000000..cd4adde5 --- /dev/null +++ b/navigation/src/main/res/values/dimens.xml @@ -0,0 +1,4 @@ + + + 65dp + diff --git a/navigation/src/main/res/values/strings.xml b/navigation/src/main/res/values/strings.xml new file mode 100644 index 00000000..77e93d52 --- /dev/null +++ b/navigation/src/main/res/values/strings.xml @@ -0,0 +1,6 @@ + + + Home + Profile + Social + diff --git a/profile/build.gradle.kts b/profile/build.gradle.kts index dd34f984..9a31edc2 100644 --- a/profile/build.gradle.kts +++ b/profile/build.gradle.kts @@ -28,6 +28,7 @@ kotlin { } dependencies { + implementation(projects.navigation) implementation(projects.core) implementation(projects.api.anilist) implementation(projects.api.preferences) 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 0be61311..3ac63314 100644 --- a/profile/src/main/kotlin/com/imashnake/animite/profile/ProfileScreen.kt +++ b/profile/src/main/kotlin/com/imashnake/animite/profile/ProfileScreen.kt @@ -46,9 +46,8 @@ import com.imashnake.animite.profile.tabs.AboutTab import com.imashnake.animite.profile.tabs.AnimeTab import com.imashnake.animite.profile.tabs.ProfileTabs import kotlinx.coroutines.launch -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable import com.imashnake.animite.core.R as coreR +import com.imashnake.animite.navigation.R as navigationR @Suppress("LongMethod") @Composable @@ -114,11 +113,10 @@ fun ProfileScreen( ) } }, - contentModifier = Modifier - .padding( - top = LocalPaddings.current.large, - bottom = dimensionResource(coreR.dimen.navigation_bar_height) - ) + contentModifier = Modifier.padding( + top = LocalPaddings.current.large, + bottom = dimensionResource(navigationR.dimen.navigation_bar_height) + ) ) } else -> Login() @@ -221,13 +219,3 @@ private fun UserTabs( } } } - -@Serializable -data class Profile( - @SerialName("accessToken") - val accessToken: String? = null, - @SerialName("tokenType") - val tokenType: String? = null, - @SerialName("expiresIn") - val expiresIn: Int = -1 -) diff --git a/profile/src/main/kotlin/com/imashnake/animite/profile/ProfileViewModel.kt b/profile/src/main/kotlin/com/imashnake/animite/profile/ProfileViewModel.kt index 06b7ef4e..d86b19f4 100644 --- a/profile/src/main/kotlin/com/imashnake/animite/profile/ProfileViewModel.kt +++ b/profile/src/main/kotlin/com/imashnake/animite/profile/ProfileViewModel.kt @@ -8,6 +8,7 @@ import com.imashnake.animite.api.anilist.AnilistUserRepository import com.imashnake.animite.api.preferences.PreferencesRepository import com.imashnake.animite.core.data.Resource import com.imashnake.animite.core.data.Resource.Companion.asResource +import com.imashnake.animite.navigation.ProfileRoute import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -27,7 +28,7 @@ class ProfileViewModel @Inject constructor( savedStateHandle: SavedStateHandle ) : ViewModel() { - private val navArgs = savedStateHandle.toRoute() + private val navArgs = savedStateHandle.toRoute() val isLoggedIn = preferencesRepository .accessToken diff --git a/settings.gradle.kts b/settings.gradle.kts index c9efbfa0..b0a3c2d6 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -28,8 +28,9 @@ include( ":api:preferences", ":material-color-utilities", ":core", + ":navigation", ":profile", - ":rslash", + ":social", ":app" ) diff --git a/rslash/build.gradle.kts b/social/build.gradle.kts similarity index 98% rename from rslash/build.gradle.kts rename to social/build.gradle.kts index 696e6360..9845578d 100644 --- a/rslash/build.gradle.kts +++ b/social/build.gradle.kts @@ -24,7 +24,7 @@ android { } kotlin { - jvmToolchain(17) + jvmToolchain(21) } dependencies { diff --git a/rslash/src/main/AndroidManifest.xml b/social/src/main/AndroidManifest.xml similarity index 100% rename from rslash/src/main/AndroidManifest.xml rename to social/src/main/AndroidManifest.xml diff --git a/rslash/src/main/kotlin/com/imashnake/animite/social/SocialScreen.kt b/social/src/main/kotlin/com/imashnake/animite/social/SocialScreen.kt similarity index 97% rename from rslash/src/main/kotlin/com/imashnake/animite/social/SocialScreen.kt rename to social/src/main/kotlin/com/imashnake/animite/social/SocialScreen.kt index deaca054..bcb67095 100644 --- a/rslash/src/main/kotlin/com/imashnake/animite/social/SocialScreen.kt +++ b/social/src/main/kotlin/com/imashnake/animite/social/SocialScreen.kt @@ -37,6 +37,3 @@ fun SocialScreen() { } } } - -@Serializable -data object Social