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.
166 lines
5.8 KiB
166 lines
5.8 KiB
/* |
|
* 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 |
|
//}
|
|
|