move navigation drawer to bottom tabs?
This commit is contained in:
parent
ebb3663f06
commit
28459c13f6
4 changed files with 78 additions and 137 deletions
|
@ -27,6 +27,8 @@ abstract class EntryListViewModel(
|
|||
private val _errorMessage = MutableStateFlow<String?>(null)
|
||||
val errorMessage = _errorMessage.asStateFlow()
|
||||
protected open val entryStatus: EntryStatus? = null
|
||||
protected open val feedId: Int? = null
|
||||
protected open val categoryId: Int? = null
|
||||
private lateinit var pagingSource: EntryAndFeedPagingSource
|
||||
val entries = Pager(PagingConfig(pageSize = 15)) {
|
||||
EntryAndFeedPagingSource(entryRepository, entryStatus).also {
|
||||
|
|
|
@ -35,7 +35,6 @@ fun EntryScreen(
|
|||
entryId: Long,
|
||||
navController: NavController,
|
||||
entryViewModel: EntryViewModel,
|
||||
setTitle: (String) -> Unit,
|
||||
) {
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
val context = LocalContext.current
|
||||
|
@ -58,7 +57,7 @@ fun EntryScreen(
|
|||
entry?.let {
|
||||
LaunchedEffect(it.entry.title) {
|
||||
// TODO: Use Material3 to use collapsing toolbar
|
||||
setTitle(it.entry.title)
|
||||
// setTitle(it.entry.title)
|
||||
}
|
||||
EntryScreen(
|
||||
entry = it,
|
||||
|
|
|
@ -74,176 +74,114 @@ fun MainScaffold(
|
|||
) {
|
||||
val snackbarHostState = remember { SnackbarHostState() }
|
||||
val scaffoldState = rememberScaffoldState(snackbarHostState = snackbarHostState)
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
val (title, setTitle) = remember { mutableStateOf("Unread") }
|
||||
Scaffold(
|
||||
scaffoldState = scaffoldState,
|
||||
topBar = {
|
||||
TopAppBar(
|
||||
modifier = Modifier.statusBarsPadding(),
|
||||
navigationIcon = {
|
||||
IconButton(onClick = {
|
||||
coroutineScope.launch {
|
||||
if (navController.currentDestination?.route?.startsWith("entries/") == true) {
|
||||
navController.popBackStack()
|
||||
} else {
|
||||
scaffoldState.drawerState.open()
|
||||
}
|
||||
}
|
||||
}) {
|
||||
val icon =
|
||||
if (navController.currentDestination?.route?.startsWith("entries/") == true) {
|
||||
Icons.Default.ArrowBack
|
||||
} else {
|
||||
Icons.Default.Menu
|
||||
}
|
||||
Icon(
|
||||
imageVector = icon,
|
||||
contentDescription = "Menu"
|
||||
)
|
||||
}
|
||||
},
|
||||
title = {
|
||||
Text(text = "nano")
|
||||
Text(text = "flux", color = MaterialTheme.colors.primary)
|
||||
},
|
||||
actions = {
|
||||
IconButton(onClick = onSettingsClicked) {
|
||||
Icon(Icons.Default.Settings, contentDescription = "Settings", tint = MaterialTheme.colors.onSurface)
|
||||
}
|
||||
}
|
||||
)
|
||||
},
|
||||
bottomBar = {
|
||||
BottomAppBar(
|
||||
modifier = Modifier.navigationBarsPadding(),
|
||||
backgroundColor = MaterialTheme.colors.surface
|
||||
) {
|
||||
BottomNavigationItem(
|
||||
selected = navController.currentDestination?.route == null || navController.currentDestination?.route == "unread",
|
||||
onClick = onUnreadClicked,
|
||||
icon = { Icon(Icons.Default.Article, contentDescription = null) },
|
||||
label = { Text("Entries") },
|
||||
selectedContentColor = MaterialTheme.colors.primary
|
||||
)
|
||||
// BottomNavigationItem(
|
||||
// selected = navController.currentDestination?.route == "starred",
|
||||
// onClick = onStarredClicked,
|
||||
// icon = { Icon(Icons.Default.Star, contentDescription = null) },
|
||||
// label = { Text("Starred") },
|
||||
// selectedContentColor = MaterialTheme.colors.primary
|
||||
// )
|
||||
// BottomNavigationItem(
|
||||
// selected = navController.currentDestination?.route == "history",
|
||||
// onClick = onHistoryClicked,
|
||||
// icon = { Icon(Icons.Default.DateRange, contentDescription = null) },
|
||||
// label = { Text("History") },
|
||||
// selectedContentColor = MaterialTheme.colors.primary
|
||||
// )
|
||||
BottomNavigationItem(
|
||||
selected = navController.currentDestination?.route == "feeds",
|
||||
onClick = onFeedsClicked,
|
||||
icon = { Icon(Icons.Default.List, contentDescription = null) },
|
||||
label = { Text("Feeds") },
|
||||
selectedContentColor = MaterialTheme.colors.primary,
|
||||
enabled = false // remove when implemented
|
||||
)
|
||||
BottomNavigationItem(
|
||||
selected = navController.currentDestination?.route == "categories",
|
||||
onClick = onCategoriesClicked,
|
||||
icon = { Icon(Icons.Default.Category, contentDescription = null) },
|
||||
label = {
|
||||
Text(
|
||||
text = title,
|
||||
text = "Categories",
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis
|
||||
)
|
||||
})
|
||||
},
|
||||
drawerContent = {
|
||||
val topPadding = WindowInsets.statusBars.asPaddingValues().calculateTopPadding() + 8.dp
|
||||
Row(Modifier.padding(top = topPadding, start = 8.dp, end = 8.dp, bottom = 8.dp)) {
|
||||
Text(text = "nano", fontSize = 24.sp)
|
||||
Text(text = "flux", color = MaterialTheme.colors.primary, fontSize = 24.sp)
|
||||
}
|
||||
DrawerButton(
|
||||
onClick = {
|
||||
onUnreadClicked()
|
||||
coroutineScope.launch {
|
||||
scaffoldState.drawerState.close()
|
||||
}
|
||||
},
|
||||
icon = Icons.Default.Email, text = "Unread"
|
||||
)
|
||||
DrawerButton(
|
||||
onClick = {
|
||||
onStarredClicked()
|
||||
coroutineScope.launch {
|
||||
scaffoldState.drawerState.close()
|
||||
}
|
||||
},
|
||||
icon = Icons.Default.Star,
|
||||
text = "Starred"
|
||||
)
|
||||
DrawerButton(
|
||||
onClick = {
|
||||
onHistoryClicked()
|
||||
coroutineScope.launch {
|
||||
scaffoldState.drawerState.close()
|
||||
}
|
||||
},
|
||||
icon = Icons.Default.DateRange,
|
||||
text = "History"
|
||||
)
|
||||
DrawerButton(
|
||||
onClick = {
|
||||
onFeedsClicked()
|
||||
coroutineScope.launch {
|
||||
scaffoldState.drawerState.close()
|
||||
}
|
||||
},
|
||||
icon = Icons.Default.List,
|
||||
text = "Feeds"
|
||||
)
|
||||
DrawerButton(
|
||||
onClick = {
|
||||
onCategoriesClicked()
|
||||
coroutineScope.launch {
|
||||
scaffoldState.drawerState.close()
|
||||
}
|
||||
},
|
||||
icon = Icons.Default.Info,
|
||||
text = "Categories"
|
||||
)
|
||||
DrawerButton(
|
||||
onClick = {
|
||||
onSettingsClicked()
|
||||
coroutineScope.launch {
|
||||
scaffoldState.drawerState.close()
|
||||
}
|
||||
},
|
||||
icon = Icons.Default.Settings,
|
||||
text = "Settings"
|
||||
selectedContentColor = MaterialTheme.colors.primary,
|
||||
enabled = false // remove when implemented
|
||||
)
|
||||
}
|
||||
) {
|
||||
},
|
||||
) { padding ->
|
||||
// TODO: Extract routes to constants
|
||||
NavHost(
|
||||
modifier = Modifier.padding(it),
|
||||
modifier = Modifier.padding(padding),
|
||||
navController = navController,
|
||||
startDestination = "unread"
|
||||
) {
|
||||
composable("unread") {
|
||||
LaunchedEffect(navController.currentBackStackEntry) {
|
||||
setTitle("Unread")
|
||||
}
|
||||
EntryListScreen(navController, snackbarHostState, hiltViewModel<UnreadViewModel>())
|
||||
}
|
||||
composable("starred") {
|
||||
LaunchedEffect(navController.currentBackStackEntry) {
|
||||
setTitle("Starred")
|
||||
}
|
||||
EntryListScreen(navController, snackbarHostState, hiltViewModel<StarredViewModel>())
|
||||
}
|
||||
composable("history") {
|
||||
LaunchedEffect(navController.currentBackStackEntry) {
|
||||
setTitle("History")
|
||||
EntryListScreen(navController, snackbarHostState, hiltViewModel<HistoryViewModel>())
|
||||
}
|
||||
composable(
|
||||
"feeds/{feedId}",
|
||||
arguments = listOf(navArgument("feedId") { type = NavType.LongType })
|
||||
) {
|
||||
EntryListScreen(navController, snackbarHostState, hiltViewModel<HistoryViewModel>())
|
||||
}
|
||||
composable(
|
||||
"categories/{categoryId}",
|
||||
arguments = listOf(navArgument("categoryId") { type = NavType.LongType })
|
||||
) {
|
||||
EntryListScreen(navController, snackbarHostState, hiltViewModel<HistoryViewModel>())
|
||||
}
|
||||
composable(
|
||||
"entries/{entryId}",
|
||||
arguments = listOf(navArgument("entryId") { type = NavType.LongType })
|
||||
) {
|
||||
LaunchedEffect(navController.currentBackStackEntry) {
|
||||
setTitle("")
|
||||
}
|
||||
EntryScreen(
|
||||
it.arguments!!.getLong("entryId"),
|
||||
navController,
|
||||
hiltViewModel(),
|
||||
setTitle,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun DrawerButton(onClick: () -> Unit, icon: ImageVector, text: String) {
|
||||
TextButton(onClick = onClick, modifier = Modifier.fillMaxWidth()) {
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.Start,
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
) {
|
||||
Icon(
|
||||
imageVector = icon,
|
||||
contentDescription = null,
|
||||
tint = MaterialTheme.colors.onSurface
|
||||
)
|
||||
Spacer(Modifier.width(16.dp))
|
||||
Text(
|
||||
text = text,
|
||||
color = MaterialTheme.colors.onSurface,
|
||||
modifier = Modifier.padding(8.dp),
|
||||
style = MaterialTheme.typography.body2
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview
|
||||
fun MainScaffold_Preview() {
|
||||
|
|
|
@ -9,7 +9,9 @@ import timber.log.Timber
|
|||
|
||||
class EntryAndFeedPagingSource(
|
||||
private val entryRepository: EntryRepository,
|
||||
private val entryStatus: EntryStatus? = null
|
||||
private val entryStatus: EntryStatus? = null,
|
||||
private val feedId: Long? = null,
|
||||
private val categoryId: Long? = null,
|
||||
) : PagingSource<Int, EntryAndFeed>() {
|
||||
init {
|
||||
Timber.tag("Nanoflux").d("EntryAndFeedPagingSource created")
|
||||
|
|
Loading…
Reference in a new issue