More updates for device previews

adaptive-previews-device-classes
Eric Schmidt 3 months ago
parent 4be3bb9bb7
commit 04c66f7a72

@ -64,6 +64,10 @@ import androidx.navigation.NavDestination
import androidx.navigation.NavDestination.Companion.hasRoute
import androidx.navigation.NavDestination.Companion.hierarchy
import com.google.samples.apps.nowinandroid.R
import com.google.samples.apps.nowinandroid.core.data.repository.NewsResourceQuery
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.designsystem.component.NiaBackground
import com.google.samples.apps.nowinandroid.core.designsystem.component.NiaGradientBackground
import com.google.samples.apps.nowinandroid.core.designsystem.component.NiaNavigationSuiteScaffold
@ -71,9 +75,15 @@ 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.designsystem.theme.NiaTheme
import com.google.samples.apps.nowinandroid.core.model.data.UserNewsResource
import com.google.samples.apps.nowinandroid.core.ui.DevicePreviews
import com.google.samples.apps.nowinandroid.feature.settings.SettingsDialog
import com.google.samples.apps.nowinandroid.navigation.NiaNavHost
import com.google.samples.apps.nowinandroid.navigation.TopLevelDestination
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flowOf
import kotlinx.datetime.TimeZone
import kotlin.reflect.KClass
import com.google.samples.apps.nowinandroid.feature.settings.R as settingsR
@ -281,3 +291,32 @@ private fun NavDestination?.isRouteInHierarchy(route: KClass<*>) =
this?.hierarchy?.any {
it.hasRoute(route)
} ?: false
@DevicePreviews
@Composable
fun NiaAppPreview() {
NiaTheme {
NiaApp(
appState = rememberNiaAppState(
networkMonitor = object : NetworkMonitor {
override val isOnline: Flow<Boolean> = flowOf(true)
},
userNewsResourceRepository = object : UserNewsResourceRepository {
override fun observeAll(query: NewsResourceQuery): Flow<List<UserNewsResource>> =
flowOf(emptyList())
override fun observeAllForFollowedTopics(): Flow<List<UserNewsResource>> =
flowOf(emptyList())
override fun observeAllBookmarked(): Flow<List<UserNewsResource>> =
flowOf(emptyList())
},
timeZoneMonitor = object : TimeZoneMonitor {
override val currentTimeZone: Flow<TimeZone> =
flowOf(TimeZone.currentSystemDefault())
},
),
)
}
}

