You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
167 lines
5.8 KiB
167 lines
5.8 KiB
2 months ago
|
/*
|
||
|
* Copyright 2021 The Android Open Source Project
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*/
|
||
|
|
||
|
package com.example.jetsnack.ui
|
||
|
|
||
|
import androidx.compose.material.ScaffoldState
|
||
|
import androidx.compose.material.rememberScaffoldState
|
||
|
import androidx.compose.runtime.Composable
|
||
|
import androidx.compose.runtime.ReadOnlyComposable
|
||
|
import androidx.compose.runtime.Stable
|
||
|
import androidx.compose.runtime.remember
|
||
|
import androidx.compose.runtime.rememberCoroutineScope
|
||
|
import com.example.jetsnack.model.SnackbarManager
|
||
|
import com.example.jetsnack.ui.home.HomeSections
|
||
|
import kotlinx.coroutines.CoroutineScope
|
||
|
import kotlinx.coroutines.flow.collect
|
||
|
import kotlinx.coroutines.launch
|
||
|
|
||
|
/**
|
||
|
* Destinations used in the [JetsnackApp].
|
||
|
*/
|
||
|
object MainDestinations {
|
||
|
const val HOME_ROUTE = "home"
|
||
|
const val SNACK_DETAIL_ROUTE = "snack"
|
||
|
const val SNACK_ID_KEY = "snackId"
|
||
|
}
|
||
|
|
||
|
|
||
|
@Composable
|
||
|
expect fun rememberMppJetsnackAppState(): MppJetsnackAppState
|
||
|
|
||
|
@Stable
|
||
|
expect class MppJetsnackAppState {
|
||
|
|
||
|
val scaffoldState: ScaffoldState
|
||
|
val snackbarManager: SnackbarManager
|
||
|
val coroutineScope: CoroutineScope
|
||
|
val bottomBarTabs: Array<HomeSections>
|
||
|
val currentRoute: String?
|
||
|
|
||
|
@Composable
|
||
|
fun shouldShowBottomBar(): Boolean
|
||
|
|
||
|
fun navigateToBottomBarRoute(route: String)
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Responsible for holding state related to [JetsnackApp] and containing UI-related logic.
|
||
|
*/
|
||
|
@Stable
|
||
|
class JetsnackAppState(
|
||
|
val scaffoldState: ScaffoldState,
|
||
|
// val navController: NavHostController,
|
||
|
private val snackbarManager: SnackbarManager,
|
||
|
// private val resources: Resources,
|
||
|
coroutineScope: CoroutineScope
|
||
|
) {
|
||
|
// Process snackbars coming from SnackbarManager
|
||
|
init {
|
||
|
coroutineScope.launch {
|
||
|
snackbarManager.messages.collect { currentMessages ->
|
||
|
if (currentMessages.isNotEmpty()) {
|
||
|
val message = currentMessages[0]
|
||
|
// TODO: implement
|
||
|
val text = "TODO: resources.getText(message.messageId)"
|
||
|
|
||
|
// Display the snackbar on the screen. `showSnackbar` is a function
|
||
|
// that suspends until the snackbar disappears from the screen
|
||
|
scaffoldState.snackbarHostState.showSnackbar(text.toString())
|
||
|
// Once the snackbar is gone or dismissed, notify the SnackbarManager
|
||
|
snackbarManager.setMessageShown(message.id)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// ----------------------------------------------------------
|
||
|
// BottomBar state source of truth
|
||
|
// ----------------------------------------------------------
|
||
|
|
||
|
val bottomBarTabs = HomeSections.values()
|
||
|
private val bottomBarRoutes = bottomBarTabs.map { it.route }
|
||
|
|
||
|
// Reading this attribute will cause recompositions when the bottom bar needs shown, or not.
|
||
|
// Not all routes need to show the bottom bar.
|
||
|
val shouldShowBottomBar: Boolean
|
||
|
@Composable get() = true
|
||
|
// navController
|
||
|
// .currentBackStackEntryAsState().value?.destination?.route in bottomBarRoutes
|
||
|
|
||
|
// ----------------------------------------------------------
|
||
|
// Navigation state source of truth
|
||
|
// ----------------------------------------------------------
|
||
|
|
||
|
val currentRoute: String?
|
||
|
get() = HomeSections.FEED.route//navController.currentDestination?.route
|
||
|
|
||
|
fun upPress() {
|
||
|
// navController.navigateUp()
|
||
|
}
|
||
|
|
||
|
fun navigateToBottomBarRoute(route: String) {
|
||
|
// if (route != currentRoute) {
|
||
|
// navController.navigate(route) {
|
||
|
// launchSingleTop = true
|
||
|
// restoreState = true
|
||
|
// // Pop up backstack to the first destination and save state. This makes going back
|
||
|
// // to the start destination when pressing back in any other bottom tab.
|
||
|
// popUpTo(findStartDestination(navController.graph).id) {
|
||
|
// saveState = true
|
||
|
// }
|
||
|
// }
|
||
|
// }
|
||
|
}
|
||
|
|
||
|
// fun navigateToSnackDetail(snackId: Long, from: NavBackStackEntry) {
|
||
|
// In order to discard duplicated navigation events, we check the Lifecycle
|
||
|
// if (from.lifecycleIsResumed()) {
|
||
|
// navController.navigate("${MainDestinations.SNACK_DETAIL_ROUTE}/$snackId")
|
||
|
// }
|
||
|
// }
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* If the lifecycle is not resumed it means this NavBackStackEntry already processed a nav event.
|
||
|
*
|
||
|
* This is used to de-duplicate navigation events.
|
||
|
*/
|
||
|
//private fun NavBackStackEntry.lifecycleIsResumed() =
|
||
|
// this.getLifecycle().currentState == Lifecycle.State.RESUMED
|
||
|
//
|
||
|
//private val NavGraph.startDestination: NavDestination?
|
||
|
// get() = findNode(startDestinationId)
|
||
|
|
||
|
/**
|
||
|
* Copied from similar function in NavigationUI.kt
|
||
|
*
|
||
|
* https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:navigation/navigation-ui/src/main/java/androidx/navigation/ui/NavigationUI.kt
|
||
|
*/
|
||
|
//private tailrec fun findStartDestination(graph: NavDestination): NavDestination {
|
||
|
// return if (graph is NavGraph) findStartDestination(graph.startDestination!!) else graph
|
||
|
//}
|
||
|
|
||
|
/**
|
||
|
* A composable function that returns the [Resources]. It will be recomposed when `Configuration`
|
||
|
* gets updated.
|
||
|
*/
|
||
|
//@Composable
|
||
|
//@ReadOnlyComposable
|
||
|
//private fun resources(): Resources {
|
||
|
// LocalConfiguration.current
|
||
|
// return LocalContext.current.resources
|
||
|
//}
|