diff --git a/app/src/main/java/dev/msfjarvis/lobsters/ui/main/LobstersApp.kt b/app/src/main/java/dev/msfjarvis/lobsters/ui/main/LobstersApp.kt new file mode 100644 index 00000000..74d659e1 --- /dev/null +++ b/app/src/main/java/dev/msfjarvis/lobsters/ui/main/LobstersApp.kt @@ -0,0 +1,114 @@ +package dev.msfjarvis.lobsters.ui.main + +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.rememberLazyListState +import androidx.compose.material.BottomNavigation +import androidx.compose.material.BottomNavigationItem +import androidx.compose.material.Scaffold +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.testTag +import androidx.compose.ui.res.stringResource +import androidx.lifecycle.viewmodel.compose.viewModel +import androidx.navigation.compose.KEY_ROUTE +import androidx.navigation.compose.NavHost +import androidx.navigation.compose.composable +import androidx.navigation.compose.currentBackStackEntryAsState +import androidx.navigation.compose.navigate +import androidx.navigation.compose.rememberNavController +import androidx.paging.compose.collectAsLazyPagingItems +import dev.msfjarvis.lobsters.ui.navigation.Destination +import dev.msfjarvis.lobsters.ui.posts.HottestPosts +import dev.msfjarvis.lobsters.ui.posts.SavedPosts +import dev.msfjarvis.lobsters.ui.viewmodel.LobstersViewModel +import dev.msfjarvis.lobsters.util.IconResource +import kotlinx.coroutines.launch + +@Composable +fun LobstersApp() { + val viewModel: LobstersViewModel = viewModel() + val coroutineScope = rememberCoroutineScope() + val navController = rememberNavController() + val hottestPosts = viewModel.posts.collectAsLazyPagingItems() + val savedPosts by viewModel.savedPosts.collectAsState() + val hottestPostsListState = rememberLazyListState() + + val navBackStackEntry by navController.currentBackStackEntryAsState() + val currentRoute = + navBackStackEntry?.arguments?.getString(KEY_ROUTE) ?: Destination.startDestination.route + val currentDestination = Destination.getDestinationFromRoute(currentRoute) + val navigateToDestination: (destination: Destination) -> Unit = { destination -> + navController.navigate(destination.route) { + launchSingleTop = true + popUpTo(navController.graph.startDestination) { inclusive = false } + } + } + val jumpToIndex: (Int) -> Unit = { + coroutineScope.launch { + hottestPostsListState.snapToItemIndex(it) + } + } + + Scaffold( + bottomBar = { + LobstersBottomNav( + currentDestination, + navigateToDestination, + jumpToIndex, + ) + }, + ) { innerPadding -> + NavHost(navController, startDestination = Destination.startDestination.route) { + composable(Destination.Hottest.route) { + HottestPosts( + posts = hottestPosts, + listState = hottestPostsListState, + isPostSaved = viewModel::isPostSaved, + saveAction = viewModel::toggleSave, + modifier = Modifier.padding(bottom = innerPadding.calculateBottomPadding()), + ) + } + composable(Destination.Saved.route) { + SavedPosts( + posts = savedPosts, + saveAction = viewModel::toggleSave, + modifier = Modifier.padding(bottom = innerPadding.calculateBottomPadding()), + ) + } + } + } +} + +@Composable +fun LobstersBottomNav( + currentDestination: Destination, + navigateToDestination: (destination: Destination) -> Unit, + jumpToIndex: (index: Int) -> Unit, +) { + BottomNavigation(modifier = Modifier.testTag("LobstersBottomNav")) { + Destination.values().forEach { screen -> + BottomNavigationItem( + icon = { + IconResource( + resourceId = screen.badgeRes, + contentDescription = stringResource(screen.labelRes), + ) + }, + label = { Text(stringResource(id = screen.labelRes)) }, + selected = currentDestination == screen, + alwaysShowLabels = false, + onClick = { + if (screen != currentDestination) { + navigateToDestination(screen) + } else if (screen.route == Destination.Hottest.route) { + jumpToIndex(0) + } + } + ) + } + } +} diff --git a/app/src/main/java/dev/msfjarvis/lobsters/ui/main/MainActivity.kt b/app/src/main/java/dev/msfjarvis/lobsters/ui/main/MainActivity.kt index e85fccc2..0ffb0ffd 100644 --- a/app/src/main/java/dev/msfjarvis/lobsters/ui/main/MainActivity.kt +++ b/app/src/main/java/dev/msfjarvis/lobsters/ui/main/MainActivity.kt @@ -3,39 +3,12 @@ package dev.msfjarvis.lobsters.ui.main import android.os.Bundle import androidx.activity.compose.setContent import androidx.appcompat.app.AppCompatActivity -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.lazy.rememberLazyListState -import androidx.compose.material.BottomNavigation -import androidx.compose.material.BottomNavigationItem -import androidx.compose.material.Scaffold -import androidx.compose.material.Text -import androidx.compose.runtime.Composable import androidx.compose.runtime.Providers -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue -import androidx.compose.runtime.rememberCoroutineScope -import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.testTag -import androidx.compose.ui.res.stringResource -import androidx.lifecycle.viewmodel.compose.viewModel -import androidx.navigation.compose.KEY_ROUTE -import androidx.navigation.compose.NavHost -import androidx.navigation.compose.composable -import androidx.navigation.compose.currentBackStackEntryAsState -import androidx.navigation.compose.navigate -import androidx.navigation.compose.rememberNavController -import androidx.paging.compose.collectAsLazyPagingItems import dagger.hilt.android.AndroidEntryPoint -import dev.msfjarvis.lobsters.ui.navigation.Destination -import dev.msfjarvis.lobsters.ui.posts.HottestPosts -import dev.msfjarvis.lobsters.ui.posts.SavedPosts import dev.msfjarvis.lobsters.ui.theme.LobstersTheme import dev.msfjarvis.lobsters.ui.urllauncher.LocalUrlLauncher import dev.msfjarvis.lobsters.ui.urllauncher.UrlLauncher -import dev.msfjarvis.lobsters.ui.viewmodel.LobstersViewModel -import dev.msfjarvis.lobsters.util.IconResource import javax.inject.Inject -import kotlinx.coroutines.launch @AndroidEntryPoint class MainActivity : AppCompatActivity() { @@ -52,88 +25,3 @@ class MainActivity : AppCompatActivity() { } } } - -@Composable -fun LobstersApp() { - val viewModel: LobstersViewModel = viewModel() - val coroutineScope = rememberCoroutineScope() - val navController = rememberNavController() - val hottestPosts = viewModel.posts.collectAsLazyPagingItems() - val savedPosts by viewModel.savedPosts.collectAsState() - val hottestPostsListState = rememberLazyListState() - - val navBackStackEntry by navController.currentBackStackEntryAsState() - val currentRoute = - navBackStackEntry?.arguments?.getString(KEY_ROUTE) ?: Destination.startDestination.route - val currentDestination = Destination.getDestinationFromRoute(currentRoute) - val navigateToDestination: (destination: Destination) -> Unit = { destination -> - navController.navigate(destination.route) { - launchSingleTop = true - popUpTo(navController.graph.startDestination) { inclusive = false } - } - } - val jumpToIndex: (Int) -> Unit = { - coroutineScope.launch { - hottestPostsListState.snapToItemIndex(it) - } - } - - Scaffold( - bottomBar = { - LobstersBottomNav( - currentDestination, - navigateToDestination, - jumpToIndex, - ) - }, - ) { innerPadding -> - NavHost(navController, startDestination = Destination.startDestination.route) { - composable(Destination.Hottest.route) { - HottestPosts( - posts = hottestPosts, - listState = hottestPostsListState, - isPostSaved = viewModel::isPostSaved, - saveAction = viewModel::toggleSave, - modifier = Modifier.padding(bottom = innerPadding.calculateBottomPadding()), - ) - } - composable(Destination.Saved.route) { - SavedPosts( - posts = savedPosts, - saveAction = viewModel::toggleSave, - modifier = Modifier.padding(bottom = innerPadding.calculateBottomPadding()), - ) - } - } - } -} - -@Composable -fun LobstersBottomNav( - currentDestination: Destination, - navigateToDestination: (destination: Destination) -> Unit, - jumpToIndex: (index: Int) -> Unit, -) { - BottomNavigation(modifier = Modifier.testTag("LobstersBottomNav")) { - Destination.values().forEach { screen -> - BottomNavigationItem( - icon = { - IconResource( - resourceId = screen.badgeRes, - contentDescription = stringResource(screen.labelRes), - ) - }, - label = { Text(stringResource(id = screen.labelRes)) }, - selected = currentDestination == screen, - alwaysShowLabels = false, - onClick = { - if (screen != currentDestination) { - navigateToDestination(screen) - } else if (screen.route == Destination.Hottest.route) { - jumpToIndex(0) - } - } - ) - } - } -}