WIP remove DI 2

pull/2003/head
Don Turner 1 week ago
parent c9bba49957
commit 386d1a0a16

@ -78,18 +78,9 @@ class MainActivity : ComponentActivity() {
@Inject
lateinit var userNewsResourceRepository: UserNewsResourceRepository
/*@Inject
lateinit var entryProviderBuilders: Set<@JvmSuppressWildcards EntryProviderScope<NavKey>.() -> Unit>
*/
/*@Inject
lateinit var niaNavigator: NiaNavigator*/
private val viewModel: MainActivityViewModel by viewModels()
// TODO: This isn't used
//private val backStackViewModel: NiaBackStackViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
val splashScreen = installSplashScreen()
super.onCreate(savedInstanceState)
@ -153,7 +144,6 @@ class MainActivity : ComponentActivity() {
networkMonitor = networkMonitor,
userNewsResourceRepository = userNewsResourceRepository,
timeZoneMonitor = timeZoneMonitor,
//niaNavigator = niaNavigator,
)
val currentTimeZone by appState.currentTimeZone.collectAsStateWithLifecycle()
@ -167,9 +157,7 @@ class MainActivity : ComponentActivity() {
androidTheme = themeSettings.androidTheme,
disableDynamicTheming = themeSettings.disableDynamicTheming,
) {
NiaApp(
appState
)
NiaApp(appState)
}
}
}

