Skip to content

Commit e26b5b6

Browse files
committed
Refactor Interests to ListDetailScene
1 parent 4fbb423 commit e26b5b6

File tree

42 files changed

+173
-132
lines changed

Some content is hidden

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

42 files changed

+173
-132
lines changed

app/build.gradle.kts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,24 +88,24 @@ dependencies {
8888
implementation(projects.core.designsystem)
8989
implementation(projects.core.data)
9090
implementation(projects.core.model)
91-
implementation(projects.core.navigation)
9291
implementation(projects.core.analytics)
9392
implementation(projects.core.navigation)
9493
implementation(projects.sync.work)
9594

9695
implementation(libs.androidx.activity.compose)
9796
implementation(libs.androidx.compose.material3)
98-
implementation(libs.androidx.navigation3.runtime)
9997
implementation(libs.androidx.navigation3.ui)
10098
implementation(libs.androidx.compose.material3.adaptive)
10199
implementation(libs.androidx.compose.material3.adaptive.layout)
102100
implementation(libs.androidx.compose.material3.adaptive.navigation)
101+
implementation(libs.androidx.compose.material3.adaptive.navigation3)
103102
implementation(libs.androidx.compose.material3.windowSizeClass)
104103
implementation(libs.androidx.compose.runtime.tracing)
105104
implementation(libs.androidx.core.ktx)
106105
implementation(libs.androidx.core.splashscreen)
107106
implementation(libs.androidx.hilt.navigation.compose)
108107
implementation(libs.androidx.lifecycle.runtimeCompose)
108+
implementation(libs.androidx.lifecycle.viewModel.navigation3)
109109
implementation(libs.androidx.navigation.compose)
110110
implementation(libs.androidx.profileinstaller)
111111
implementation(libs.androidx.tracing.ktx)

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ 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
4545
import com.google.samples.apps.nowinandroid.core.navigation.NiaBackStack
46+
import com.google.samples.apps.nowinandroid.core.navigation.NiaBackStackKey
4647
import com.google.samples.apps.nowinandroid.ui.NiaApp
4748
import com.google.samples.apps.nowinandroid.ui.rememberNiaAppState
4849
import com.google.samples.apps.nowinandroid.util.isSystemInDarkTheme
@@ -80,7 +81,7 @@ class MainActivity : ComponentActivity() {
8081
lateinit var niaBackStack: NiaBackStack
8182

8283
@Inject
83-
lateinit var entryProviderBuilders: Set<@JvmSuppressWildcards EntryProviderBuilder<Any>.() -> Unit>
84+
lateinit var entryProviderBuilders: Set<@JvmSuppressWildcards EntryProviderBuilder<NiaBackStackKey>.() -> Unit>
8485

8586
override fun onCreate(savedInstanceState: Bundle?) {
8687
val splashScreen = installSplashScreen()

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import dagger.hilt.components.SingletonComponent
2626

2727
@Module
2828
@InstallIn(SingletonComponent::class)
29-
object NiaAppNavigation {
29+
object BackStackProvider {
3030
@Provides
3131
@Singleton
3232
fun provideNiaBackStack(): NiaBackStack =

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

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,23 +16,36 @@
1616

1717
package com.google.samples.apps.nowinandroid.navigation
1818

19+
import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi
20+
import androidx.compose.material3.adaptive.navigation3.rememberListDetailSceneStrategy
1921
import androidx.compose.runtime.Composable
2022
import androidx.compose.runtime.compositionLocalOf
21-
import androidx.compose.runtime.snapshots.SnapshotStateList
23+
import androidx.lifecycle.viewmodel.navigation3.rememberViewModelStoreNavEntryDecorator
2224
import androidx.navigation3.runtime.EntryProviderBuilder
23-
import androidx.navigation3.runtime.NavEntryDecorator
2425
import androidx.navigation3.runtime.entryProvider
26+
import androidx.navigation3.runtime.rememberSavedStateNavEntryDecorator
2527
import androidx.navigation3.ui.NavDisplay
28+
import androidx.navigation3.ui.rememberSceneSetupNavEntryDecorator
2629
import com.google.samples.apps.nowinandroid.core.navigation.NiaBackStack
30+
import com.google.samples.apps.nowinandroid.core.navigation.NiaBackStackKey
2731

32+
@OptIn(ExperimentalMaterial3AdaptiveApi::class)
2833
@Composable
2934
fun NiaNavDisplay(
3035
niaBackStack: NiaBackStack,
31-
entryProviderBuilders: Set<@JvmSuppressWildcards EntryProviderBuilder<Any>.() -> Unit>,
36+
entryProviderBuilders: Set<@JvmSuppressWildcards EntryProviderBuilder<NiaBackStackKey>.() -> Unit>,
3237
) {
38+
val listDetailStrategy = rememberListDetailSceneStrategy<NiaBackStackKey>()
39+
3340
NavDisplay(
3441
backStack = niaBackStack.backStack,
42+
sceneStrategy = listDetailStrategy,
3543
onBack = { niaBackStack.removeLast() },
44+
entryDecorators = listOf(
45+
rememberSceneSetupNavEntryDecorator(),
46+
rememberSavedStateNavEntryDecorator(),
47+
rememberViewModelStoreNavEntryDecorator(),
48+
),
3649
entryProvider = entryProvider {
3750
entryProviderBuilders.forEach { builder ->
3851
builder()

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import androidx.compose.runtime.Composable
2020
import androidx.compose.ui.Modifier
2121
import androidx.navigation.compose.NavHost
2222
import com.google.samples.apps.nowinandroid.feature.bookmarks.api.navigation.bookmarksScreen
23-
import com.google.samples.apps.nowinandroid.feature.foryou.api.navigation.ForYouBaseRoute
23+
import com.google.samples.apps.nowinandroid.feature.foryou.api.navigation.ForYouRoute
2424
import com.google.samples.apps.nowinandroid.feature.foryou.api.navigation.forYouSection
2525
import com.google.samples.apps.nowinandroid.feature.interests.api.navigation.navigateToInterests
2626
import com.google.samples.apps.nowinandroid.feature.search.api.navigation.searchScreen
@@ -46,7 +46,7 @@ fun NiaNavHost(
4646
val navController = appState.navController
4747
NavHost(
4848
navController = navController,
49-
startDestination = ForYouBaseRoute,
49+
startDestination = ForYouRoute,
5050
modifier = modifier,
5151
) {
5252
forYouSection(

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,8 +20,8 @@ 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
2324
import com.google.samples.apps.nowinandroid.feature.bookmarks.api.navigation.BookmarksRoute
24-
import com.google.samples.apps.nowinandroid.feature.foryou.api.navigation.ForYouBaseRoute
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
@@ -49,17 +49,15 @@ enum class TopLevelDestination(
4949
@StringRes val iconTextId: Int,
5050
@StringRes val titleTextId: Int,
5151
val route: KClass<*>,
52-
val baseRoute: KClass<*> = route,
53-
val key: Any
52+
val key: NiaBackStackKey
5453
) {
5554
FOR_YOU(
5655
selectedIcon = NiaIcons.Upcoming,
5756
unselectedIcon = NiaIcons.UpcomingBorder,
5857
iconTextId = forYouR.string.feature_foryou_api_title,
5958
titleTextId = R.string.app_name,
6059
route = ForYouRoute::class,
61-
baseRoute = ForYouBaseRoute::class,
62-
key = ForYouBaseRoute
60+
key = ForYouRoute
6361
),
6462
BOOKMARKS(
6563
selectedIcon = NiaIcons.Bookmarks,
@@ -78,3 +76,5 @@ enum class TopLevelDestination(
7876
key = InterestsRoute(null)
7977
),
8078
}
79+
80+
internal val TopLevelDestinations = TopLevelDestination.entries.associateBy { dest -> dest.key }

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

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,9 @@ import com.google.samples.apps.nowinandroid.core.designsystem.component.NiaTopAp
7171
import com.google.samples.apps.nowinandroid.core.designsystem.icon.NiaIcons
7272
import com.google.samples.apps.nowinandroid.core.designsystem.theme.GradientColors
7373
import com.google.samples.apps.nowinandroid.core.designsystem.theme.LocalGradientColors
74+
import com.google.samples.apps.nowinandroid.core.navigation.NiaBackStackKey
7475
import com.google.samples.apps.nowinandroid.feature.bookmarks.impl.navigation.LocalSnackbarHostState
76+
import com.google.samples.apps.nowinandroid.feature.search.api.navigation.navigateToSearch
7577
import com.google.samples.apps.nowinandroid.feature.settings.api.SettingsDialog
7678
import com.google.samples.apps.nowinandroid.navigation.NiaNavDisplay
7779
import com.google.samples.apps.nowinandroid.navigation.TopLevelDestination
@@ -81,7 +83,7 @@ import com.google.samples.apps.nowinandroid.feature.settings.api.R as settingsR
8183
@Composable
8284
fun NiaApp(
8385
appState: NiaAppState,
84-
entryProviderBuilders: Set<@JvmSuppressWildcards EntryProviderBuilder<Any>.() -> Unit>,
86+
entryProviderBuilders: Set<@JvmSuppressWildcards EntryProviderBuilder<NiaBackStackKey>.() -> Unit>,
8587
modifier: Modifier = Modifier,
8688
windowAdaptiveInfo: WindowAdaptiveInfo = currentWindowAdaptiveInfo(),
8789
) {
@@ -132,7 +134,7 @@ fun NiaApp(
132134
)
133135
internal fun NiaApp(
134136
appState: NiaAppState,
135-
entryProviderBuilders: Set<@JvmSuppressWildcards EntryProviderBuilder<Any>.() -> Unit>,
137+
entryProviderBuilders: Set<@JvmSuppressWildcards EntryProviderBuilder<NiaBackStackKey>.() -> Unit>,
136138
showSettingsDialog: Boolean,
137139
onSettingsDismissed: () -> Unit,
138140
onTopAppBarActionClick: () -> Unit,
@@ -141,7 +143,7 @@ internal fun NiaApp(
141143
) {
142144
val unreadDestinations by appState.topLevelDestinationsWithUnreadResources
143145
.collectAsStateWithLifecycle()
144-
val currentTopLevelKey = appState.currentTopLevelDestination
146+
val currentTopLevelKey = appState.currentTopLevelDestination!!.key
145147

146148

147149
if (showSettingsDialog) {
@@ -156,10 +158,7 @@ internal fun NiaApp(
156158
navigationSuiteItems = {
157159
appState.topLevelDestinations.forEach { destination ->
158160
val hasUnread = unreadDestinations.contains(destination)
159-
// val selected = currentDestination
160-
// .isRouteInHierarchy(destination.baseRoute)
161161
val selected = destination.key == currentTopLevelKey
162-
println("cfok destination:$destination, currentDest:$currentTopLevelKey")
163162
item(
164163
selected = selected,
165164
onClick = { appState.navigateToTopLevelDestination(destination) },
@@ -233,7 +232,7 @@ internal fun NiaApp(
233232
containerColor = Color.Transparent,
234233
),
235234
onActionClick = { onTopAppBarActionClick() },
236-
onNavigationClick = { appState.navigateToSearchNav3() },
235+
onNavigationClick = { appState.niaBackStack.navigateToSearch() },
237236
)
238237
}
239238

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

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import com.google.samples.apps.nowinandroid.navigation.TopLevelDestination
3535
import com.google.samples.apps.nowinandroid.navigation.TopLevelDestination.BOOKMARKS
3636
import com.google.samples.apps.nowinandroid.navigation.TopLevelDestination.FOR_YOU
3737
import com.google.samples.apps.nowinandroid.navigation.TopLevelDestination.INTERESTS
38+
import com.google.samples.apps.nowinandroid.navigation.TopLevelDestinations
3839
import kotlinx.coroutines.CoroutineScope
3940
import kotlinx.coroutines.flow.SharingStarted
4041
import kotlinx.coroutines.flow.StateFlow
@@ -98,12 +99,7 @@ class NiaAppState(
9899
// }
99100

100101
val currentTopLevelDestination: TopLevelDestination?
101-
@Composable get() {
102-
return TopLevelDestination.entries.firstOrNull { topLevelDestination ->
103-
topLevelDestination.key == niaBackStack.currentTopLevelKey
104-
// currentDestination?.hasRoute(route = topLevelDestination.route) == true
105-
}
106-
}
102+
@Composable get() = TopLevelDestinations[niaBackStack.currentTopLevelKey]
107103

108104
val isOffline = networkMonitor.isOnline
109105
.map(Boolean::not)
@@ -178,9 +174,6 @@ class NiaAppState(
178174
}
179175

180176
fun navigateToSearch() = navController.navigateToSearch()
181-
fun navigateToSearchNav3() = niaBackStack.navigateToSearch(
182-
onInterestsClick = { navigateToTopLevelDestination(INTERESTS) }
183-
)
184177
}
185178

186179
/**

core/navigation/build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@ plugins {
44
}
55

66
dependencies {
7-
implementation(libs.androidx.navigation3.runtime)
7+
api(libs.androidx.navigation3.runtime)
88
}

core/navigation/src/main/kotlin/com/google/samples/apps/nowinandroid/core/navigation/NiaBackStack.kt

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616

1717
package com.google.samples.apps.nowinandroid.core.navigation
1818

19-
import androidx.compose.runtime.Composable
2019
import androidx.compose.runtime.getValue
2120
import androidx.compose.runtime.mutableStateListOf
2221
import androidx.compose.runtime.mutableStateOf
@@ -26,29 +25,29 @@ import javax.inject.Inject
2625
import kotlin.collections.remove
2726

2827
class NiaBackStack @Inject constructor(
29-
startKey: Any,
28+
startKey: NiaBackStackKey,
3029
) {
3130
val backStack = mutableStateListOf(startKey)
3231

3332
// Maintain a stack for each top level route
34-
private var topLevelStacks : LinkedHashMap<Any, SnapshotStateList<Any>> = linkedMapOf(
33+
private var topLevelStacks : LinkedHashMap<NiaBackStackKey, SnapshotStateList<NiaBackStackKey>> = linkedMapOf(
3534
startKey to mutableStateListOf(startKey)
3635
)
3736

3837
// Expose the current top level route for consumers
3938
var currentTopLevelKey by mutableStateOf(startKey)
4039
private set
4140

42-
internal val currentKey: Any
43-
@Composable get() = topLevelStacks[currentTopLevelKey]!!.last()
41+
internal val currentKey: NiaBackStackKey
42+
get() = topLevelStacks[currentTopLevelKey]!!.last()
4443

4544
private fun updateBackStack() =
4645
backStack.apply {
4746
clear()
4847
addAll(topLevelStacks.flatMap { it.value })
4948
}
5049

51-
fun navigateToTopLevelDestination(key: Any){
50+
fun navigateToTopLevelDestination(key: NiaBackStackKey){
5251
// If the top level doesn't exist, add it
5352
if (topLevelStacks[key] == null){
5453
topLevelStacks.put(key, mutableStateListOf(key))
@@ -60,14 +59,16 @@ class NiaBackStack @Inject constructor(
6059
}
6160
}
6261
}
62+
6363
currentTopLevelKey = key
6464
updateBackStack()
6565
}
6666

67-
fun navigate(key: Any){
68-
println("cfok navigate $key")
69-
topLevelStacks[currentTopLevelKey]?.add(key)
70-
updateBackStack()
67+
fun navigate(key: NiaBackStackKey){
68+
if (backStack.lastOrNull() != key) {
69+
topLevelStacks[currentTopLevelKey]?.add(key)
70+
updateBackStack()
71+
}
7172
}
7273

7374
fun removeLast(){
@@ -77,5 +78,6 @@ class NiaBackStack @Inject constructor(
7778
currentTopLevelKey = topLevelStacks.keys.last()
7879
updateBackStack()
7980
}
81+
}
8082

81-
}
83+
interface NiaBackStackKey

0 commit comments

Comments
 (0)