@ -35,7 +35,7 @@ dependencies {
testImplementation(libs.hilt.android.testing)
testImplementation(libs.robolectric)
testImplementation(projects.core.testing)
testDemoImplementation(projects.core.screenshotTesting)
testImplementation(projects.core.screenshotTesting)
androidTestImplementation(libs.bundles.androidx.compose.ui.test)
androidTestImplementation(projects.core.testing)

@ -16,7 +16,6 @@
package com.google.samples.apps.nowinandroid.feature.foryou
import android.net.Uri
import android.os.Build.VERSION
import android.os.Build.VERSION_CODES
import androidx.activity.compose.ReportDrawnWhen
@ -103,31 +102,48 @@ import com.google.samples.apps.nowinandroid.core.ui.TrackScrollJank
import com.google.samples.apps.nowinandroid.core.ui.UserNewsResourcePreviewParameterProvider
import com.google.samples.apps.nowinandroid.core.ui.launchCustomChromeTab
import com.google.samples.apps.nowinandroid.core.ui.newsFeed
import androidx.core.net.toUri
@Composable
internal fun ForYouScreen(
onTopicClick: (String) -> Unit,
modifier: Modifier = Modifier,
viewModel: ForYouViewModel = hiltViewModel(),
viewModel: ForYouViewModel? = if (LocalInspectionMode.current) null else hiltViewModel(),
) {
val onboardingUiState by viewModel.onboardingUiState.collectAsStateWithLifecycle()
val feedState by viewModel.feedState.collectAsStateWithLifecycle()
val isSyncing by viewModel.isSyncing.collectAsStateWithLifecycle()
val deepLinkedUserNewsResource by viewModel.deepLinkedNewsResource.collectAsStateWithLifecycle()
if (viewModel != null) {
val onboardingUiState by viewModel.onboardingUiState.collectAsStateWithLifecycle()
val feedState by viewModel.feedState.collectAsStateWithLifecycle()
val isSyncing by viewModel.isSyncing.collectAsStateWithLifecycle()
val deepLinkedUserNewsResource by viewModel.deepLinkedNewsResource.collectAsStateWithLifecycle()
ForYouScreen(
isSyncing = isSyncing,
onboardingUiState = onboardingUiState,
feedState = feedState,
deepLinkedUserNewsResource = deepLinkedUserNewsResource,
onTopicCheckedChanged = viewModel::updateTopicSelection,
onDeepLinkOpened = viewModel::onDeepLinkOpened,
onTopicClick = onTopicClick,
saveFollowedTopics = viewModel::dismissOnboarding,
onNewsResourcesCheckedChanged = viewModel::updateNewsResourceSaved,
onNewsResourceViewed = { viewModel.setNewsResourceViewed(it, true) },
modifier = modifier,
)
ForYouScreen(
isSyncing = isSyncing,
onboardingUiState = onboardingUiState,
feedState = feedState,
deepLinkedUserNewsResource = deepLinkedUserNewsResource,
onTopicCheckedChanged = viewModel::updateTopicSelection,
onDeepLinkOpened = viewModel::onDeepLinkOpened,
onTopicClick = onTopicClick,
saveFollowedTopics = viewModel::dismissOnboarding,
onNewsResourcesCheckedChanged = viewModel::updateNewsResourceSaved,
onNewsResourceViewed = { viewModel.setNewsResourceViewed(it, true) },
modifier = modifier,
)
} else {
ForYouScreen(
isSyncing = false,
onboardingUiState = OnboardingUiState.NotShown,
feedState = NewsFeedUiState.Success(emptyList()),
deepLinkedUserNewsResource = null,
onTopicCheckedChanged = { _, _ -> },
onDeepLinkOpened = { },
onTopicClick = onTopicClick,
saveFollowedTopics = { },
onNewsResourcesCheckedChanged = { _, _ -> },
onNewsResourceViewed = { },
modifier = modifier,
)
}
}
@Composable
@ -184,7 +200,7 @@ internal fun ForYouScreen(
),
)
layout(placeable.width, placeable.height) {
placeable.place(0, 0)
placeable.place(-16.dp.roundToPx(), 0)
}
},
)
@ -300,11 +316,12 @@ private fun LazyStaggeredGridScope.onboarding(
enabled = onboardingUiState.isDismissable,
modifier = Modifier
.padding(horizontal = 24.dp)
.widthIn(364.dp)
.widthIn(max = 320.dp)
.fillMaxWidth(),
) {
Text(
text = stringResource(R.string.feature_foryou_done),
color = if (onboardingUiState.isDismissable) androidx.compose.ui.graphics.Color.Unspecified else MaterialTheme.colorScheme.onSurface.copy(alpha = 0.7f),
)
}
}
@ -475,7 +492,7 @@ private fun DeepLinkEffect(
launchCustomChromeTab(
context = context,
uri = Uri.parse(userNewsResource.url),
uri = userNewsResource.url.toUri(),
toolbarColor = backgroundColor,
)
}
@ -617,3 +634,24 @@ fun ForYouScreenPopulatedAndLoading(
)
}
}
@DevicePreviews
@Composable
fun ForYouScreenNotPopulatedOnboarding() {
NiaTheme {
ForYouScreen(
isSyncing = true,
onboardingUiState = OnboardingUiState.Shown(
topics = emptyList(),
),
feedState = NewsFeedUiState.Loading,
deepLinkedUserNewsResource = null,
onTopicCheckedChanged = { _, _ -> },
saveFollowedTopics = {},
onNewsResourcesCheckedChanged = { _, _ -> },
onNewsResourceViewed = {},
onTopicClick = {},
onDeepLinkOpened = {},
)
}
}
Loading…
Cancel
Save