Implement settings feature as a Nav3 dialog screen

This makes the `:feature:settings` behave like any other feature with api/impl split.
pull/2043/head
Simon Marquis 8 months ago
parent ade8065442
commit 5dbbffb958

@ -13,10 +13,6 @@ config:
graph TB graph TB
subgraph :feature subgraph :feature
direction TB direction TB
subgraph :feature:settings
direction TB
:feature:settings:impl[impl]:::android-library
end
subgraph :feature:foryou subgraph :feature:foryou
direction TB direction TB
:feature:foryou:api[api]:::android-library :feature:foryou:api[api]:::android-library
@ -32,6 +28,11 @@ graph TB
:feature:search:api[api]:::android-library :feature:search:api[api]:::android-library
:feature:search:impl[impl]:::android-library :feature:search:impl[impl]:::android-library
end end
subgraph :feature:settings
direction TB
:feature:settings:api[api]:::android-library
:feature:settings:impl[impl]:::android-library
end
subgraph :feature:interests subgraph :feature:interests
direction TB direction TB
:feature:interests:api[api]:::android-library :feature:interests:api[api]:::android-library
@ -81,6 +82,7 @@ graph TB
:app -.-> :feature:interests:impl :app -.-> :feature:interests:impl
:app -.-> :feature:search:api :app -.-> :feature:search:api
:app -.-> :feature:search:impl :app -.-> :feature:search:impl
:app -.-> :feature:settings:api
:app -.-> :feature:settings:impl :app -.-> :feature:settings:impl
:app -.-> :feature:topic:api :app -.-> :feature:topic:api
:app -.-> :feature:topic:impl :app -.-> :feature:topic:impl
@ -128,13 +130,16 @@ graph TB
:feature:search:api --> :core:navigation :feature:search:api --> :core:navigation
:feature:search:impl -.-> :core:designsystem :feature:search:impl -.-> :core:designsystem
:feature:search:impl -.-> :core:domain :feature:search:impl -.-> :core:domain
:feature:search:impl -.-> :core:navigation
:feature:search:impl -.-> :core:ui :feature:search:impl -.-> :core:ui
:feature:search:impl -.-> :feature:interests:api :feature:search:impl -.-> :feature:interests:api
:feature:search:impl -.-> :feature:search:api :feature:search:impl -.-> :feature:search:api
:feature:search:impl -.-> :feature:topic:api :feature:search:impl -.-> :feature:topic:api
:feature:settings:api --> :core:navigation
:feature:settings:impl -.-> :core:data :feature:settings:impl -.-> :core:data
:feature:settings:impl -.-> :core:designsystem :feature:settings:impl -.-> :core:designsystem
:feature:settings:impl -.-> :core:ui :feature:settings:impl -.-> :core:ui
:feature:settings:impl -.-> :feature:settings:api
:feature:topic:api -.-> :core:designsystem :feature:topic:api -.-> :core:designsystem
:feature:topic:api --> :core:navigation :feature:topic:api --> :core:navigation
:feature:topic:api -.-> :core:ui :feature:topic:api -.-> :core:ui

