Navigate with enum defines. Create new TopBarState
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
@@ -17,11 +17,8 @@ import androidx.compose.ui.Modifier
|
|||||||
import androidx.compose.ui.graphics.vector.ImageVector
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.unit.dp
|
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.NavHostController
|
||||||
import androidx.navigation.compose.NavHost
|
import androidx.navigation.compose.NavHost
|
||||||
import androidx.navigation.compose.composable
|
|
||||||
import androidx.navigation.compose.currentBackStackEntryAsState
|
import androidx.navigation.compose.currentBackStackEntryAsState
|
||||||
import androidx.navigation.compose.rememberNavController
|
import androidx.navigation.compose.rememberNavController
|
||||||
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
||||||
@@ -106,10 +103,7 @@ class MainActivity : AppCompatActivity(), ISettingsChangeListener {
|
|||||||
fabAction: () -> Unit
|
fabAction: () -> Unit
|
||||||
) {
|
) {
|
||||||
|
|
||||||
var topBarTitle by remember { mutableStateOf("") }
|
var topBarState by remember { mutableStateOf(TopBarState()) }
|
||||||
var topBarIcon by remember { mutableStateOf(Icons.Filled.Menu) }
|
|
||||||
var topBarActions by remember { mutableStateOf(emptyList<TopBarAction>()) }
|
|
||||||
var topBarNavigationAction by remember { mutableStateOf(NavigationAction {}) }
|
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
floatingActionButton = {
|
floatingActionButton = {
|
||||||
@@ -120,76 +114,63 @@ class MainActivity : AppCompatActivity(), ISettingsChangeListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
topBar = {
|
topBar = { TopBar(topBarState) }) { paddings ->
|
||||||
TopBar(
|
|
||||||
topBarTitle,
|
|
||||||
topBarIcon,
|
|
||||||
{ topBarNavigationAction.action() },
|
|
||||||
topBarActions
|
|
||||||
)
|
|
||||||
}) { paddings ->
|
|
||||||
|
|
||||||
NavHost(
|
NavHost(
|
||||||
navController = navController,
|
navController = navController,
|
||||||
startDestination = "counter",
|
startDestination = Route.COUNTER.name,
|
||||||
modifier = Modifier.padding(paddings)
|
modifier = Modifier.padding(paddings)
|
||||||
) {
|
) {
|
||||||
composable("counter") {
|
composable(Route.COUNTER) {
|
||||||
|
|
||||||
var expanded by remember { mutableStateOf(false) }
|
var expanded by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
Counter(counterViewModel)
|
topBarState = TopBarState(
|
||||||
topBarActions = (listOf(
|
title = stringResource(R.string.app_name),
|
||||||
TopBarAction(
|
actions = (listOf(
|
||||||
Icons.Outlined.Undo,
|
TopBarAction(
|
||||||
mainViewModel.isUndoActionActive,
|
Icons.Outlined.Undo,
|
||||||
{ mainViewModel.undoLastRound() }),
|
mainViewModel.isUndoActionActive,
|
||||||
TopBarAction(
|
{ mainViewModel.undoLastRound() }),
|
||||||
Icons.Outlined.Redo,
|
TopBarAction(
|
||||||
mainViewModel.isRedoActionActive,
|
Icons.Outlined.Redo,
|
||||||
{ mainViewModel.redoLastRound() }),
|
mainViewModel.isRedoActionActive,
|
||||||
TopBarAction(
|
{ mainViewModel.redoLastRound() }),
|
||||||
Icons.Outlined.MoreVert,
|
TopBarAction(
|
||||||
mainViewModel.activeGameHasRounds,
|
Icons.Outlined.MoreVert,
|
||||||
{ expanded = true }
|
mainViewModel.activeGameHasRounds,
|
||||||
) {
|
{ expanded = true }
|
||||||
DropDownMenu(
|
|
||||||
mapOf("new" to R.string.newGame),
|
|
||||||
"",
|
|
||||||
expanded,
|
|
||||||
) {
|
) {
|
||||||
expanded = false
|
DropDownMenu(
|
||||||
it?.let {
|
mapOf("new" to R.string.newGame),
|
||||||
when (it) {
|
"",
|
||||||
"new" -> mainViewModel.newGame()
|
expanded,
|
||||||
|
) {
|
||||||
|
expanded = false
|
||||||
|
it?.let {
|
||||||
|
when (it) {
|
||||||
|
"new" -> mainViewModel.newGame()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
},
|
|
||||||
|
|
||||||
))
|
))
|
||||||
topBarIcon = Icons.Outlined.Menu
|
) { scope.launch { drawerState.open() } }
|
||||||
topBarTitle = stringResource(R.string.app_name)
|
|
||||||
topBarNavigationAction =
|
Counter(counterViewModel)
|
||||||
NavigationAction { scope.launch { drawerState.open() } }
|
|
||||||
}
|
}
|
||||||
composable("history") {
|
composable(Route.HISTORY) {
|
||||||
|
topBarState =
|
||||||
|
TopBarState(title = stringResource(R.string.menu_history)) { scope.launch { drawerState.open() } }
|
||||||
|
|
||||||
HistoryList(historyViewModel) { navController.navigate("counter") }
|
HistoryList(historyViewModel) { navController.navigate(Route.COUNTER) }
|
||||||
|
|
||||||
topBarActions = emptyList()
|
|
||||||
topBarIcon = Icons.Outlined.Menu
|
|
||||||
topBarTitle = stringResource(R.string.menu_history)
|
|
||||||
topBarNavigationAction =
|
|
||||||
NavigationAction { scope.launch { drawerState.open() } }
|
|
||||||
}
|
}
|
||||||
composable("settings") {
|
composable(Route.SETTINGS) {
|
||||||
|
topBarState =
|
||||||
|
TopBarState(title = stringResource(R.string.menu_settings)) { scope.launch { drawerState.open() } }
|
||||||
|
|
||||||
SettingsView(settingsViewModel)
|
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 navController = rememberNavController()
|
||||||
|
|
||||||
val items = listOf(
|
val items = listOf(
|
||||||
Screen("counter", Icons.Outlined.Calculate, R.string.app_name),
|
Screen(Route.COUNTER, Icons.Outlined.Calculate, R.string.app_name),
|
||||||
Screen("history", Icons.Outlined.List, R.string.menu_history),
|
Screen(Route.HISTORY, Icons.Outlined.List, R.string.menu_history),
|
||||||
Screen("settings", Icons.Outlined.Settings, R.string.menu_settings)
|
Screen(Route.SETTINGS, Icons.Outlined.Settings, R.string.menu_settings)
|
||||||
)
|
)
|
||||||
|
|
||||||
val navBackStackEntry by navController.currentBackStackEntryAsState()
|
val navBackStackEntry by navController.currentBackStackEntryAsState()
|
||||||
val currentDestination = navBackStackEntry?.destination
|
val currentDestination =
|
||||||
|
Route.valueOf(navBackStackEntry?.destination?.route ?: Route.COUNTER.name)
|
||||||
|
|
||||||
ModalNavigationDrawer(
|
ModalNavigationDrawer(
|
||||||
drawerState = drawerState,
|
drawerState = drawerState,
|
||||||
gesturesEnabled = drawerState.isOpen,
|
gesturesEnabled = drawerState.isOpen,
|
||||||
drawerContent = {
|
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,
|
drawerState,
|
||||||
scope,
|
scope,
|
||||||
navController,
|
navController,
|
||||||
counterViewModel.keyboardHidden && (currentDestination?.hierarchy?.any { it.route == "counter" } == true)
|
counterViewModel.keyboardHidden && (currentDestination == Route.COUNTER)
|
||||||
) { counterViewModel.showKeyboard() }
|
) { 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)
|
||||||
}
|
}
|
||||||
@@ -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)
|
||||||
|
}
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
package me.zobrist.tichucounter.domain
|
|
||||||
|
|
||||||
class NavigationAction(val action: () -> Unit)
|
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
package me.zobrist.tichucounter.domain
|
||||||
|
|
||||||
|
enum class Route { COUNTER, HISTORY, SETTINGS }
|
||||||
@@ -3,4 +3,9 @@ package me.zobrist.tichucounter.domain
|
|||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.graphics.vector.ImageVector
|
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 = {}
|
||||||
|
)
|
||||||
@@ -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 = {}
|
||||||
|
)
|
||||||
@@ -5,6 +5,17 @@ import androidx.compose.runtime.Composable
|
|||||||
import androidx.compose.ui.graphics.vector.ImageVector
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import me.zobrist.tichucounter.domain.TopBarAction
|
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)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
|
|||||||
Reference in New Issue
Block a user