Merge pull request #1094 from lihenggui/main

Upgrade Spotless and Ktlint and remove code convention violations
pull/1119/head
Don Turner 1 year ago committed by GitHub
commit ad15f0137e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -4,3 +4,4 @@
[*.{kt,kts}] [*.{kt,kts}]
ij_kotlin_allow_trailing_comma=true ij_kotlin_allow_trailing_comma=true
ij_kotlin_allow_trailing_comma_on_call_site=true ij_kotlin_allow_trailing_comma_on_call_site=true
ktlint_function_naming_ignore_when_annotated_with=Composable, Test

@ -20,7 +20,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.navigation.compose.NavHost import androidx.navigation.compose.NavHost
import com.google.samples.apps.nowinandroid.feature.bookmarks.navigation.bookmarksScreen import com.google.samples.apps.nowinandroid.feature.bookmarks.navigation.bookmarksScreen
import com.google.samples.apps.nowinandroid.feature.foryou.navigation.forYouNavigationRoute import com.google.samples.apps.nowinandroid.feature.foryou.navigation.FOR_YOU_ROUTE
import com.google.samples.apps.nowinandroid.feature.foryou.navigation.forYouScreen import com.google.samples.apps.nowinandroid.feature.foryou.navigation.forYouScreen
import com.google.samples.apps.nowinandroid.feature.interests.navigation.interestsGraph import com.google.samples.apps.nowinandroid.feature.interests.navigation.interestsGraph
import com.google.samples.apps.nowinandroid.feature.search.navigation.searchScreen import com.google.samples.apps.nowinandroid.feature.search.navigation.searchScreen
@ -41,7 +41,7 @@ fun NiaNavHost(
appState: NiaAppState, appState: NiaAppState,
onShowSnackbar: suspend (String, String?) -> Boolean, onShowSnackbar: suspend (String, String?) -> Boolean,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
startDestination: String = forYouNavigationRoute, startDestination: String = FOR_YOU_ROUTE,
) { ) {
val navController = appState.navController val navController = appState.navController
NavHost( NavHost(

@ -33,11 +33,11 @@ import androidx.tracing.trace
import com.google.samples.apps.nowinandroid.core.data.repository.UserNewsResourceRepository 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.NetworkMonitor
import com.google.samples.apps.nowinandroid.core.ui.TrackDisposableJank import com.google.samples.apps.nowinandroid.core.ui.TrackDisposableJank
import com.google.samples.apps.nowinandroid.feature.bookmarks.navigation.bookmarksRoute import com.google.samples.apps.nowinandroid.feature.bookmarks.navigation.BOOKMARKS_ROUTE
import com.google.samples.apps.nowinandroid.feature.bookmarks.navigation.navigateToBookmarks import com.google.samples.apps.nowinandroid.feature.bookmarks.navigation.navigateToBookmarks
import com.google.samples.apps.nowinandroid.feature.foryou.navigation.forYouNavigationRoute import com.google.samples.apps.nowinandroid.feature.foryou.navigation.FOR_YOU_ROUTE
import com.google.samples.apps.nowinandroid.feature.foryou.navigation.navigateToForYou import com.google.samples.apps.nowinandroid.feature.foryou.navigation.navigateToForYou
import com.google.samples.apps.nowinandroid.feature.interests.navigation.interestsRoute import com.google.samples.apps.nowinandroid.feature.interests.navigation.INTERESTS_ROUTE
import com.google.samples.apps.nowinandroid.feature.interests.navigation.navigateToInterestsGraph import com.google.samples.apps.nowinandroid.feature.interests.navigation.navigateToInterestsGraph
import com.google.samples.apps.nowinandroid.feature.search.navigation.navigateToSearch import com.google.samples.apps.nowinandroid.feature.search.navigation.navigateToSearch
import com.google.samples.apps.nowinandroid.navigation.TopLevelDestination import com.google.samples.apps.nowinandroid.navigation.TopLevelDestination
@ -91,9 +91,9 @@ class NiaAppState(
val currentTopLevelDestination: TopLevelDestination? val currentTopLevelDestination: TopLevelDestination?
@Composable get() = when (currentDestination?.route) { @Composable get() = when (currentDestination?.route) {
forYouNavigationRoute -> FOR_YOU FOR_YOU_ROUTE -> FOR_YOU
bookmarksRoute -> BOOKMARKS BOOKMARKS_ROUTE -> BOOKMARKS
interestsRoute -> INTERESTS INTERESTS_ROUTE -> INTERESTS
else -> null else -> null
} }

@ -60,7 +60,8 @@ class StartupBenchmark {
packageName = PACKAGE_NAME, packageName = PACKAGE_NAME,
metrics = listOf(StartupTimingMetric()), metrics = listOf(StartupTimingMetric()),
compilationMode = compilationMode, compilationMode = compilationMode,
iterations = 20, // More iterations result in higher statistical significance. // More iterations result in higher statistical significance.
iterations = 20,
startupMode = COLD, startupMode = COLD,
setupBlock = { setupBlock = {
pressHome() pressHome()

@ -35,6 +35,8 @@ abstract class AnalyticsModule {
companion object { companion object {
@Provides @Provides
@Singleton @Singleton
fun provideFirebaseAnalytics(): FirebaseAnalytics { return Firebase.analytics } fun provideFirebaseAnalytics(): FirebaseAnalytics {
return Firebase.analytics
}
} }
} }

@ -134,7 +134,7 @@ fun NiaOutlinedButton(
MaterialTheme.colorScheme.outline MaterialTheme.colorScheme.outline
} else { } else {
MaterialTheme.colorScheme.onSurface.copy( MaterialTheme.colorScheme.onSurface.copy(
alpha = NiaButtonDefaults.DisabledOutlinedButtonBorderAlpha, alpha = NiaButtonDefaults.DISABLED_OUTLINED_BUTTON_BORDER_ALPHA,
) )
}, },
), ),
@ -278,7 +278,7 @@ fun NiaButtonPreview() {
@ThemePreviews @ThemePreviews
@Composable @Composable
fun NiaOutlinedButtonPreview() { fun NiaOutlinedButtonPreview() {
NiaTheme() { NiaTheme {
NiaBackground(modifier = Modifier.size(150.dp, 50.dp)) { NiaBackground(modifier = Modifier.size(150.dp, 50.dp)) {
NiaOutlinedButton(onClick = {}, text = { Text("Test button") }) NiaOutlinedButton(onClick = {}, text = { Text("Test button") })
} }
@ -315,7 +315,7 @@ fun NiaButtonLeadingIconPreview() {
object NiaButtonDefaults { object NiaButtonDefaults {
// TODO: File bug // TODO: File bug
// OutlinedButton border color doesn't respect disabled state by default // OutlinedButton border color doesn't respect disabled state by default
const val DisabledOutlinedButtonBorderAlpha = 0.12f const val DISABLED_OUTLINED_BUTTON_BORDER_ALPHA = 0.12f
// TODO: File bug // TODO: File bug
// OutlinedButton default border width isn't exposed via ButtonDefaults // OutlinedButton default border width isn't exposed via ButtonDefaults

@ -76,10 +76,10 @@ fun NiaFilterChip(
borderColor = MaterialTheme.colorScheme.onBackground, borderColor = MaterialTheme.colorScheme.onBackground,
selectedBorderColor = MaterialTheme.colorScheme.onBackground, selectedBorderColor = MaterialTheme.colorScheme.onBackground,
disabledBorderColor = MaterialTheme.colorScheme.onBackground.copy( disabledBorderColor = MaterialTheme.colorScheme.onBackground.copy(
alpha = NiaChipDefaults.DisabledChipContentAlpha, alpha = NiaChipDefaults.DISABLED_CHIP_CONTENT_ALPHA,
), ),
disabledSelectedBorderColor = MaterialTheme.colorScheme.onBackground.copy( disabledSelectedBorderColor = MaterialTheme.colorScheme.onBackground.copy(
alpha = NiaChipDefaults.DisabledChipContentAlpha, alpha = NiaChipDefaults.DISABLED_CHIP_CONTENT_ALPHA,
), ),
selectedBorderWidth = NiaChipDefaults.ChipBorderWidth, selectedBorderWidth = NiaChipDefaults.ChipBorderWidth,
), ),
@ -88,16 +88,16 @@ fun NiaFilterChip(
iconColor = MaterialTheme.colorScheme.onBackground, iconColor = MaterialTheme.colorScheme.onBackground,
disabledContainerColor = if (selected) { disabledContainerColor = if (selected) {
MaterialTheme.colorScheme.onBackground.copy( MaterialTheme.colorScheme.onBackground.copy(
alpha = NiaChipDefaults.DisabledChipContainerAlpha, alpha = NiaChipDefaults.DISABLED_CHIP_CONTAINER_ALPHA,
) )
} else { } else {
Color.Transparent Color.Transparent
}, },
disabledLabelColor = MaterialTheme.colorScheme.onBackground.copy( disabledLabelColor = MaterialTheme.colorScheme.onBackground.copy(
alpha = NiaChipDefaults.DisabledChipContentAlpha, alpha = NiaChipDefaults.DISABLED_CHIP_CONTENT_ALPHA,
), ),
disabledLeadingIconColor = MaterialTheme.colorScheme.onBackground.copy( disabledLeadingIconColor = MaterialTheme.colorScheme.onBackground.copy(
alpha = NiaChipDefaults.DisabledChipContentAlpha, alpha = NiaChipDefaults.DISABLED_CHIP_CONTENT_ALPHA,
), ),
selectedContainerColor = MaterialTheme.colorScheme.primaryContainer, selectedContainerColor = MaterialTheme.colorScheme.primaryContainer,
selectedLabelColor = MaterialTheme.colorScheme.onBackground, selectedLabelColor = MaterialTheme.colorScheme.onBackground,
@ -124,7 +124,7 @@ fun ChipPreview() {
object NiaChipDefaults { object NiaChipDefaults {
// TODO: File bug // TODO: File bug
// FilterChip default values aren't exposed via FilterChipDefaults // FilterChip default values aren't exposed via FilterChipDefaults
const val DisabledChipContainerAlpha = 0.12f const val DISABLED_CHIP_CONTAINER_ALPHA = 0.12f
const val DisabledChipContentAlpha = 0.38f const val DISABLED_CHIP_CONTENT_ALPHA = 0.38f
val ChipBorderWidth = 1.dp val ChipBorderWidth = 1.dp
} }

@ -60,7 +60,7 @@ fun NiaIconToggleButton(
checkedContentColor = MaterialTheme.colorScheme.onPrimaryContainer, checkedContentColor = MaterialTheme.colorScheme.onPrimaryContainer,
disabledContainerColor = if (checked) { disabledContainerColor = if (checked) {
MaterialTheme.colorScheme.onBackground.copy( MaterialTheme.colorScheme.onBackground.copy(
alpha = NiaIconButtonDefaults.DisabledIconButtonContainerAlpha, alpha = NiaIconButtonDefaults.DISABLED_ICON_BUTTON_CONTAINER_ALPHA,
) )
} else { } else {
Color.Transparent Color.Transparent
@ -123,5 +123,5 @@ fun IconButtonPreviewUnchecked() {
object NiaIconButtonDefaults { object NiaIconButtonDefaults {
// TODO: File bug // TODO: File bug
// IconToggleButton disabled container alpha not exposed by IconButtonDefaults // IconToggleButton disabled container alpha not exposed by IconButtonDefaults
const val DisabledIconButtonContainerAlpha = 0.12f const val DISABLED_ICON_BUTTON_CONTAINER_ALPHA = 0.12f
} }

@ -40,7 +40,7 @@ fun NiaTopicTag(
MaterialTheme.colorScheme.primaryContainer MaterialTheme.colorScheme.primaryContainer
} else { } else {
MaterialTheme.colorScheme.surfaceVariant.copy( MaterialTheme.colorScheme.surfaceVariant.copy(
alpha = NiaTagDefaults.UnfollowedTopicTagContainerAlpha, alpha = NiaTagDefaults.UNFOLLOWED_TOPIC_TAG_CONTAINER_ALPHA,
) )
} }
TextButton( TextButton(
@ -50,7 +50,7 @@ fun NiaTopicTag(
containerColor = containerColor, containerColor = containerColor,
contentColor = contentColorFor(backgroundColor = containerColor), contentColor = contentColorFor(backgroundColor = containerColor),
disabledContainerColor = MaterialTheme.colorScheme.onSurface.copy( disabledContainerColor = MaterialTheme.colorScheme.onSurface.copy(
alpha = NiaTagDefaults.DisabledTopicTagContainerAlpha, alpha = NiaTagDefaults.DISABLED_TOPIC_TAG_CONTAINER_ALPHA,
), ),
), ),
) { ) {
@ -75,9 +75,9 @@ fun TagPreview() {
* Now in Android tag default values. * Now in Android tag default values.
*/ */
object NiaTagDefaults { object NiaTagDefaults {
const val UnfollowedTopicTagContainerAlpha = 0.5f const val UNFOLLOWED_TOPIC_TAG_CONTAINER_ALPHA = 0.5f
// TODO: File bug // TODO: File bug
// Button disabled container alpha value not exposed by ButtonDefaults // Button disabled container alpha value not exposed by ButtonDefaults
const val DisabledTopicTagContainerAlpha = 0.12f const val DISABLED_TOPIC_TAG_CONTAINER_ALPHA = 0.12f
} }

@ -251,5 +251,7 @@ private fun scrollbarThumbColor(
} }
private enum class ThumbState { private enum class ThumbState {
Active, Inactive, Dormant Active,
Inactive,
Dormant,
} }

@ -66,7 +66,7 @@ class LoadingWheelScreenshotTests() {
fun loadingWheelAnimation() { fun loadingWheelAnimation() {
composeTestRule.mainClock.autoAdvance = false composeTestRule.mainClock.autoAdvance = false
composeTestRule.setContent { composeTestRule.setContent {
NiaTheme() { NiaTheme {
NiaLoadingWheel(contentDesc = "") NiaLoadingWheel(contentDesc = "")
} }
} }

@ -17,5 +17,7 @@
package com.google.samples.apps.nowinandroid.core.model.data package com.google.samples.apps.nowinandroid.core.model.data
enum class DarkThemeConfig { enum class DarkThemeConfig {
FOLLOW_SYSTEM, LIGHT, DARK FOLLOW_SYSTEM,
LIGHT,
DARK,
} }

@ -19,7 +19,8 @@ package com.google.samples.apps.nowinandroid.core.model.data
/** /**
* A [topic] with the additional information for whether or not it is followed. * A [topic] with the additional information for whether or not it is followed.
*/ */
data class FollowableTopic( // TODO consider changing to UserTopic and flattening // TODO consider changing to UserTopic and flattening
data class FollowableTopic(
val topic: Topic, val topic: Topic,
val isFollowed: Boolean, val isFollowed: Boolean,
) )

@ -17,5 +17,6 @@
package com.google.samples.apps.nowinandroid.core.model.data package com.google.samples.apps.nowinandroid.core.model.data
enum class ThemeBrand { enum class ThemeBrand {
DEFAULT, ANDROID DEFAULT,
ANDROID,
} }

@ -44,10 +44,10 @@ class FakeNiaNetworkDataSourceTest {
) )
} }
@Suppress("ktlint:standard:max-line-length")
@Test @Test
fun testDeserializationOfTopics() = runTest(testDispatcher) { fun testDeserializationOfTopics() = runTest(testDispatcher) {
assertEquals( assertEquals(
/* ktlint-disable max-line-length */
NetworkTopic( NetworkTopic(
id = "1", id = "1",
name = "Headlines", name = "Headlines",
@ -56,15 +56,14 @@ class FakeNiaNetworkDataSourceTest {
url = "", url = "",
imageUrl = "https://firebasestorage.googleapis.com/v0/b/now-in-android.appspot.com/o/img%2Fic_topic_Headlines.svg?alt=media&token=506faab0-617a-4668-9e63-4a2fb996603f", imageUrl = "https://firebasestorage.googleapis.com/v0/b/now-in-android.appspot.com/o/img%2Fic_topic_Headlines.svg?alt=media&token=506faab0-617a-4668-9e63-4a2fb996603f",
), ),
/* ktlint-enable max-line-length */
subject.getTopics().first(), subject.getTopics().first(),
) )
} }
@Suppress("ktlint:standard:max-line-length")
@Test @Test
fun testDeserializationOfNewsResources() = runTest(testDispatcher) { fun testDeserializationOfNewsResources() = runTest(testDispatcher) {
assertEquals( assertEquals(
/* ktlint-disable max-line-length */
NetworkNewsResource( NetworkNewsResource(
id = "125", id = "125",
title = "Android Basics with Compose", title = "Android Basics with Compose",
@ -83,7 +82,6 @@ class FakeNiaNetworkDataSourceTest {
type = "Codelab", type = "Codelab",
topics = listOf("2", "3", "10"), topics = listOf("2", "3", "10"),
), ),
/* ktlint-enable max-line-length */
subject.getNewsResources().find { it.id == "125" }, subject.getNewsResources().find { it.id == "125" },
) )
} }

@ -14,12 +14,13 @@
* limitations under the License. * limitations under the License.
*/ */
@file:Suppress("ktlint:standard:max-line-length")
package com.google.samples.apps.nowinandroid.core.testing.data package com.google.samples.apps.nowinandroid.core.testing.data
import com.google.samples.apps.nowinandroid.core.model.data.FollowableTopic import com.google.samples.apps.nowinandroid.core.model.data.FollowableTopic
import com.google.samples.apps.nowinandroid.core.model.data.Topic import com.google.samples.apps.nowinandroid.core.model.data.Topic
/* ktlint-disable max-line-length */
val followableTopicTestData: List<FollowableTopic> = listOf( val followableTopicTestData: List<FollowableTopic> = listOf(
FollowableTopic( FollowableTopic(
topic = Topic( topic = Topic(

@ -14,12 +14,13 @@
* limitations under the License. * limitations under the License.
*/ */
@file:Suppress("ktlint:standard:max-line-length")
package com.google.samples.apps.nowinandroid.core.testing.data package com.google.samples.apps.nowinandroid.core.testing.data
import com.google.samples.apps.nowinandroid.core.model.data.NewsResource import com.google.samples.apps.nowinandroid.core.model.data.NewsResource
import kotlinx.datetime.Instant import kotlinx.datetime.Instant
/* ktlint-disable max-line-length */
val newsResourcesTestData: List<NewsResource> = listOf( val newsResourcesTestData: List<NewsResource> = listOf(
NewsResource( NewsResource(
id = "1", id = "1",

@ -14,11 +14,12 @@
* limitations under the License. * limitations under the License.
*/ */
@file:Suppress("ktlint:standard:max-line-length")
package com.google.samples.apps.nowinandroid.core.testing.data package com.google.samples.apps.nowinandroid.core.testing.data
import com.google.samples.apps.nowinandroid.core.model.data.Topic import com.google.samples.apps.nowinandroid.core.model.data.Topic
/* ktlint-disable max-line-length */
val topicsTestData: List<Topic> = listOf( val topicsTestData: List<Topic> = listOf(
Topic( Topic(
id = "2", id = "2",

@ -14,6 +14,8 @@
* limitations under the License. * limitations under the License.
*/ */
@file:Suppress("ktlint:standard:max-line-length")
package com.google.samples.apps.nowinandroid.core.testing.data package com.google.samples.apps.nowinandroid.core.testing.data
import com.google.samples.apps.nowinandroid.core.model.data.DarkThemeConfig import com.google.samples.apps.nowinandroid.core.model.data.DarkThemeConfig
@ -26,7 +28,6 @@ import kotlinx.datetime.LocalDateTime
import kotlinx.datetime.TimeZone import kotlinx.datetime.TimeZone
import kotlinx.datetime.toInstant import kotlinx.datetime.toInstant
/* ktlint-disable max-line-length */
val userNewsResourcesTestData: List<UserNewsResource> = UserData( val userNewsResourcesTestData: List<UserNewsResource> = UserData(
bookmarkedNewsResources = setOf("1", "4"), bookmarkedNewsResources = setOf("1", "4"),
viewedNewsResources = setOf("1", "2", "4"), viewedNewsResources = setOf("1", "2", "4"),

@ -38,8 +38,10 @@ import org.robolectric.RuntimeEnvironment
val DefaultRoborazziOptions = val DefaultRoborazziOptions =
RoborazziOptions( RoborazziOptions(
compareOptions = CompareOptions(changeThreshold = 0f), // Pixel-perfect matching // Pixel-perfect matching
recordOptions = RecordOptions(resizeScale = 0.5), // Reduce the size of the PNGs compareOptions = CompareOptions(changeThreshold = 0f),
// Reduce the size of the PNGs
recordOptions = RecordOptions(resizeScale = 0.5),
) )
enum class DefaultTestDevices(val description: String, val spec: String) { enum class DefaultTestDevices(val description: String, val spec: String) {

@ -14,13 +14,14 @@
* limitations under the License. * limitations under the License.
*/ */
@file:Suppress("ktlint:standard:max-line-length")
package com.google.samples.apps.nowinandroid.core.ui package com.google.samples.apps.nowinandroid.core.ui
import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import com.google.samples.apps.nowinandroid.core.model.data.FollowableTopic import com.google.samples.apps.nowinandroid.core.model.data.FollowableTopic
import com.google.samples.apps.nowinandroid.core.model.data.Topic import com.google.samples.apps.nowinandroid.core.model.data.Topic
/* ktlint-disable max-line-length */
/** /**
* This [PreviewParameterProvider](https://developer.android.com/reference/kotlin/androidx/compose/ui/tooling/preview/PreviewParameterProvider) * This [PreviewParameterProvider](https://developer.android.com/reference/kotlin/androidx/compose/ui/tooling/preview/PreviewParameterProvider)
* provides list of [FollowableTopic] for Composable previews. * provides list of [FollowableTopic] for Composable previews.

@ -186,7 +186,8 @@ fun NewsResourceHeaderImage(
painterResource(drawable.ic_placeholder_default) painterResource(drawable.ic_placeholder_default)
}, },
// TODO b/226661685: Investigate using alt text of image to populate content description // TODO b/226661685: Investigate using alt text of image to populate content description
contentDescription = null, // decorative image, // decorative image,
contentDescription = null,
) )
} }
} }
@ -295,7 +296,8 @@ fun NewsResourceTopics(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
) { ) {
Row( Row(
modifier = modifier.horizontalScroll(rememberScrollState()), // causes narrow chips // causes narrow chips
modifier = modifier.horizontalScroll(rememberScrollState()),
horizontalArrangement = Arrangement.spacedBy(4.dp), horizontalArrangement = Arrangement.spacedBy(4.dp),
) { ) {
for (followableTopic in topics) { for (followableTopic in topics) {

@ -14,6 +14,8 @@
* limitations under the License. * limitations under the License.
*/ */
@file:Suppress("ktlint:standard:max-line-length")
package com.google.samples.apps.nowinandroid.core.ui package com.google.samples.apps.nowinandroid.core.ui
import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.compose.ui.tooling.preview.PreviewParameterProvider
@ -29,7 +31,6 @@ import kotlinx.datetime.LocalDateTime
import kotlinx.datetime.TimeZone import kotlinx.datetime.TimeZone
import kotlinx.datetime.toInstant import kotlinx.datetime.toInstant
/* ktlint-disable max-line-length */
/** /**
* This [PreviewParameterProvider](https://developer.android.com/reference/kotlin/androidx/compose/ui/tooling/preview/PreviewParameterProvider) * This [PreviewParameterProvider](https://developer.android.com/reference/kotlin/androidx/compose/ui/tooling/preview/PreviewParameterProvider)
* provides list of [UserNewsResource] for Composable previews. * provides list of [UserNewsResource] for Composable previews.

@ -22,17 +22,17 @@ import androidx.navigation.NavOptions
import androidx.navigation.compose.composable import androidx.navigation.compose.composable
import com.google.samples.apps.nowinandroid.feature.bookmarks.BookmarksRoute import com.google.samples.apps.nowinandroid.feature.bookmarks.BookmarksRoute
const val bookmarksRoute = "bookmarks_route" const val BOOKMARKS_ROUTE = "bookmarks_route"
fun NavController.navigateToBookmarks(navOptions: NavOptions? = null) { fun NavController.navigateToBookmarks(navOptions: NavOptions? = null) {
this.navigate(bookmarksRoute, navOptions) this.navigate(BOOKMARKS_ROUTE, navOptions)
} }
fun NavGraphBuilder.bookmarksScreen( fun NavGraphBuilder.bookmarksScreen(
onTopicClick: (String) -> Unit, onTopicClick: (String) -> Unit,
onShowSnackbar: suspend (String, String?) -> Boolean, onShowSnackbar: suspend (String, String?) -> Boolean,
) { ) {
composable(route = bookmarksRoute) { composable(route = BOOKMARKS_ROUTE) {
BookmarksRoute(onTopicClick, onShowSnackbar) BookmarksRoute(onTopicClick, onShowSnackbar)
} }
} }

@ -437,7 +437,8 @@ fun TopicIcon(
DynamicAsyncImage( DynamicAsyncImage(
placeholder = painterResource(R.drawable.ic_icon_placeholder), placeholder = painterResource(R.drawable.ic_icon_placeholder),
imageUrl = imageUrl, imageUrl = imageUrl,
contentDescription = null, // decorative // decorative
contentDescription = null,
modifier = modifier modifier = modifier
.padding(10.dp) .padding(10.dp)
.size(32.dp), .size(32.dp),

@ -26,17 +26,17 @@ import androidx.navigation.navDeepLink
import com.google.samples.apps.nowinandroid.feature.foryou.ForYouRoute import com.google.samples.apps.nowinandroid.feature.foryou.ForYouRoute
const val LINKED_NEWS_RESOURCE_ID = "linkedNewsResourceId" const val LINKED_NEWS_RESOURCE_ID = "linkedNewsResourceId"
const val forYouNavigationRoute = "for_you_route/{$LINKED_NEWS_RESOURCE_ID}" const val FOR_YOU_ROUTE = "for_you_route/{$LINKED_NEWS_RESOURCE_ID}"
private const val DEEP_LINK_URI_PATTERN = private const val DEEP_LINK_URI_PATTERN =
"https://www.nowinandroid.apps.samples.google.com/foryou/{$LINKED_NEWS_RESOURCE_ID}" "https://www.nowinandroid.apps.samples.google.com/foryou/{$LINKED_NEWS_RESOURCE_ID}"
fun NavController.navigateToForYou(navOptions: NavOptions? = null) { fun NavController.navigateToForYou(navOptions: NavOptions? = null) {
this.navigate(forYouNavigationRoute, navOptions) this.navigate(FOR_YOU_ROUTE, navOptions)
} }
fun NavGraphBuilder.forYouScreen(onTopicClick: (String) -> Unit) { fun NavGraphBuilder.forYouScreen(onTopicClick: (String) -> Unit) {
composable( composable(
route = forYouNavigationRoute, route = FOR_YOU_ROUTE,
deepLinks = listOf( deepLinks = listOf(
navDeepLink { uriPattern = DEEP_LINK_URI_PATTERN }, navDeepLink { uriPattern = DEEP_LINK_URI_PATTERN },
), ),

@ -99,7 +99,8 @@ private fun InterestsIcon(topicImageUrl: String, modifier: Modifier = Modifier)
.background(MaterialTheme.colorScheme.surface) .background(MaterialTheme.colorScheme.surface)
.padding(4.dp), .padding(4.dp),
imageVector = NiaIcons.Person, imageVector = NiaIcons.Person,
contentDescription = null, // decorative image // decorative image
contentDescription = null,
) )
} else { } else {
DynamicAsyncImage( DynamicAsyncImage(

@ -24,7 +24,7 @@ import androidx.navigation.navigation
import com.google.samples.apps.nowinandroid.feature.interests.InterestsRoute import com.google.samples.apps.nowinandroid.feature.interests.InterestsRoute
private const val INTERESTS_GRAPH_ROUTE_PATTERN = "interests_graph" private const val INTERESTS_GRAPH_ROUTE_PATTERN = "interests_graph"
const val interestsRoute = "interests_route" const val INTERESTS_ROUTE = "interests_route"
fun NavController.navigateToInterestsGraph(navOptions: NavOptions? = null) { fun NavController.navigateToInterestsGraph(navOptions: NavOptions? = null) {
this.navigate(INTERESTS_GRAPH_ROUTE_PATTERN, navOptions) this.navigate(INTERESTS_GRAPH_ROUTE_PATTERN, navOptions)
@ -36,9 +36,9 @@ fun NavGraphBuilder.interestsGraph(
) { ) {
navigation( navigation(
route = INTERESTS_GRAPH_ROUTE_PATTERN, route = INTERESTS_GRAPH_ROUTE_PATTERN,
startDestination = interestsRoute, startDestination = INTERESTS_ROUTE,
) { ) {
composable(route = interestsRoute) { composable(route = INTERESTS_ROUTE) {
InterestsRoute(onTopicClick) InterestsRoute(onTopicClick)
} }
nestedGraphs() nestedGraphs()

@ -328,7 +328,8 @@ private fun SearchResultBody(
topics.forEach { followableTopic -> topics.forEach { followableTopic ->
val topicId = followableTopic.topic.id val topicId = followableTopic.topic.id
item( item(
key = "topic-$topicId", // Append a prefix to distinguish a key for news resources // Append a prefix to distinguish a key for news resources
key = "topic-$topicId",
span = StaggeredGridItemSpan.FullLine, span = StaggeredGridItemSpan.FullLine,
) { ) {
InterestsItem( InterestsItem(

@ -14,6 +14,8 @@
* limitations under the License. * limitations under the License.
*/ */
@file:Suppress("ktlint:standard:max-line-length")
package com.google.samples.apps.nowinandroid.feature.search package com.google.samples.apps.nowinandroid.feature.search
import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.compose.ui.tooling.preview.PreviewParameterProvider
@ -21,7 +23,6 @@ import com.google.samples.apps.nowinandroid.core.model.data.FollowableTopic
import com.google.samples.apps.nowinandroid.core.ui.PreviewParameterData.newsResources import com.google.samples.apps.nowinandroid.core.ui.PreviewParameterData.newsResources
import com.google.samples.apps.nowinandroid.core.ui.PreviewParameterData.topics import com.google.samples.apps.nowinandroid.core.ui.PreviewParameterData.topics
/* ktlint-disable max-line-length */
/** /**
* This [PreviewParameterProvider](https://developer.android.com/reference/kotlin/androidx/compose/ui/tooling/preview/PreviewParameterProvider) * This [PreviewParameterProvider](https://developer.android.com/reference/kotlin/androidx/compose/ui/tooling/preview/PreviewParameterProvider)
* provides list of [SearchResultUiState] for Composable previews. * provides list of [SearchResultUiState] for Composable previews.

@ -22,10 +22,10 @@ import androidx.navigation.NavOptions
import androidx.navigation.compose.composable import androidx.navigation.compose.composable
import com.google.samples.apps.nowinandroid.feature.search.SearchRoute import com.google.samples.apps.nowinandroid.feature.search.SearchRoute
const val searchRoute = "search_route" const val SEARCH_ROUTE = "search_route"
fun NavController.navigateToSearch(navOptions: NavOptions? = null) { fun NavController.navigateToSearch(navOptions: NavOptions? = null) {
this.navigate(searchRoute, navOptions) this.navigate(SEARCH_ROUTE, navOptions)
} }
fun NavGraphBuilder.searchScreen( fun NavGraphBuilder.searchScreen(
@ -35,7 +35,7 @@ fun NavGraphBuilder.searchScreen(
) { ) {
// TODO: Handle back stack for each top-level destination. At the moment each top-level // TODO: Handle back stack for each top-level destination. At the moment each top-level
// destination may have own search screen's back stack. // destination may have own search screen's back stack.
composable(route = searchRoute) { composable(route = SEARCH_ROUTE) {
SearchRoute( SearchRoute(
onBackClick = onBackClick, onBackClick = onBackClick,
onInterestsClick = onInterestsClick, onInterestsClick = onInterestsClick,

@ -14,6 +14,8 @@
* limitations under the License. * limitations under the License.
*/ */
@file:Suppress("ktlint:standard:max-line-length")
package com.google.samples.apps.nowinandroid.feature.settings package com.google.samples.apps.nowinandroid.feature.settings
import android.content.Intent import android.content.Intent
@ -316,7 +318,6 @@ private fun PreviewSettingsDialogLoading() {
} }
} }
/* ktlint-disable max-line-length */
private const val PRIVACY_POLICY_URL = "https://policies.google.com/privacy" private const val PRIVACY_POLICY_URL = "https://policies.google.com/privacy"
private const val BRAND_GUIDELINES_URL = "https://developer.android.com/distribute/marketing-tools/brand-guidelines" private const val BRAND_GUIDELINES_URL = "https://developer.android.com/distribute/marketing-tools/brand-guidelines"
private const val FEEDBACK_URL = "https://goo.gle/nia-app-feedback" private const val FEEDBACK_URL = "https://goo.gle/nia-app-feedback"

@ -31,11 +31,11 @@ import kotlin.text.Charsets.UTF_8
private val URL_CHARACTER_ENCODING = UTF_8.name() private val URL_CHARACTER_ENCODING = UTF_8.name()
@VisibleForTesting @VisibleForTesting
internal const val topicIdArg = "topicId" internal const val TOPIC_ID_ARG = "topicId"
internal class TopicArgs(val topicId: String) { internal class TopicArgs(val topicId: String) {
constructor(savedStateHandle: SavedStateHandle) : constructor(savedStateHandle: SavedStateHandle) :
this(URLDecoder.decode(checkNotNull(savedStateHandle[topicIdArg]), URL_CHARACTER_ENCODING)) this(URLDecoder.decode(checkNotNull(savedStateHandle[TOPIC_ID_ARG]), URL_CHARACTER_ENCODING))
} }
fun NavController.navigateToTopic(topicId: String) { fun NavController.navigateToTopic(topicId: String) {
@ -50,9 +50,9 @@ fun NavGraphBuilder.topicScreen(
onTopicClick: (String) -> Unit, onTopicClick: (String) -> Unit,
) { ) {
composable( composable(
route = "topic_route/{$topicIdArg}", route = "topic_route/{$TOPIC_ID_ARG}",
arguments = listOf( arguments = listOf(
navArgument(topicIdArg) { type = NavType.StringType }, navArgument(TOPIC_ID_ARG) { type = NavType.StringType },
), ),
) { ) {
TopicRoute(onBackClick = onBackClick, onTopicClick = onTopicClick) TopicRoute(onBackClick = onBackClick, onTopicClick = onTopicClick)

@ -25,7 +25,7 @@ import com.google.samples.apps.nowinandroid.core.testing.repository.TestNewsRepo
import com.google.samples.apps.nowinandroid.core.testing.repository.TestTopicsRepository import com.google.samples.apps.nowinandroid.core.testing.repository.TestTopicsRepository
import com.google.samples.apps.nowinandroid.core.testing.repository.TestUserDataRepository import com.google.samples.apps.nowinandroid.core.testing.repository.TestUserDataRepository
import com.google.samples.apps.nowinandroid.core.testing.util.MainDispatcherRule import com.google.samples.apps.nowinandroid.core.testing.util.MainDispatcherRule
import com.google.samples.apps.nowinandroid.feature.topic.navigation.topicIdArg import com.google.samples.apps.nowinandroid.feature.topic.navigation.TOPIC_ID_ARG
import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.first
@ -60,7 +60,7 @@ class TopicViewModelTest {
@Before @Before
fun setup() { fun setup() {
viewModel = TopicViewModel( viewModel = TopicViewModel(
savedStateHandle = SavedStateHandle(mapOf(topicIdArg to testInputTopics[0].topic.id)), savedStateHandle = SavedStateHandle(mapOf(TOPIC_ID_ARG to testInputTopics[0].topic.id)),
userDataRepository = userDataRepository, userDataRepository = userDataRepository,
topicsRepository = topicsRepository, topicsRepository = topicsRepository,
userNewsResourceRepository = userNewsResourceRepository, userNewsResourceRepository = userNewsResourceRepository,

@ -14,10 +14,10 @@
* limitations under the License. * limitations under the License.
*/ */
val ktlintVersion = "0.48.1" val ktlintVersion = "1.0.1"
initscript { initscript {
val spotlessVersion = "6.22.0" val spotlessVersion = "6.23.3"
repositories { repositories {
mavenCentral() mavenCentral()
@ -35,7 +35,11 @@ rootProject {
kotlin { kotlin {
target("**/*.kt") target("**/*.kt")
targetExclude("**/build/**/*.kt") targetExclude("**/build/**/*.kt")
ktlint(ktlintVersion).userData(mapOf("android" to "true")) ktlint(ktlintVersion).editorConfigOverride(
mapOf(
"android" to "true",
),
)
licenseHeaderFile(rootProject.file("spotless/copyright.kt")) licenseHeaderFile(rootProject.file("spotless/copyright.kt"))
} }
format("kts") { format("kts") {

@ -28,7 +28,7 @@ object Sync {
WorkManager.getInstance(context).apply { WorkManager.getInstance(context).apply {
// Run sync on app startup and ensure only one sync worker runs at any time // Run sync on app startup and ensure only one sync worker runs at any time
enqueueUniqueWork( enqueueUniqueWork(
SyncWorkName, SYNC_WORK_NAME,
ExistingWorkPolicy.KEEP, ExistingWorkPolicy.KEEP,
SyncWorker.startUpSyncWork(), SyncWorker.startUpSyncWork(),
) )
@ -37,4 +37,4 @@ object Sync {
} }
// This name should not be changed otherwise the app may have concurrent sync requests running // This name should not be changed otherwise the app may have concurrent sync requests running
internal const val SyncWorkName = "SyncWorkName" internal const val SYNC_WORK_NAME = "SyncWorkName"

@ -22,7 +22,7 @@ import androidx.work.WorkInfo
import androidx.work.WorkInfo.State import androidx.work.WorkInfo.State
import androidx.work.WorkManager import androidx.work.WorkManager
import com.google.samples.apps.nowinandroid.core.data.util.SyncManager import com.google.samples.apps.nowinandroid.core.data.util.SyncManager
import com.google.samples.apps.nowinandroid.sync.initializers.SyncWorkName import com.google.samples.apps.nowinandroid.sync.initializers.SYNC_WORK_NAME
import com.google.samples.apps.nowinandroid.sync.workers.SyncWorker import com.google.samples.apps.nowinandroid.sync.workers.SyncWorker
import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
@ -37,7 +37,7 @@ class WorkManagerSyncManager @Inject constructor(
@ApplicationContext private val context: Context, @ApplicationContext private val context: Context,
) : SyncManager { ) : SyncManager {
override val isSyncing: Flow<Boolean> = override val isSyncing: Flow<Boolean> =
WorkManager.getInstance(context).getWorkInfosForUniqueWorkFlow(SyncWorkName) WorkManager.getInstance(context).getWorkInfosForUniqueWorkFlow(SYNC_WORK_NAME)
.map(List<WorkInfo>::anyRunning) .map(List<WorkInfo>::anyRunning)
.conflate() .conflate()
@ -45,7 +45,7 @@ class WorkManagerSyncManager @Inject constructor(
val workManager = WorkManager.getInstance(context) val workManager = WorkManager.getInstance(context)
// Run sync on app startup and ensure only one sync worker runs at any time // Run sync on app startup and ensure only one sync worker runs at any time
workManager.enqueueUniqueWork( workManager.enqueueUniqueWork(
SyncWorkName, SYNC_WORK_NAME,
ExistingWorkPolicy.KEEP, ExistingWorkPolicy.KEEP,
SyncWorker.startUpSyncWork(), SyncWorker.startUpSyncWork(),
) )

Loading…
Cancel
Save