@ -78,6 +78,7 @@ dependencies {
implementation(projects.feature.topic.impl) implementation(projects.feature.topic.impl)
implementation(projects.feature.search.api) implementation(projects.feature.search.api)
implementation(projects.feature.search.impl) implementation(projects.feature.search.impl)
implementation(projects.feature.settings.api)
implementation(projects.feature.settings.impl) implementation(projects.feature.settings.impl)
implementation(projects.core.common) implementation(projects.core.common)

@ -45,10 +45,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.composed import androidx.compose.ui.composed
@ -63,6 +60,7 @@ import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.navigation3.runtime.NavKey import androidx.navigation3.runtime.NavKey
import androidx.navigation3.runtime.entryProvider import androidx.navigation3.runtime.entryProvider
import androidx.navigation3.scene.DialogSceneStrategy
import androidx.navigation3.ui.NavDisplay import androidx.navigation3.ui.NavDisplay
import com.google.samples.apps.nowinandroid.R 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.NiaBackground
@ -81,7 +79,8 @@ import com.google.samples.apps.nowinandroid.feature.foryou.impl.navigation.forYo
import com.google.samples.apps.nowinandroid.feature.interests.impl.navigation.interestsEntry import com.google.samples.apps.nowinandroid.feature.interests.impl.navigation.interestsEntry
import com.google.samples.apps.nowinandroid.feature.search.api.navigation.SearchNavKey import com.google.samples.apps.nowinandroid.feature.search.api.navigation.SearchNavKey
import com.google.samples.apps.nowinandroid.feature.search.impl.navigation.searchEntry import com.google.samples.apps.nowinandroid.feature.search.impl.navigation.searchEntry
import com.google.samples.apps.nowinandroid.feature.settings.impl.SettingsDialog import com.google.samples.apps.nowinandroid.feature.settings.api.navigation.SettingsNavKey
import com.google.samples.apps.nowinandroid.feature.settings.impl.navigation.settingsEntry
import com.google.samples.apps.nowinandroid.feature.topic.impl.navigation.topicEntry import com.google.samples.apps.nowinandroid.feature.topic.impl.navigation.topicEntry
import com.google.samples.apps.nowinandroid.navigation.TOP_LEVEL_NAV_ITEMS import com.google.samples.apps.nowinandroid.navigation.TOP_LEVEL_NAV_ITEMS
import com.google.samples.apps.nowinandroid.feature.settings.impl.R as settingsR import com.google.samples.apps.nowinandroid.feature.settings.impl.R as settingsR
@ -93,7 +92,6 @@ fun NiaApp(
windowAdaptiveInfo: WindowAdaptiveInfo = currentWindowAdaptiveInfo(), windowAdaptiveInfo: WindowAdaptiveInfo = currentWindowAdaptiveInfo(),
) { ) {
val shouldShowGradientBackground = appState.navigationState.currentTopLevelKey == ForYouNavKey val shouldShowGradientBackground = appState.navigationState.currentTopLevelKey == ForYouNavKey
var showSettingsDialog by rememberSaveable { mutableStateOf(false) }
NiaBackground(modifier = modifier) { NiaBackground(modifier = modifier) {
NiaGradientBackground( NiaGradientBackground(
@ -118,13 +116,8 @@ fun NiaApp(
} }
} }
CompositionLocalProvider(LocalSnackbarHostState provides snackbarHostState) { CompositionLocalProvider(LocalSnackbarHostState provides snackbarHostState) {
NiaApp( NiaAppContent(
appState = appState, appState = appState,
// TODO: Settings should be a dialog screen
showSettingsDialog = showSettingsDialog,
onSettingsDismissed = { showSettingsDialog = false },
onTopAppBarActionClick = { showSettingsDialog = true },
windowAdaptiveInfo = windowAdaptiveInfo, windowAdaptiveInfo = windowAdaptiveInfo,
) )
} }
@ -138,23 +131,14 @@ fun NiaApp(
ExperimentalComposeUiApi::class, ExperimentalComposeUiApi::class,
ExperimentalMaterial3AdaptiveApi::class, ExperimentalMaterial3AdaptiveApi::class,
) )
internal fun NiaApp( internal fun NiaAppContent(
appState: NiaAppState, appState: NiaAppState,
showSettingsDialog: Boolean,
onSettingsDismissed: () -> Unit,
onTopAppBarActionClick: () -> Unit,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
windowAdaptiveInfo: WindowAdaptiveInfo = currentWindowAdaptiveInfo(), windowAdaptiveInfo: WindowAdaptiveInfo = currentWindowAdaptiveInfo(),
) { ) {
val unreadNavKeys by appState.topLevelNavKeysWithUnreadResources val unreadNavKeys by appState.topLevelNavKeysWithUnreadResources
.collectAsStateWithLifecycle() .collectAsStateWithLifecycle()
if (showSettingsDialog) {
SettingsDialog(
onDismiss = { onSettingsDismissed() },
)
}
val snackbarHostState = LocalSnackbarHostState.current val snackbarHostState = LocalSnackbarHostState.current
val navigator = remember { Navigator(appState.navigationState) } val navigator = remember { Navigator(appState.navigationState) }
@ -220,7 +204,7 @@ internal fun NiaApp(
// Only show the top app bar on top level destinations. // Only show the top app bar on top level destinations.
var shouldShowTopAppBar = false var shouldShowTopAppBar = false
if (appState.navigationState.currentKey in appState.navigationState.topLevelKeys) { if (appState.navigationState.currentKeyIgnoringDialogs in appState.navigationState.topLevelKeys) {
shouldShowTopAppBar = true shouldShowTopAppBar = true
val destination = TOP_LEVEL_NAV_ITEMS[appState.navigationState.currentTopLevelKey] val destination = TOP_LEVEL_NAV_ITEMS[appState.navigationState.currentTopLevelKey]
@ -239,7 +223,7 @@ internal fun NiaApp(
colors = TopAppBarDefaults.topAppBarColors( colors = TopAppBarDefaults.topAppBarColors(
containerColor = Color.Transparent, containerColor = Color.Transparent,
), ),
onActionClick = { onTopAppBarActionClick() }, onActionClick = { navigator.navigate(SettingsNavKey) },
onNavigationClick = { navigator.navigate(SearchNavKey) }, onNavigationClick = { navigator.navigate(SearchNavKey) },
) )
} }
@ -255,6 +239,7 @@ internal fun NiaApp(
), ),
) { ) {
val listDetailStrategy = rememberListDetailSceneStrategy<NavKey>() val listDetailStrategy = rememberListDetailSceneStrategy<NavKey>()
val dialogStrategy = remember { DialogSceneStrategy<NavKey>() }
val entryProvider = entryProvider { val entryProvider = entryProvider {
forYouEntry(navigator) forYouEntry(navigator)
@ -262,11 +247,12 @@ internal fun NiaApp(
interestsEntry(navigator) interestsEntry(navigator)
topicEntry(navigator) topicEntry(navigator)
searchEntry(navigator) searchEntry(navigator)
settingsEntry(navigator)
} }
NavDisplay( NavDisplay(
entries = appState.navigationState.toEntries(entryProvider), entries = appState.navigationState.toEntries(entryProvider),
sceneStrategy = listDetailStrategy, sceneStrategy = dialogStrategy then listDetailStrategy,
onBack = { navigator.goBack() }, onBack = { navigator.goBack() },
) )
} }

@ -251,11 +251,8 @@ class SnackbarInsetsScreenshotTests {
userNewsResourceRepository = userNewsResourceRepository, userNewsResourceRepository = userNewsResourceRepository,
timeZoneMonitor = timeZoneMonitor, timeZoneMonitor = timeZoneMonitor,
) )
NiaApp( NiaAppContent(
appState = appState, appState = appState,
showSettingsDialog = false,
onSettingsDismissed = {},
onTopAppBarActionClick = {},
windowAdaptiveInfo = WindowAdaptiveInfo( windowAdaptiveInfo = WindowAdaptiveInfo(
windowSizeClass = WindowSizeClass.compute( windowSizeClass = WindowSizeClass.compute(
maxWidth.value, maxWidth.value,

@ -201,11 +201,8 @@ class SnackbarScreenshotTests {
userNewsResourceRepository = userNewsResourceRepository, userNewsResourceRepository = userNewsResourceRepository,
timeZoneMonitor = timeZoneMonitor, timeZoneMonitor = timeZoneMonitor,
) )
NiaApp( NiaAppContent(
appState = appState, appState = appState,
showSettingsDialog = false,
onSettingsDismissed = {},
onTopAppBarActionClick = {},
windowAdaptiveInfo = WindowAdaptiveInfo( windowAdaptiveInfo = WindowAdaptiveInfo(
windowSizeClass = WindowSizeClass.compute( windowSizeClass = WindowSizeClass.compute(
maxWidth.value, maxWidth.value,

@ -13,10 +13,6 @@ config:
graph TB graph TB
subgraph :feature subgraph :feature
direction TB direction TB
subgraph :feature:settings
direction TB
:feature:settings:impl[impl]:::android-library
end
subgraph :feature:foryou subgraph :feature:foryou
direction TB direction TB
:feature:foryou:api[api]:::android-library :feature:foryou:api[api]:::android-library
@ -32,6 +28,11 @@ graph TB
:feature:search:api[api]:::android-library :feature:search:api[api]:::android-library
:feature:search:impl[impl]:::android-library :feature:search:impl[impl]:::android-library
end end
subgraph :feature:settings
direction TB
:feature:settings:api[api]:::android-library
:feature:settings:impl[impl]:::android-library
end
subgraph :feature:interests subgraph :feature:interests
direction TB direction TB
:feature:interests:api[api]:::android-library :feature:interests:api[api]:::android-library
@ -81,6 +82,7 @@ graph TB
:app -.-> :feature:interests:impl :app -.-> :feature:interests:impl
:app -.-> :feature:search:api :app -.-> :feature:search:api
:app -.-> :feature:search:impl :app -.-> :feature:search:impl
:app -.-> :feature:settings:api
:app -.-> :feature:settings:impl :app -.-> :feature:settings:impl
:app -.-> :feature:topic:api :app -.-> :feature:topic:api
:app -.-> :feature:topic:impl :app -.-> :feature:topic:impl
@ -128,13 +130,16 @@ graph TB
:feature:search:api --> :core:navigation :feature:search:api --> :core:navigation
:feature:search:impl -.-> :core:designsystem :feature:search:impl -.-> :core:designsystem
:feature:search:impl -.-> :core:domain :feature:search:impl -.-> :core:domain
:feature:search:impl -.-> :core:navigation
:feature:search:impl -.-> :core:ui :feature:search:impl -.-> :core:ui
:feature:search:impl -.-> :feature:interests:api :feature:search:impl -.-> :feature:interests:api
:feature:search:impl -.-> :feature:search:api :feature:search:impl -.-> :feature:search:api
:feature:search:impl -.-> :feature:topic:api :feature:search:impl -.-> :feature:topic:api
:feature:settings:api --> :core:navigation
:feature:settings:impl -.-> :core:data :feature:settings:impl -.-> :core:data
:feature:settings:impl -.-> :core:designsystem :feature:settings:impl -.-> :core:designsystem
:feature:settings:impl -.-> :core:ui :feature:settings:impl -.-> :core:ui
:feature:settings:impl -.-> :feature:settings:api
:feature:topic:api -.-> :core:designsystem :feature:topic:api -.-> :core:designsystem
:feature:topic:api --> :core:navigation :feature:topic:api --> :core:navigation
:feature:topic:api -.-> :core:ui :feature:topic:api -.-> :core:ui

@ -0,0 +1,24 @@
/*
* Copyright 2026 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.google.samples.apps.nowinandroid.core.navigation
import androidx.navigation3.runtime.NavKey
/**
* [NavKey] that must behave as a dialog when handled by a [DialogSceneStrategy].
*/
interface DialogNavKey : NavKey

@ -75,6 +75,11 @@ class NavigationState(
@get:VisibleForTesting @get:VisibleForTesting
val currentKey: NavKey by derivedStateOf { currentSubStack.last() } val currentKey: NavKey by derivedStateOf { currentSubStack.last() }
/**
* Current [NavKey] but ignores [DialogNavKey]s that could be added on top.
*/
val currentKeyIgnoringDialogs: NavKey by derivedStateOf { currentSubStack.last { it !is DialogNavKey } }
} }
/** /**

@ -68,6 +68,7 @@ graph TB
:feature:search:api --> :core:navigation :feature:search:api --> :core:navigation
:feature:search:impl -.-> :core:designsystem :feature:search:impl -.-> :core:designsystem
:feature:search:impl -.-> :core:domain :feature:search:impl -.-> :core:domain
:feature:search:impl -.-> :core:navigation
:feature:search:impl -.-> :core:ui :feature:search:impl -.-> :core:ui
:feature:search:impl -.-> :feature:interests:api :feature:search:impl -.-> :feature:interests:api
:feature:search:impl -.-> :feature:search:api :feature:search:impl -.-> :feature:search:api

@ -26,6 +26,7 @@ android {
dependencies { dependencies {
implementation(projects.core.domain) implementation(projects.core.domain)
implementation(projects.core.navigation)
implementation(projects.feature.interests.api) implementation(projects.feature.interests.api)
implementation(projects.feature.search.api) implementation(projects.feature.search.api)
implementation(projects.feature.topic.api) implementation(projects.feature.topic.api)

@ -0,0 +1,57 @@
# `:feature:settings:api`
## Module dependency graph
<!--region graph-->
```mermaid
---
config:
layout: elk
elk:
nodePlacementStrategy: SIMPLE
---
graph TB
subgraph :feature
direction TB
subgraph :feature:settings
direction TB
:feature:settings:api[api]:::android-library
end
end
subgraph :core
direction TB
:core:navigation[navigation]:::android-library
end
:feature:settings:api --> :core:navigation
classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000;
classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000;
classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000;
classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000;
classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000;
classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000;
```
<details><summary>📋 Graph legend</summary>
```mermaid
graph TB
application[application]:::android-application
feature[feature]:::android-feature
library[library]:::android-library
jvm[jvm]:::jvm-library
application -.-> feature
library --> jvm
classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000;
classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000;
classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000;
classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000;
classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000;
classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000;
```
</details>
<!--endregion-->

@ -0,0 +1,23 @@
/*
* Copyright 2026 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.
*/
plugins {
alias(libs.plugins.nowinandroid.android.feature.api)
}
android {
namespace = "com.google.samples.apps.nowinandroid.feature.settings.api"
}

@ -0,0 +1,23 @@
/*
* Copyright 2026 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.google.samples.apps.nowinandroid.feature.settings.api.navigation
import com.google.samples.apps.nowinandroid.core.navigation.DialogNavKey
import kotlinx.serialization.Serializable
@Serializable
object SettingsNavKey : DialogNavKey

@ -15,6 +15,7 @@ graph TB
direction TB direction TB
subgraph :feature:settings subgraph :feature:settings
direction TB direction TB
:feature:settings:api[api]:::android-library
:feature:settings:impl[impl]:::android-library :feature:settings:impl[impl]:::android-library
end end
end end
@ -28,6 +29,7 @@ graph TB
:core:datastore-proto[datastore-proto]:::android-library :core:datastore-proto[datastore-proto]:::android-library
:core:designsystem[designsystem]:::android-library :core:designsystem[designsystem]:::android-library
:core:model[model]:::jvm-library :core:model[model]:::jvm-library
:core:navigation[navigation]:::android-library
:core:network[network]:::android-library :core:network[network]:::android-library
:core:notifications[notifications]:::android-library :core:notifications[notifications]:::android-library
:core:ui[ui]:::android-library :core:ui[ui]:::android-library
@ -50,9 +52,11 @@ graph TB
:core:ui --> :core:analytics :core:ui --> :core:analytics
:core:ui --> :core:designsystem :core:ui --> :core:designsystem
:core:ui --> :core:model :core:ui --> :core:model
:feature:settings:api --> :core:navigation
:feature:settings:impl -.-> :core:data :feature:settings:impl -.-> :core:data
:feature:settings:impl -.-> :core:designsystem :feature:settings:impl -.-> :core:designsystem
:feature:settings:impl -.-> :core:ui :feature:settings:impl -.-> :core:ui
:feature:settings:impl -.-> :feature:settings:api
classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000;
classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000;

@ -26,8 +26,10 @@ android {
dependencies { dependencies {
implementation(libs.androidx.appcompat) implementation(libs.androidx.appcompat)
implementation(libs.androidx.navigation3.ui)
implementation(libs.google.oss.licenses) implementation(libs.google.oss.licenses)
implementation(projects.core.data) implementation(projects.core.data)
implementation(projects.feature.settings.api)
testImplementation(projects.core.testing) testImplementation(projects.core.testing)

@ -71,7 +71,7 @@ import com.google.samples.apps.nowinandroid.feature.settings.impl.SettingsUiStat
import com.google.samples.apps.nowinandroid.feature.settings.impl.SettingsUiState.Success import com.google.samples.apps.nowinandroid.feature.settings.impl.SettingsUiState.Success
@Composable @Composable
fun SettingsDialog( internal fun SettingsDialog(
onDismiss: () -> Unit, onDismiss: () -> Unit,
viewModel: SettingsViewModel = hiltViewModel(), viewModel: SettingsViewModel = hiltViewModel(),
) { ) {
@ -86,7 +86,7 @@ fun SettingsDialog(
} }
@Composable @Composable
fun SettingsDialog( internal fun SettingsDialog(
settingsUiState: SettingsUiState, settingsUiState: SettingsUiState,
supportDynamicColor: Boolean = supportsDynamicTheming(), supportDynamicColor: Boolean = supportsDynamicTheming(),
onDismiss: () -> Unit, onDismiss: () -> Unit,

@ -33,7 +33,7 @@ import javax.inject.Inject
import kotlin.time.Duration.Companion.seconds import kotlin.time.Duration.Companion.seconds
@HiltViewModel @HiltViewModel
class SettingsViewModel @Inject constructor( internal class SettingsViewModel @Inject constructor(
private val userDataRepository: UserDataRepository, private val userDataRepository: UserDataRepository,
) : ViewModel() { ) : ViewModel() {
val settingsUiState: StateFlow<SettingsUiState> = val settingsUiState: StateFlow<SettingsUiState> =

@ -0,0 +1,34 @@
/*
* Copyright 2025 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.google.samples.apps.nowinandroid.feature.settings.impl.navigation
import androidx.navigation3.runtime.EntryProviderScope
import androidx.navigation3.runtime.NavKey
import androidx.navigation3.scene.DialogSceneStrategy
import com.google.samples.apps.nowinandroid.core.navigation.Navigator
import com.google.samples.apps.nowinandroid.feature.settings.api.navigation.SettingsNavKey
import com.google.samples.apps.nowinandroid.feature.settings.impl.SettingsDialog
fun EntryProviderScope<NavKey>.settingsEntry(navigator: Navigator) {
entry<SettingsNavKey>(
metadata = DialogSceneStrategy.dialog(),
) {
SettingsDialog(
onDismiss = navigator::goBack,
)
}
}

@ -76,6 +76,7 @@ include(":feature:topic:api")
include(":feature:topic:impl") include(":feature:topic:impl")
include(":feature:search:api") include(":feature:search:api")
include(":feature:search:impl") include(":feature:search:impl")
include(":feature:settings:api")
include(":feature:settings:impl") include(":feature:settings:impl")
include(":lint") include(":lint")
include(":sync:work") include(":sync:work")

Loading…
Cancel
Save