Skip to content

Commit f75b028

Browse files
committed
Update feature ViewModels and tests
1 parent e26b5b6 commit f75b028

File tree

85 files changed

+1222
-870
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

85 files changed

+1222
-870
lines changed

app/build.gradle.kts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,10 +103,8 @@ dependencies {
103103
implementation(libs.androidx.compose.runtime.tracing)
104104
implementation(libs.androidx.core.ktx)
105105
implementation(libs.androidx.core.splashscreen)
106-
implementation(libs.androidx.hilt.navigation.compose)
107106
implementation(libs.androidx.lifecycle.runtimeCompose)
108107
implementation(libs.androidx.lifecycle.viewModel.navigation3)
109-
implementation(libs.androidx.navigation.compose)
110108
implementation(libs.androidx.profileinstaller)
111109
implementation(libs.androidx.tracing.ktx)
112110
implementation(libs.androidx.window.core)

app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/NavigationTest.kt

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package com.google.samples.apps.nowinandroid.ui
1818

1919
import androidx.compose.ui.semantics.SemanticsActions.ScrollBy
2020
import androidx.compose.ui.test.assertCountEquals
21+
import androidx.compose.ui.test.assertIsDisplayed
2122
import androidx.compose.ui.test.assertIsOn
2223
import androidx.compose.ui.test.assertIsSelected
2324
import androidx.compose.ui.test.hasTestTag
@@ -39,11 +40,13 @@ import com.google.samples.apps.nowinandroid.core.data.repository.NewsRepository
3940
import com.google.samples.apps.nowinandroid.core.data.repository.TopicsRepository
4041
import com.google.samples.apps.nowinandroid.core.model.data.Topic
4142
import com.google.samples.apps.nowinandroid.core.rules.GrantPostNotificationsPermissionRule
43+
import com.google.samples.apps.nowinandroid.feature.interests.impl.LIST_PANE_TEST_TAG
4244
import dagger.hilt.android.testing.HiltAndroidRule
4345
import dagger.hilt.android.testing.HiltAndroidTest
4446
import kotlinx.coroutines.flow.first
4547
import kotlinx.coroutines.runBlocking
4648
import org.junit.Before
49+
import org.junit.Ignore
4750
import org.junit.Rule
4851
import org.junit.Test
4952
import javax.inject.Inject
@@ -85,10 +88,10 @@ class NavigationTest {
8588
// The strings used for matching in these tests
8689
private val navigateUp by composeTestRule.stringResource(FeatureForyouR.string.feature_foryou_api_navigate_up)
8790
private val forYou by composeTestRule.stringResource(FeatureForyouR.string.feature_foryou_api_title)
88-
private val interests by composeTestRule.stringResource(FeatureSearchR.string.feature_search_interests)
91+
private val interests by composeTestRule.stringResource(FeatureSearchR.string.feature_search_api_interests)
8992
private val sampleTopic = "Headlines"
9093
private val appName by composeTestRule.stringResource(R.string.app_name)
91-
private val saved by composeTestRule.stringResource(BookmarksR.string.feature_bookmarks_title)
94+
private val saved by composeTestRule.stringResource(BookmarksR.string.feature_bookmarks_api_title)
9295
private val settings by composeTestRule.stringResource(SettingsR.string.feature_settings_top_app_bar_action_icon_description)
9396
private val brand by composeTestRule.stringResource(SettingsR.string.feature_settings_brand_android)
9497
private val ok by composeTestRule.stringResource(SettingsR.string.feature_settings_dismiss_dialog_button_text)
@@ -252,6 +255,9 @@ class NavigationTest {
252255
}
253256
}
254257

258+
// TODO decide if backStack should preserve previous stacks when navigating back to home tab (ForYou)
259+
// https://github.com/android/nowinandroid/issues/1937
260+
@Ignore
255261
@Test
256262
fun navigationBar_multipleBackStackInterests() {
257263
composeTestRule.apply {
@@ -261,12 +267,14 @@ class NavigationTest {
261267
val topic = runBlocking {
262268
topicsRepository.getTopics().first().sortedBy(Topic::name).last()
263269
}
264-
onNodeWithTag("interests:topics").performScrollToNode(hasText(topic.name))
270+
onNodeWithTag(LIST_PANE_TEST_TAG).performScrollToNode(hasText(topic.name))
265271
onNodeWithText(topic.name).performClick()
266272

273+
// Verify the topic is still shown
274+
onNodeWithTag("topic:${topic.id}").assertIsDisplayed()
275+
267276
// Switch tab
268277
onNodeWithText(forYou).performClick()
269-
270278
// Come back to Interests
271279
onNodeWithText(interests).performClick()
272280

app/src/main/kotlin/com/google/samples/apps/nowinandroid/MainActivity.kt

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@ import com.google.samples.apps.nowinandroid.core.data.util.NetworkMonitor
4242
import com.google.samples.apps.nowinandroid.core.data.util.TimeZoneMonitor
4343
import com.google.samples.apps.nowinandroid.core.designsystem.theme.NiaTheme
4444
import com.google.samples.apps.nowinandroid.core.ui.LocalTimeZone
45-
import com.google.samples.apps.nowinandroid.core.navigation.NiaBackStack
46-
import com.google.samples.apps.nowinandroid.core.navigation.NiaBackStackKey
45+
import com.google.samples.apps.nowinandroid.core.navigation.NiaBackStackViewModel
46+
import com.google.samples.apps.nowinandroid.core.navigation.NiaNavKey
4747
import com.google.samples.apps.nowinandroid.ui.NiaApp
4848
import com.google.samples.apps.nowinandroid.ui.rememberNiaAppState
4949
import com.google.samples.apps.nowinandroid.util.isSystemInDarkTheme
@@ -77,11 +77,10 @@ class MainActivity : ComponentActivity() {
7777
lateinit var userNewsResourceRepository: UserNewsResourceRepository
7878
private val viewModel: MainActivityViewModel by viewModels()
7979

80-
@Inject
81-
lateinit var niaBackStack: NiaBackStack
80+
private val backStackViewModel: NiaBackStackViewModel by viewModels()
8281

8382
@Inject
84-
lateinit var entryProviderBuilders: Set<@JvmSuppressWildcards EntryProviderBuilder<NiaBackStackKey>.() -> Unit>
83+
lateinit var entryProviderBuilders: Set<@JvmSuppressWildcards EntryProviderBuilder<NiaNavKey>.() -> Unit>
8584

8685
override fun onCreate(savedInstanceState: Bundle?) {
8786
val splashScreen = installSplashScreen()
@@ -145,7 +144,7 @@ class MainActivity : ComponentActivity() {
145144
networkMonitor = networkMonitor,
146145
userNewsResourceRepository = userNewsResourceRepository,
147146
timeZoneMonitor = timeZoneMonitor,
148-
niaBackStack = niaBackStack,
147+
niaBackStack = backStackViewModel.niaBackStack,
149148
)
150149

151150
val currentTimeZone by appState.currentTimeZone.collectAsStateWithLifecycle()

app/src/main/kotlin/com/google/samples/apps/nowinandroid/di/BackStackProvider.kt

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,16 @@
1717
package com.google.samples.apps.nowinandroid.di
1818

1919
import com.google.samples.apps.nowinandroid.core.navigation.NiaBackStack
20+
import com.google.samples.apps.nowinandroid.core.navigation.NiaNavKey
2021
import com.google.samples.apps.nowinandroid.navigation.TopLevelDestination
2122
import dagger.Module
2223
import dagger.Provides
2324
import dagger.hilt.InstallIn
24-
import javax.inject.Singleton
2525
import dagger.hilt.components.SingletonComponent
26+
import kotlinx.serialization.modules.PolymorphicModuleBuilder
27+
import kotlinx.serialization.modules.SerializersModule
28+
import kotlinx.serialization.modules.polymorphic
29+
import javax.inject.Singleton
2630

2731
@Module
2832
@InstallIn(SingletonComponent::class)
@@ -31,4 +35,14 @@ object BackStackProvider {
3135
@Singleton
3236
fun provideNiaBackStack(): NiaBackStack =
3337
NiaBackStack(startKey = TopLevelDestination.FOR_YOU.key)
38+
39+
@Provides
40+
@Singleton
41+
fun provideSerializersModule(
42+
polymorphicModuleBuilders: Set<@JvmSuppressWildcards PolymorphicModuleBuilder<NiaNavKey>.() -> Unit>
43+
) : SerializersModule = SerializersModule {
44+
polymorphic(NiaNavKey::class) {
45+
polymorphicModuleBuilders.forEach { it() }
46+
}
47+
}
3448
}

app/src/main/kotlin/com/google/samples/apps/nowinandroid/navigation/NiaNavDisplay.kt

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,23 +19,22 @@ package com.google.samples.apps.nowinandroid.navigation
1919
import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi
2020
import androidx.compose.material3.adaptive.navigation3.rememberListDetailSceneStrategy
2121
import androidx.compose.runtime.Composable
22-
import androidx.compose.runtime.compositionLocalOf
2322
import androidx.lifecycle.viewmodel.navigation3.rememberViewModelStoreNavEntryDecorator
2423
import androidx.navigation3.runtime.EntryProviderBuilder
2524
import androidx.navigation3.runtime.entryProvider
2625
import androidx.navigation3.runtime.rememberSavedStateNavEntryDecorator
2726
import androidx.navigation3.ui.NavDisplay
2827
import androidx.navigation3.ui.rememberSceneSetupNavEntryDecorator
2928
import com.google.samples.apps.nowinandroid.core.navigation.NiaBackStack
30-
import com.google.samples.apps.nowinandroid.core.navigation.NiaBackStackKey
29+
import com.google.samples.apps.nowinandroid.core.navigation.NiaNavKey
3130

3231
@OptIn(ExperimentalMaterial3AdaptiveApi::class)
3332
@Composable
3433
fun NiaNavDisplay(
3534
niaBackStack: NiaBackStack,
36-
entryProviderBuilders: Set<@JvmSuppressWildcards EntryProviderBuilder<NiaBackStackKey>.() -> Unit>,
35+
entryProviderBuilders: Set<@JvmSuppressWildcards EntryProviderBuilder<NiaNavKey>.() -> Unit>,
3736
) {
38-
val listDetailStrategy = rememberListDetailSceneStrategy<NiaBackStackKey>()
37+
val listDetailStrategy = rememberListDetailSceneStrategy<NiaNavKey>()
3938

4039
NavDisplay(
4140
backStack = niaBackStack.backStack,

app/src/main/kotlin/com/google/samples/apps/nowinandroid/navigation/NiaNavHost.kt

Lines changed: 0 additions & 72 deletions
This file was deleted.

app/src/main/kotlin/com/google/samples/apps/nowinandroid/navigation/TopLevelDestination.kt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,12 @@ import androidx.annotation.StringRes
2020
import androidx.compose.ui.graphics.vector.ImageVector
2121
import com.google.samples.apps.nowinandroid.R
2222
import com.google.samples.apps.nowinandroid.core.designsystem.icon.NiaIcons
23-
import com.google.samples.apps.nowinandroid.core.navigation.NiaBackStackKey
23+
import com.google.samples.apps.nowinandroid.core.navigation.NiaNavKey
2424
import com.google.samples.apps.nowinandroid.feature.bookmarks.api.navigation.BookmarksRoute
2525
import com.google.samples.apps.nowinandroid.feature.foryou.api.navigation.ForYouRoute
2626
import com.google.samples.apps.nowinandroid.feature.interests.api.navigation.InterestsRoute
2727
import kotlin.reflect.KClass
28-
import com.google.samples.apps.nowinandroid.feature.bookmarks.impl.R as bookmarksR
28+
import com.google.samples.apps.nowinandroid.feature.bookmarks.api.R as bookmarksR
2929
import com.google.samples.apps.nowinandroid.feature.foryou.api.R as forYouR
3030
import com.google.samples.apps.nowinandroid.feature.search.api.R as searchR
3131

@@ -49,7 +49,7 @@ enum class TopLevelDestination(
4949
@StringRes val iconTextId: Int,
5050
@StringRes val titleTextId: Int,
5151
val route: KClass<*>,
52-
val key: NiaBackStackKey
52+
val key: NiaNavKey
5353
) {
5454
FOR_YOU(
5555
selectedIcon = NiaIcons.Upcoming,
@@ -62,8 +62,8 @@ enum class TopLevelDestination(
6262
BOOKMARKS(
6363
selectedIcon = NiaIcons.Bookmarks,
6464
unselectedIcon = NiaIcons.BookmarksBorder,
65-
iconTextId = bookmarksR.string.feature_bookmarks_impl_title,
66-
titleTextId = bookmarksR.string.feature_bookmarks_impl_title,
65+
iconTextId = bookmarksR.string.feature_bookmarks_api_title,
66+
titleTextId = bookmarksR.string.feature_bookmarks_api_title,
6767
route = BookmarksRoute::class,
6868
key = BookmarksRoute
6969
),

app/src/main/kotlin/com/google/samples/apps/nowinandroid/ui/NiaApp.kt

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,6 @@ import androidx.compose.ui.semantics.semantics
5959
import androidx.compose.ui.semantics.testTagsAsResourceId
6060
import androidx.compose.ui.unit.dp
6161
import androidx.lifecycle.compose.collectAsStateWithLifecycle
62-
import androidx.navigation.NavDestination
63-
import androidx.navigation.NavDestination.Companion.hasRoute
64-
import androidx.navigation.NavDestination.Companion.hierarchy
6562
import androidx.navigation3.runtime.EntryProviderBuilder
6663
import com.google.samples.apps.nowinandroid.R
6764
import com.google.samples.apps.nowinandroid.core.designsystem.component.NiaBackground
@@ -71,19 +68,18 @@ import com.google.samples.apps.nowinandroid.core.designsystem.component.NiaTopAp
7168
import com.google.samples.apps.nowinandroid.core.designsystem.icon.NiaIcons
7269
import com.google.samples.apps.nowinandroid.core.designsystem.theme.GradientColors
7370
import com.google.samples.apps.nowinandroid.core.designsystem.theme.LocalGradientColors
74-
import com.google.samples.apps.nowinandroid.core.navigation.NiaBackStackKey
71+
import com.google.samples.apps.nowinandroid.core.navigation.NiaNavKey
7572
import com.google.samples.apps.nowinandroid.feature.bookmarks.impl.navigation.LocalSnackbarHostState
7673
import com.google.samples.apps.nowinandroid.feature.search.api.navigation.navigateToSearch
7774
import com.google.samples.apps.nowinandroid.feature.settings.api.SettingsDialog
7875
import com.google.samples.apps.nowinandroid.navigation.NiaNavDisplay
7976
import com.google.samples.apps.nowinandroid.navigation.TopLevelDestination
80-
import kotlin.reflect.KClass
8177
import com.google.samples.apps.nowinandroid.feature.settings.api.R as settingsR
8278

8379
@Composable
8480
fun NiaApp(
8581
appState: NiaAppState,
86-
entryProviderBuilders: Set<@JvmSuppressWildcards EntryProviderBuilder<NiaBackStackKey>.() -> Unit>,
82+
entryProviderBuilders: Set<@JvmSuppressWildcards EntryProviderBuilder<NiaNavKey>.() -> Unit>,
8783
modifier: Modifier = Modifier,
8884
windowAdaptiveInfo: WindowAdaptiveInfo = currentWindowAdaptiveInfo(),
8985
) {
@@ -134,7 +130,7 @@ fun NiaApp(
134130
)
135131
internal fun NiaApp(
136132
appState: NiaAppState,
137-
entryProviderBuilders: Set<@JvmSuppressWildcards EntryProviderBuilder<NiaBackStackKey>.() -> Unit>,
133+
entryProviderBuilders: Set<@JvmSuppressWildcards EntryProviderBuilder<NiaNavKey>.() -> Unit>,
138134
showSettingsDialog: Boolean,
139135
onSettingsDismissed: () -> Unit,
140136
onTopAppBarActionClick: () -> Unit,
@@ -145,7 +141,6 @@ internal fun NiaApp(
145141
.collectAsStateWithLifecycle()
146142
val currentTopLevelKey = appState.currentTopLevelDestination!!.key
147143

148-
149144
if (showSettingsDialog) {
150145
SettingsDialog(
151146
onDismiss = { onSettingsDismissed() },
@@ -161,7 +156,7 @@ internal fun NiaApp(
161156
val selected = destination.key == currentTopLevelKey
162157
item(
163158
selected = selected,
164-
onClick = { appState.navigateToTopLevelDestination(destination) },
159+
onClick = { appState.niaBackStack.navigate(destination.key) },
165160
icon = {
166161
Icon(
167162
imageVector = destination.unselectedIcon,
@@ -246,10 +241,6 @@ internal fun NiaApp(
246241
},
247242
),
248243
) {
249-
// NiaNavHost(
250-
// appState = appState,
251-
// onShowSnackbar = onShowSnackbar,
252-
// )
253244
NiaNavDisplay(
254245
niaBackStack = appState.niaBackStack,
255246
entryProviderBuilders,
@@ -280,9 +271,4 @@ private fun Modifier.notificationDot(): Modifier =
280271
),
281272
)
282273
}
283-
}
284-
285-
private fun NavDestination?.isRouteInHierarchy(route: KClass<*>) =
286-
this?.hierarchy?.any {
287-
it.hasRoute(route)
288-
} ?: false
274+
}

0 commit comments

Comments
 (0)