@ -16,18 +16,6 @@
package com.google.samples.apps.nowinandroid.di
import com.google.samples.apps.nowinandroid.core.navigation.NiaNavKey
import com.google.samples.apps.nowinandroid.core.navigation.NiaNavigationState
import com.google.samples.apps.nowinandroid.navigation.TopLevelDestination
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import kotlinx.serialization.modules.PolymorphicModuleBuilder
import kotlinx.serialization.modules.SerializersModule
import kotlinx.serialization.modules.polymorphic
import javax.inject.Singleton
// TODO: Rename to `NiaNavigationStateProvider`
// Does this even need to be injected? Can't we just instantiate it directly using `rememberNavigationState`?
/*

@ -81,35 +81,32 @@ enum class TopLevelDestination(
internal val TopLevelDestinations = TopLevelDestination.entries.associateBy { dest -> dest.key }
*/
val FOR_YOU = TopLevelDestination(
val FOR_YOU = NavBarItem(
selectedIcon = NiaIcons.Upcoming,
unselectedIcon = NiaIcons.UpcomingBorder,
iconTextId = forYouR.string.feature_foryou_api_title,
titleTextId = R.string.app_name,
route = ForYouRoute::class,
key = ForYouRoute,
)
val BOOKMARKS = TopLevelDestination(
val BOOKMARKS = NavBarItem(
selectedIcon = NiaIcons.Bookmarks,
unselectedIcon = NiaIcons.BookmarksBorder,
iconTextId = bookmarksR.string.feature_bookmarks_api_title,
titleTextId = bookmarksR.string.feature_bookmarks_api_title,
route = BookmarksRoute::class,
key = BookmarksRoute,
)
val INTERESTS = TopLevelDestination(
val INTERESTS = NavBarItem(
selectedIcon = NiaIcons.Grid3x3,
unselectedIcon = NiaIcons.Grid3x3,
iconTextId = searchR.string.feature_search_api_interests,
titleTextId = searchR.string.feature_search_api_interests,
route = InterestsRoute::class,
key = InterestsRoute(null)
)
val TOP_LEVEL_ROUTES = mapOf<NavKey, TopLevelDestination>(
val TOP_LEVEL_ROUTES = mapOf<NavKey, NavBarItem>(
ForYouRoute to FOR_YOU,
BookmarksRoute to BOOKMARKS,
InterestsRoute(null) to INTERESTS,
@ -117,8 +114,8 @@ val TOP_LEVEL_ROUTES = mapOf<NavKey, TopLevelDestination>(
/**
* Type for the top level destinations in the application. Contains metadata about the destination
* that is used in the top app bar and common navigation UI.
* Type for the top level navigation items in the application. Contains UI information about the
* current route that is used in the top app bar and common navigation UI.
*
* @param selectedIcon The icon to be displayed in the navigation UI when this destination is
* selected.
@ -126,15 +123,13 @@ val TOP_LEVEL_ROUTES = mapOf<NavKey, TopLevelDestination>(
* not selected.
* @param iconTextId Text that to be displayed in the navigation UI.
* @param titleTextId Text that is displayed on the top app bar.
* @param route The route to use when navigating to this destination.
* @param baseRoute The highest ancestor of this destination. Defaults to [route], meaning that
* @param key The navigation key to use when navigating to this destination.
* there is a single destination in that section of the app (no nested destinations).
*/
data class TopLevelDestination(
data class NavBarItem(
val selectedIcon: ImageVector,
val unselectedIcon: ImageVector,
@StringRes val iconTextId: Int,
@StringRes val titleTextId: Int,
val route: KClass<*>,
val key: NavKey,
)

@ -61,11 +61,9 @@ import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.semantics.testTagsAsResourceId
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.navigation3.runtime.EntryProviderScope
import androidx.navigation3.runtime.NavKey
import androidx.navigation3.runtime.entryProvider
import androidx.navigation3.ui.NavDisplay
import com.example.nav3recipes.multiplestacks.Navigator
import com.google.samples.apps.nowinandroid.R
import com.google.samples.apps.nowinandroid.core.designsystem.component.NiaBackground
import com.google.samples.apps.nowinandroid.core.designsystem.component.NiaGradientBackground
@ -74,9 +72,8 @@ import com.google.samples.apps.nowinandroid.core.designsystem.component.NiaTopAp
import com.google.samples.apps.nowinandroid.core.designsystem.icon.NiaIcons
import com.google.samples.apps.nowinandroid.core.designsystem.theme.GradientColors
import com.google.samples.apps.nowinandroid.core.designsystem.theme.LocalGradientColors
import com.google.samples.apps.nowinandroid.core.navigation.NiaNavKey
import com.google.samples.apps.nowinandroid.core.navigation.simple.Navigator
import com.google.samples.apps.nowinandroid.core.navigation.simple.toEntries
import com.google.samples.apps.nowinandroid.core.navigation.toEntries
import com.google.samples.apps.nowinandroid.feature.bookmarks.impl.navigation.LocalSnackbarHostState
import com.google.samples.apps.nowinandroid.feature.bookmarks.impl.navigation.bookmarksEntry
import com.google.samples.apps.nowinandroid.feature.foryou.impl.navigation.forYouEntry
@ -94,10 +91,8 @@ fun NiaApp(
appState: NiaAppState,
modifier: Modifier = Modifier,
windowAdaptiveInfo: WindowAdaptiveInfo = currentWindowAdaptiveInfo(),
//entryProviderBuilders: Set<EntryProviderScope<NavKey>.() -> Unit>,
) {
val shouldShowGradientBackground =
appState.currentTopLevelDestination == FOR_YOU
val shouldShowGradientBackground = appState.currentNavBarItem == FOR_YOU
var showSettingsDialog by rememberSaveable { mutableStateOf(false) }
NiaBackground(modifier = modifier) {
@ -125,11 +120,12 @@ fun NiaApp(
CompositionLocalProvider(LocalSnackbarHostState provides snackbarHostState) {
NiaApp(
appState = appState,
// TODO: Settings should be a dialog screen
showSettingsDialog = showSettingsDialog,
onSettingsDismissed = { showSettingsDialog = false },
onTopAppBarActionClick = { showSettingsDialog = true },
windowAdaptiveInfo = windowAdaptiveInfo,
//entryProviderBuilders = entryProviderBuilders,
)
}
}
@ -148,11 +144,9 @@ internal fun NiaApp(
onTopAppBarActionClick: () -> Unit,
modifier: Modifier = Modifier,
windowAdaptiveInfo: WindowAdaptiveInfo = currentWindowAdaptiveInfo(),
//entryProviderBuilders: Set<EntryProviderScope<NavKey>.() -> Unit>,
) {
val unreadDestinations by appState.topLevelDestinationsWithUnreadResources
.collectAsStateWithLifecycle()
val currentTopLevelKey = appState.currentTopLevelDestination!!.key
if (showSettingsDialog) {
SettingsDialog(
@ -166,25 +160,25 @@ internal fun NiaApp(
NiaNavigationSuiteScaffold(
navigationSuiteItems = {
TOP_LEVEL_ROUTES.values.forEach { destination ->
val hasUnread = unreadDestinations.contains(destination)
val selected = destination.key == currentTopLevelKey
TOP_LEVEL_ROUTES.forEach { (navKey, navBarItem) ->
val hasUnread = unreadDestinations.contains(navBarItem)
val selected = navKey == appState.navigationState.topLevelRoute
item(
selected = selected,
onClick = { navigator.navigate(destination.key) },
onClick = { navigator.navigate(navKey) },
icon = {
Icon(
imageVector = destination.unselectedIcon,
imageVector = navBarItem.unselectedIcon,
contentDescription = null,
)
},
selectedIcon = {
Icon(
imageVector = destination.selectedIcon,
imageVector = navBarItem.selectedIcon,
contentDescription = null,
)
},
label = { Text(stringResource(destination.iconTextId)) },
label = { Text(stringResource(navBarItem.iconTextId)) },
modifier = Modifier
.testTag("NiaNavItem")
.then(if (hasUnread) Modifier.notificationDot() else Modifier),
@ -223,7 +217,7 @@ internal fun NiaApp(
),
) {
// Show the top app bar on top level destinations.
val destination = appState.currentTopLevelDestination
val destination = appState.currentNavBarItem
var shouldShowTopAppBar = false
if (destination != null) {

@ -23,15 +23,13 @@ import androidx.compose.runtime.rememberCoroutineScope
import com.google.samples.apps.nowinandroid.core.data.repository.UserNewsResourceRepository
import com.google.samples.apps.nowinandroid.core.data.util.NetworkMonitor
import com.google.samples.apps.nowinandroid.core.data.util.TimeZoneMonitor
import com.google.samples.apps.nowinandroid.core.navigation.NiaNavigator
import com.google.samples.apps.nowinandroid.core.navigation.simple.NavigationState
import com.google.samples.apps.nowinandroid.core.navigation.simple.rememberNavigationState
import com.google.samples.apps.nowinandroid.feature.foryou.api.navigation.ForYouRoute
import com.google.samples.apps.nowinandroid.navigation.BOOKMARKS
import com.google.samples.apps.nowinandroid.navigation.FOR_YOU
import com.google.samples.apps.nowinandroid.navigation.TopLevelDestination
import com.google.samples.apps.nowinandroid.navigation.TOP_LEVEL_ROUTES
//import com.google.samples.apps.nowinandroid.navigation.TopLevelDestinations
import com.google.samples.apps.nowinandroid.navigation.NavBarItem
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
@ -45,15 +43,14 @@ fun rememberNiaAppState(
networkMonitor: NetworkMonitor,
userNewsResourceRepository: UserNewsResourceRepository,
timeZoneMonitor: TimeZoneMonitor,
//niaNavigator: NiaNavigator,
coroutineScope: CoroutineScope = rememberCoroutineScope(),
): NiaAppState {
//NavigationTrackingSideEffect(niaNavigator)
val navigationState = rememberNavigationState(ForYouRoute, TOP_LEVEL_ROUTES.keys)
NavigationTrackingSideEffect(navigationState)
return remember(
//niaNavigator,
navigationState,
coroutineScope,
networkMonitor,
@ -61,7 +58,6 @@ fun rememberNiaAppState(
timeZoneMonitor,
) {
NiaAppState(
//niaNavigator = niaNavigator,
navigationState = navigationState,
coroutineScope = coroutineScope,
networkMonitor = networkMonitor,
@ -73,19 +69,13 @@ fun rememberNiaAppState(
@Stable
class NiaAppState(
//val niaNavigator: NiaNavigator,
val navigationState: NavigationState,
coroutineScope: CoroutineScope,
networkMonitor: NetworkMonitor,
userNewsResourceRepository: UserNewsResourceRepository,
timeZoneMonitor: TimeZoneMonitor,
) {
/*
val currentTopLevelDestination: TopLevelDestination?
@Composable get() = TOP_LEVEL_ROUTES[niaNavigator.navigationState.currentTopLevelKey]
*/
// TODO: It seems unnecessary to expose this as a TopLevelDestination rather than just a key
val currentTopLevelDestination: TopLevelDestination?
val currentNavBarItem: NavBarItem?
@Composable get() = TOP_LEVEL_ROUTES[navigationState.topLevelRoute]
val isOffline = networkMonitor.isOnline
@ -99,7 +89,7 @@ class NiaAppState(
/**
* The top level destinations that have unread news resources.
*/
val topLevelDestinationsWithUnreadResources: StateFlow<Set<TopLevelDestination>> =
val topLevelDestinationsWithUnreadResources: StateFlow<Set<NavBarItem>> =
userNewsResourceRepository.observeAllForFollowedTopics()
.combine(userNewsResourceRepository.observeAllBookmarked()) { forYouNewsResources, bookmarkedNewsResources ->
setOfNotNull(
@ -125,9 +115,9 @@ class NiaAppState(
* Stores information about navigation events to be used with JankStats
*/
// TODO: This shouldn't be commented out
// TODO: NavigationState needs to expose an observable representation of its state for this to work
@Composable
private fun NavigationTrackingSideEffect(niaNavigator: NiaNavigator) {
private fun NavigationTrackingSideEffect(navigationState: NavigationState) {
// TrackDisposableJank(niaNavigator) { metricsHolder ->
// snapshotFlow {
// val stack = niaNavigator.backStack.toList()

@ -14,10 +14,9 @@
* limitations under the License.
*/
package com.example.nav3recipes.multiplestacks
package com.google.samples.apps.nowinandroid.core.navigation.simple
import androidx.navigation3.runtime.NavKey
import com.google.samples.apps.nowinandroid.core.navigation.simple.NavigationState
/**
* Handles navigation events (forward and back) by updating the navigation state.

@ -22,9 +22,7 @@ import androidx.compose.material3.SnackbarResult.ActionPerformed
import androidx.compose.runtime.compositionLocalOf
import androidx.navigation3.runtime.EntryProviderScope
import androidx.navigation3.runtime.NavKey
import com.example.nav3recipes.multiplestacks.Navigator
import com.google.samples.apps.nowinandroid.core.navigation.NiaNavKey
import com.google.samples.apps.nowinandroid.core.navigation.NiaNavigator
import com.google.samples.apps.nowinandroid.core.navigation.simple.Navigator
import com.google.samples.apps.nowinandroid.feature.bookmarks.api.navigation.BookmarksRoute
import com.google.samples.apps.nowinandroid.feature.bookmarks.impl.BookmarksScreen
import com.google.samples.apps.nowinandroid.feature.topic.api.navigation.TopicRoute

@ -18,9 +18,7 @@ package com.google.samples.apps.nowinandroid.feature.foryou.impl.navigation
import androidx.navigation3.runtime.EntryProviderScope
import androidx.navigation3.runtime.NavKey
import com.example.nav3recipes.multiplestacks.Navigator
import com.google.samples.apps.nowinandroid.core.navigation.NiaNavKey
import com.google.samples.apps.nowinandroid.core.navigation.NiaNavigator
import com.google.samples.apps.nowinandroid.core.navigation.simple.Navigator
import com.google.samples.apps.nowinandroid.feature.foryou.api.navigation.ForYouRoute
import com.google.samples.apps.nowinandroid.feature.foryou.impl.ForYouScreen
import com.google.samples.apps.nowinandroid.feature.topic.api.navigation.TopicRoute

@ -21,9 +21,7 @@ import androidx.compose.material3.adaptive.navigation3.ListDetailSceneStrategy
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import androidx.navigation3.runtime.EntryProviderScope
import androidx.navigation3.runtime.NavKey
import com.example.nav3recipes.multiplestacks.Navigator
import com.google.samples.apps.nowinandroid.core.navigation.NiaNavKey
import com.google.samples.apps.nowinandroid.core.navigation.NiaNavigator
import com.google.samples.apps.nowinandroid.core.navigation.simple.Navigator
import com.google.samples.apps.nowinandroid.feature.interests.api.navigation.InterestsRoute
import com.google.samples.apps.nowinandroid.feature.interests.impl.InterestsDetailPlaceholder
import com.google.samples.apps.nowinandroid.feature.interests.impl.InterestsScreen

@ -18,13 +18,10 @@ package com.google.samples.apps.nowinandroid.feature.search.impl.navigation
import androidx.navigation3.runtime.EntryProviderScope
import androidx.navigation3.runtime.NavKey
import com.example.nav3recipes.multiplestacks.Navigator
import com.google.samples.apps.nowinandroid.core.navigation.NiaNavKey
import com.google.samples.apps.nowinandroid.core.navigation.NiaNavigator
import com.google.samples.apps.nowinandroid.core.navigation.simple.Navigator
import com.google.samples.apps.nowinandroid.feature.interests.api.navigation.InterestsRoute
import com.google.samples.apps.nowinandroid.feature.search.api.navigation.SearchRoute
import com.google.samples.apps.nowinandroid.feature.search.impl.SearchScreen
import com.google.samples.apps.nowinandroid.feature.search.impl.navigation.searchEntry
import com.google.samples.apps.nowinandroid.feature.topic.api.navigation.TopicRoute
import dagger.Module
import dagger.Provides

@ -21,9 +21,7 @@ import androidx.compose.material3.adaptive.navigation3.ListDetailSceneStrategy
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import androidx.navigation3.runtime.EntryProviderScope
import androidx.navigation3.runtime.NavKey
import com.example.nav3recipes.multiplestacks.Navigator
import com.google.samples.apps.nowinandroid.core.navigation.NiaNavKey
import com.google.samples.apps.nowinandroid.core.navigation.NiaNavigator
import com.google.samples.apps.nowinandroid.core.navigation.simple.Navigator
import com.google.samples.apps.nowinandroid.feature.topic.api.navigation.TopicRoute
//import com.google.samples.apps.nowinandroid.feature.topic.api.navigation.navigateToTopic
import com.google.samples.apps.nowinandroid.feature.topic.impl.TopicScreen

Loading…
Cancel
Save