Navigate with enum defines. Create new TopBarState
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2023-01-28 10:06:58 +01:00
parent 48374c5980
commit 6aedb0d7f9
7 changed files with 129 additions and 91 deletions

View File

@@ -17,11 +17,8 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.navigation.NavDestination.Companion.hierarchy
import androidx.navigation.NavGraph.Companion.findStartDestination
import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.rememberNavController
import com.google.accompanist.systemuicontroller.rememberSystemUiController
@@ -106,10 +103,7 @@ class MainActivity : AppCompatActivity(), ISettingsChangeListener {
fabAction: () -> Unit
) {
var topBarTitle by remember { mutableStateOf("") }
var topBarIcon by remember { mutableStateOf(Icons.Filled.Menu) }
var topBarActions by remember { mutableStateOf(emptyList<TopBarAction>()) }
var topBarNavigationAction by remember { mutableStateOf(NavigationAction {}) }
var topBarState by remember { mutableStateOf(TopBarState()) }
Scaffold(
floatingActionButton = {
@@ -120,76 +114,63 @@ class MainActivity : AppCompatActivity(), ISettingsChangeListener {
}
}
},
topBar = {
TopBar(
topBarTitle,
topBarIcon,
{ topBarNavigationAction.action() },
topBarActions
)
}) { paddings ->
topBar = { TopBar(topBarState) }) { paddings ->
NavHost(
navController = navController,
startDestination = "counter",
startDestination = Route.COUNTER.name,
modifier = Modifier.padding(paddings)
) {
composable("counter") {
composable(Route.COUNTER) {
var expanded by remember { mutableStateOf(false) }
Counter(counterViewModel)
topBarActions = (listOf(
TopBarAction(
Icons.Outlined.Undo,
mainViewModel.isUndoActionActive,
{ mainViewModel.undoLastRound() }),
TopBarAction(
Icons.Outlined.Redo,
mainViewModel.isRedoActionActive,
{ mainViewModel.redoLastRound() }),
TopBarAction(
Icons.Outlined.MoreVert,
mainViewModel.activeGameHasRounds,
{ expanded = true }
) {
DropDownMenu(
mapOf("new" to R.string.newGame),
"",
expanded,
topBarState = TopBarState(
title = stringResource(R.string.app_name),
actions = (listOf(
TopBarAction(
Icons.Outlined.Undo,
mainViewModel.isUndoActionActive,
{ mainViewModel.undoLastRound() }),
TopBarAction(
Icons.Outlined.Redo,
mainViewModel.isRedoActionActive,
{ mainViewModel.redoLastRound() }),
TopBarAction(
Icons.Outlined.MoreVert,
mainViewModel.activeGameHasRounds,
{ expanded = true }
) {
expanded = false
it?.let {
when (it) {
"new" -> mainViewModel.newGame()
DropDownMenu(
mapOf("new" to R.string.newGame),
"",
expanded,
) {
expanded = false
it?.let {
when (it) {
"new" -> mainViewModel.newGame()
}
}
}
}
},
},
))
topBarIcon = Icons.Outlined.Menu
topBarTitle = stringResource(R.string.app_name)
topBarNavigationAction =
NavigationAction { scope.launch { drawerState.open() } }
))
) { scope.launch { drawerState.open() } }
Counter(counterViewModel)
}
composable("history") {
composable(Route.HISTORY) {
topBarState =
TopBarState(title = stringResource(R.string.menu_history)) { scope.launch { drawerState.open() } }
HistoryList(historyViewModel) { navController.navigate("counter") }
topBarActions = emptyList()
topBarIcon = Icons.Outlined.Menu
topBarTitle = stringResource(R.string.menu_history)
topBarNavigationAction =
NavigationAction { scope.launch { drawerState.open() } }
HistoryList(historyViewModel) { navController.navigate(Route.COUNTER) }
}
composable("settings") {
composable(Route.SETTINGS) {
topBarState =
TopBarState(title = stringResource(R.string.menu_settings)) { scope.launch { drawerState.open() } }
SettingsView(settingsViewModel)
topBarActions = emptyList()
topBarIcon = Icons.Outlined.Menu
topBarTitle = stringResource(R.string.menu_settings)
topBarNavigationAction =
NavigationAction { scope.launch { drawerState.open() } }
}
}
}
@@ -204,40 +185,27 @@ class MainActivity : AppCompatActivity(), ISettingsChangeListener {
val navController = rememberNavController()
val items = listOf(
Screen("counter", Icons.Outlined.Calculate, R.string.app_name),
Screen("history", Icons.Outlined.List, R.string.menu_history),
Screen("settings", Icons.Outlined.Settings, R.string.menu_settings)
Screen(Route.COUNTER, Icons.Outlined.Calculate, R.string.app_name),
Screen(Route.HISTORY, Icons.Outlined.List, R.string.menu_history),
Screen(Route.SETTINGS, Icons.Outlined.Settings, R.string.menu_settings)
)
val navBackStackEntry by navController.currentBackStackEntryAsState()
val currentDestination = navBackStackEntry?.destination
val currentDestination =
Route.valueOf(navBackStackEntry?.destination?.route ?: Route.COUNTER.name)
ModalNavigationDrawer(
drawerState = drawerState,
gesturesEnabled = drawerState.isOpen,
drawerContent = {
ModalDrawerSheet {
DrawerContent(
screens = items,
selectedScreen = items.first { it.route == currentDestination }) {
scope.launch {
drawerState.close()
Spacer(Modifier.height(20.dp))
items.forEach { screen ->
NavigationDrawerItem(
icon = { Icon(screen.icon, contentDescription = null) },
label = { Text(stringResource(screen.resourceId)) },
selected = currentDestination?.hierarchy?.any { it.route == screen.route } == true,
onClick = {
scope.launch { drawerState.close() }
navController.navigate(screen.route) {
popUpTo(navController.graph.findStartDestination().id) {
saveState = true
}
launchSingleTop = true
restoreState = true
}
},
modifier = Modifier.padding(NavigationDrawerItemDefaults.ItemPadding)
)
}
navController.navigate(it)
}
}
) {
@@ -245,10 +213,34 @@ class MainActivity : AppCompatActivity(), ISettingsChangeListener {
drawerState,
scope,
navController,
counterViewModel.keyboardHidden && (currentDestination?.hierarchy?.any { it.route == "counter" } == true)
counterViewModel.keyboardHidden && (currentDestination == Route.COUNTER)
) { counterViewModel.showKeyboard() }
}
}
private class Screen(val route: String, val icon: ImageVector, @StringRes val resourceId: Int)
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun DrawerContent(
screens: List<Screen>,
selectedScreen: Screen,
onElementClicked: (Route) -> Unit
) {
ModalDrawerSheet {
Spacer(Modifier.height(20.dp))
screens.forEach { screen ->
NavigationDrawerItem(
icon = { Icon(screen.icon, contentDescription = null) },
label = { Text(stringResource(screen.resourceId)) },
selected = screen == selectedScreen,
onClick = { onElementClicked(screen.route) },
modifier = Modifier.padding(NavigationDrawerItemDefaults.ItemPadding)
)
}
}
}
private class Screen(val route: Route, val icon: ImageVector, @StringRes val resourceId: Int)
}

View File

@@ -0,0 +1,18 @@
package me.zobrist.tichucounter.domain
import androidx.compose.runtime.Composable
import androidx.navigation.*
import androidx.navigation.compose.composable
fun NavController.navigate(route: Route) {
this.navigate(route.name)
}
fun NavGraphBuilder.composable(
route: Route,
arguments: List<NamedNavArgument> = emptyList(),
deepLinks: List<NavDeepLink> = emptyList(),
content: @Composable (NavBackStackEntry) -> Unit
) {
this.composable(route.name, arguments, deepLinks, content)
}

View File

@@ -1,3 +0,0 @@
package me.zobrist.tichucounter.domain
class NavigationAction(val action: () -> Unit)

View File

@@ -0,0 +1,3 @@
package me.zobrist.tichucounter.domain
enum class Route { COUNTER, HISTORY, SETTINGS }

View File

@@ -3,4 +3,9 @@ package me.zobrist.tichucounter.domain
import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.vector.ImageVector
class TopBarAction(val imageVector: ImageVector, val isActive: Boolean, val action: () -> Unit, val composeCode: @Composable () -> Unit = {})
class TopBarAction(
val imageVector: ImageVector,
val isActive: Boolean,
val action: () -> Unit,
val composeCode: @Composable () -> Unit = {}
)

View File

@@ -0,0 +1,12 @@
package me.zobrist.tichucounter.domain
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Menu
import androidx.compose.ui.graphics.vector.ImageVector
data class TopBarState(
var title: String = "",
var icon: ImageVector = Icons.Outlined.Menu,
var actions: List<TopBarAction> = emptyList(),
var onNavigate: () -> Unit = {}
)

View File

@@ -5,6 +5,17 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.text.style.TextOverflow
import me.zobrist.tichucounter.domain.TopBarAction
import me.zobrist.tichucounter.domain.TopBarState
@Composable
fun TopBar(topBarState: TopBarState) {
TopBar(
topBarState.title,
topBarState.icon,
topBarState.onNavigate,
topBarState.actions
)
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable