From 23f14116f6ba8c23a5da6f81b69efd6a51c5cb8d Mon Sep 17 00:00:00 2001 From: Simon Marquis Date: Sat, 16 Sep 2023 15:19:58 +0200 Subject: [PATCH 01/35] Extract `ProfileVerifier` logs from `MainActivity` to `NiaApplication` - Prevent logging multiple times (because of `onResume()` callback) - Remove unnecessary io dispatcher: `ListenableFuture.await()` is already main-safe and prevent acquiring io slot. - Merge comments into a single javadoc comment on the `ProfileVerifierLogger` type. - Add proper javadoc format with markdown specific blocks. - Update logs & tag to be more uniform. Closes #945 --- .../samples/apps/nowinandroid/MainActivity.kt | 41 ----------- .../apps/nowinandroid/NiaApplication.kt | 5 ++ .../util/ProfileVerifierLogger.kt | 70 +++++++++++++++++++ 3 files changed, 75 insertions(+), 41 deletions(-) create mode 100644 app/src/main/java/com/google/samples/apps/nowinandroid/util/ProfileVerifierLogger.kt diff --git a/app/src/main/java/com/google/samples/apps/nowinandroid/MainActivity.kt b/app/src/main/java/com/google/samples/apps/nowinandroid/MainActivity.kt index 7fe1bc674..42468ca6f 100644 --- a/app/src/main/java/com/google/samples/apps/nowinandroid/MainActivity.kt +++ b/app/src/main/java/com/google/samples/apps/nowinandroid/MainActivity.kt @@ -17,7 +17,6 @@ package com.google.samples.apps.nowinandroid import android.os.Bundle -import android.util.Log import androidx.activity.ComponentActivity import androidx.activity.SystemBarStyle import androidx.activity.compose.setContent @@ -37,7 +36,6 @@ import androidx.lifecycle.Lifecycle import androidx.lifecycle.lifecycleScope import androidx.lifecycle.repeatOnLifecycle import androidx.metrics.performance.JankStats -import androidx.profileinstaller.ProfileVerifier import com.google.samples.apps.nowinandroid.MainActivityUiState.Loading import com.google.samples.apps.nowinandroid.MainActivityUiState.Success import com.google.samples.apps.nowinandroid.core.analytics.AnalyticsHelper @@ -49,12 +47,9 @@ import com.google.samples.apps.nowinandroid.core.model.data.DarkThemeConfig import com.google.samples.apps.nowinandroid.core.model.data.ThemeBrand import com.google.samples.apps.nowinandroid.ui.NiaApp import dagger.hilt.android.AndroidEntryPoint -import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.onEach -import kotlinx.coroutines.guava.await import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext import javax.inject.Inject private const val TAG = "MainActivity" @@ -152,48 +147,12 @@ class MainActivity : ComponentActivity() { override fun onResume() { super.onResume() lazyStats.get().isTrackingEnabled = true - lifecycleScope.launch { - logCompilationStatus() - } } override fun onPause() { super.onPause() lazyStats.get().isTrackingEnabled = false } - - /** - * Logs the app's Baseline Profile Compilation Status using [ProfileVerifier]. - */ - private suspend fun logCompilationStatus() { - /* - When delivering through Google Play, the baseline profile is compiled during installation. - In this case you will see the correct state logged without any further action necessary. - To verify baseline profile installation locally, you need to manually trigger baseline - profile installation. - For immediate compilation, call: - `adb shell cmd package compile -f -m speed-profile com.example.macrobenchmark.target` - You can also trigger background optimizations: - `adb shell pm bg-dexopt-job` - Both jobs run asynchronously and might take some time complete. - To see quick turnaround of the ProfileVerifier, we recommend using `speed-profile`. - If you don't do either of these steps, you might only see the profile status reported as - "enqueued for compilation" when running the sample locally. - */ - withContext(Dispatchers.IO) { - val status = ProfileVerifier.getCompilationStatusAsync().await() - Log.d(TAG, "ProfileInstaller status code: ${status.profileInstallResultCode}") - Log.d( - TAG, - when { - status.isCompiledWithProfile -> "ProfileInstaller: is compiled with profile" - status.hasProfileEnqueuedForCompilation() -> - "ProfileInstaller: Enqueued for compilation" - else -> "Profile not compiled or enqueued" - }, - ) - } - } } /** diff --git a/app/src/main/java/com/google/samples/apps/nowinandroid/NiaApplication.kt b/app/src/main/java/com/google/samples/apps/nowinandroid/NiaApplication.kt index 699f52575..9f0bb2ef7 100644 --- a/app/src/main/java/com/google/samples/apps/nowinandroid/NiaApplication.kt +++ b/app/src/main/java/com/google/samples/apps/nowinandroid/NiaApplication.kt @@ -20,6 +20,7 @@ import android.app.Application import coil.ImageLoader import coil.ImageLoaderFactory import com.google.samples.apps.nowinandroid.sync.initializers.Sync +import com.google.samples.apps.nowinandroid.util.ProfileVerifierLogger import dagger.hilt.android.HiltAndroidApp import javax.inject.Inject import javax.inject.Provider @@ -32,10 +33,14 @@ class NiaApplication : Application(), ImageLoaderFactory { @Inject lateinit var imageLoader: Provider + @Inject + lateinit var profileVerifierLogger: ProfileVerifierLogger + override fun onCreate() { super.onCreate() // Initialize Sync; the system responsible for keeping data in the app up to date. Sync.initialize(context = this) + profileVerifierLogger() } override fun newImageLoader(): ImageLoader = imageLoader.get() diff --git a/app/src/main/java/com/google/samples/apps/nowinandroid/util/ProfileVerifierLogger.kt b/app/src/main/java/com/google/samples/apps/nowinandroid/util/ProfileVerifierLogger.kt new file mode 100644 index 000000000..595166f03 --- /dev/null +++ b/app/src/main/java/com/google/samples/apps/nowinandroid/util/ProfileVerifierLogger.kt @@ -0,0 +1,70 @@ +/* + * Copyright 2023 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.util + +import android.util.Log +import androidx.profileinstaller.ProfileVerifier +import com.google.samples.apps.nowinandroid.core.network.di.ApplicationScope +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.guava.await +import kotlinx.coroutines.launch +import javax.inject.Inject + +/** + * Logs the app's Baseline Profile Compilation Status using [ProfileVerifier]. + * + * When delivering through Google Play, the baseline profile is compiled during installation. + * In this case you will see the correct state logged without any further action necessary. + * To verify baseline profile installation locally, you need to manually trigger baseline + * profile installation. + * + * For immediate compilation, call: + * ```bash + * adb shell cmd package compile -f -m speed-profile com.example.macrobenchmark.target + * ``` + * You can also trigger background optimizations: + * ```bash + * adb shell pm bg-dexopt-job + * ``` + * Both jobs run asynchronously and might take some time complete. + * + * To see quick turnaround of the ProfileVerifier, we recommend using `speed-profile`. + * If you don't do either of these steps, you might only see the profile status reported as + * "enqueued for compilation" when running the sample locally. + * + * @see androidx.profileinstaller.ProfileVerifier.CompilationStatus.ResultCode + */ +class ProfileVerifierLogger @Inject constructor( + @ApplicationScope private val scope: CoroutineScope, +) { + companion object { + private const val TAG = "ProfileInstaller" + } + + operator fun invoke() = scope.launch { + val status = ProfileVerifier.getCompilationStatusAsync().await() + Log.d(TAG, "Status code: ${status.profileInstallResultCode}") + Log.d( + TAG, + when { + status.isCompiledWithProfile -> "App compiled with profile" + status.hasProfileEnqueuedForCompilation() -> "Profile enqueued for compilation" + else -> "Profile not compiled nor enqueued" + }, + ) + } +} From 6a3a5ea692b151ac638ec53df1084d794b02141b Mon Sep 17 00:00:00 2001 From: Simon Marquis Date: Thu, 16 Nov 2023 23:45:31 +0100 Subject: [PATCH 02/35] Kotlinify codebase - Remove unnecessary nullable types - Replace no-op method bodies with Unit - Convert to expression body - Replace if with when - Remove braces from 'when' entries - Remove braces from if statement - Convert to single line lambda - oneline if/returns - Replace 'contains' call with 'in' operator Following this refactor, it could be great to envision a more "strict" code formatter like ktlint 1.0 (we are currently stuck at 0.48.1) --- .../apps/nowinandroid/ui/NavigationTest.kt | 2 +- .../samples/apps/nowinandroid/MainActivity.kt | 4 +- .../apps/nowinandroid/di/JankStatsModule.kt | 23 +++--- .../samples/apps/nowinandroid/ui/NiaApp.kt | 4 +- .../apps/nowinandroid/ui/NiaAppState.kt | 4 +- .../test/uiautomator/UiAutomatorHelpers.kt | 14 ++-- .../baselineprofile/StartupBaselineProfile.kt | 13 ++-- .../apps/nowinandroid/PrintTestApks.kt | 6 +- .../apps/nowinandroid/core/result/Result.kt | 13 ++-- .../DefaultRecentSearchRepository.kt | 4 +- .../fake/FakeRecentSearchRepository.kt | 4 +- .../fake/FakeSearchContentsRepository.kt | 2 +- .../repository/fake/FakeTopicsRepository.kt | 5 +- ...CompositeUserNewsResourceRepositoryTest.kt | 4 +- .../core/data/UserNewsResourceTest.kt | 4 +- .../data/testdoubles/TestNewsResourceDao.kt | 6 +- .../testdoubles/TestNiaNetworkDataSource.kt | 11 ++- .../core/data/testdoubles/TestTopicDao.kt | 21 ++---- .../core/datastore/ListToMapMigration.kt | 5 +- .../datastore/NiaPreferencesDataSource.kt | 8 +-- .../core/designsystem/ThemeTest.kt | 70 +++++++------------ .../component/DynamicAsyncImage.kt | 3 +- .../core/designsystem/component/TopAppBar.kt | 4 +- .../component/scrollbar/ScrollbarExt.kt | 9 +-- .../core/designsystem/theme/Tint.kt | 2 +- .../core/domain/GetFollowableTopicsUseCase.kt | 28 ++++---- .../core/model/data/UserNewsResource.kt | 11 ++- .../core/notifications/SystemTrayNotifier.kt | 40 +++++------ .../core/testing/NiaTestRunner.kt | 5 +- .../testing/repository/TestNewsRepository.kt | 4 +- .../repository/TestRecentSearchRepository.kt | 4 +- .../TestSearchContentsRepository.kt | 9 +-- .../repository/TestTopicsRepository.kt | 5 +- .../core/testing/util/MainDispatcherRule.kt | 8 +-- .../core/testing/util/TestAnalyticsHelper.kt | 2 +- .../core/testing/util/TestSyncManager.kt | 4 +- .../core/ui/JankStatsExtensions.kt | 4 +- .../apps/nowinandroid/core/ui/NewsFeed.kt | 4 +- .../feature/bookmarks/BookmarksScreen.kt | 3 +- .../navigation/BookmarksNavigation.kt | 2 +- .../foryou/navigation/ForYouNavigation.kt | 2 +- .../navigation/InterestsNavigation.kt | 2 +- .../feature/search/SearchScreen.kt | 8 +-- .../feature/topic/TopicViewModel.kt | 33 ++------- .../topic/navigation/TopicNavigation.kt | 2 +- .../lint/designsystem/DesignSystemDetector.kt | 15 ++-- 46 files changed, 161 insertions(+), 279 deletions(-) diff --git a/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/NavigationTest.kt b/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/NavigationTest.kt index 5861cda58..d57556ac2 100644 --- a/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/NavigationTest.kt +++ b/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/NavigationTest.kt @@ -90,7 +90,7 @@ class NavigationTest { lateinit var topicsRepository: TopicsRepository private fun AndroidComposeTestRule<*, *>.stringResource(@StringRes resId: Int) = - ReadOnlyProperty { _, _ -> activity.getString(resId) } + ReadOnlyProperty { _, _ -> activity.getString(resId) } // The strings used for matching in these tests private val navigateUp by composeTestRule.stringResource(FeatureForyouR.string.navigate_up) diff --git a/app/src/main/kotlin/com/google/samples/apps/nowinandroid/MainActivity.kt b/app/src/main/kotlin/com/google/samples/apps/nowinandroid/MainActivity.kt index 7fe1bc674..0d03aa300 100644 --- a/app/src/main/kotlin/com/google/samples/apps/nowinandroid/MainActivity.kt +++ b/app/src/main/kotlin/com/google/samples/apps/nowinandroid/MainActivity.kt @@ -90,9 +90,7 @@ class MainActivity : ComponentActivity() { lifecycleScope.launch { lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) { viewModel.uiState - .onEach { - uiState = it - } + .onEach { uiState = it } .collect() } } diff --git a/app/src/main/kotlin/com/google/samples/apps/nowinandroid/di/JankStatsModule.kt b/app/src/main/kotlin/com/google/samples/apps/nowinandroid/di/JankStatsModule.kt index be64d057f..56d1b6e24 100644 --- a/app/src/main/kotlin/com/google/samples/apps/nowinandroid/di/JankStatsModule.kt +++ b/app/src/main/kotlin/com/google/samples/apps/nowinandroid/di/JankStatsModule.kt @@ -20,6 +20,7 @@ import android.app.Activity import android.util.Log import android.view.Window import androidx.metrics.performance.JankStats +import androidx.metrics.performance.JankStats.OnFrameListener import dagger.Module import dagger.Provides import dagger.hilt.InstallIn @@ -29,26 +30,20 @@ import dagger.hilt.android.components.ActivityComponent @InstallIn(ActivityComponent::class) object JankStatsModule { @Provides - fun providesOnFrameListener(): JankStats.OnFrameListener { - return JankStats.OnFrameListener { frameData -> - // Make sure to only log janky frames. - if (frameData.isJank) { - // We're currently logging this but would better report it to a backend. - Log.v("NiA Jank", frameData.toString()) - } + fun providesOnFrameListener(): OnFrameListener = OnFrameListener { frameData -> + // Make sure to only log janky frames. + if (frameData.isJank) { + // We're currently logging this but would better report it to a backend. + Log.v("NiA Jank", frameData.toString()) } } @Provides - fun providesWindow(activity: Activity): Window { - return activity.window - } + fun providesWindow(activity: Activity): Window = activity.window @Provides fun providesJankStats( window: Window, - frameListener: JankStats.OnFrameListener, - ): JankStats { - return JankStats.createAndTrack(window, frameListener) - } + frameListener: OnFrameListener, + ): JankStats = JankStats.createAndTrack(window, frameListener) } diff --git a/app/src/main/kotlin/com/google/samples/apps/nowinandroid/ui/NiaApp.kt b/app/src/main/kotlin/com/google/samples/apps/nowinandroid/ui/NiaApp.kt index aa85afebd..caefeab4d 100644 --- a/app/src/main/kotlin/com/google/samples/apps/nowinandroid/ui/NiaApp.kt +++ b/app/src/main/kotlin/com/google/samples/apps/nowinandroid/ui/NiaApp.kt @@ -97,9 +97,7 @@ fun NiaApp( ) { val shouldShowGradientBackground = appState.currentTopLevelDestination == TopLevelDestination.FOR_YOU - var showSettingsDialog by rememberSaveable { - mutableStateOf(false) - } + var showSettingsDialog by rememberSaveable { mutableStateOf(false) } NiaBackground { NiaGradientBackground( diff --git a/app/src/main/kotlin/com/google/samples/apps/nowinandroid/ui/NiaAppState.kt b/app/src/main/kotlin/com/google/samples/apps/nowinandroid/ui/NiaAppState.kt index 09e70069e..c652d08f1 100644 --- a/app/src/main/kotlin/com/google/samples/apps/nowinandroid/ui/NiaAppState.kt +++ b/app/src/main/kotlin/com/google/samples/apps/nowinandroid/ui/NiaAppState.kt @@ -164,9 +164,7 @@ class NiaAppState( } } - fun navigateToSearch() { - navController.navigateToSearch() - } + fun navigateToSearch() = navController.navigateToSearch() } /** diff --git a/benchmarks/src/main/kotlin/androidx/test/uiautomator/UiAutomatorHelpers.kt b/benchmarks/src/main/kotlin/androidx/test/uiautomator/UiAutomatorHelpers.kt index 85867b982..b0eb754c7 100644 --- a/benchmarks/src/main/kotlin/androidx/test/uiautomator/UiAutomatorHelpers.kt +++ b/benchmarks/src/main/kotlin/androidx/test/uiautomator/UiAutomatorHelpers.kt @@ -29,15 +29,11 @@ import androidx.test.uiautomator.HasChildrenOp.EXACTLY fun untilHasChildren( childCount: Int = 1, op: HasChildrenOp = AT_LEAST, -): UiObject2Condition { - return object : UiObject2Condition() { - override fun apply(element: UiObject2): Boolean { - return when (op) { - AT_LEAST -> element.childCount >= childCount - EXACTLY -> element.childCount == childCount - AT_MOST -> element.childCount <= childCount - } - } +): UiObject2Condition = object : UiObject2Condition() { + override fun apply(element: UiObject2): Boolean = when (op) { + AT_LEAST -> element.childCount >= childCount + EXACTLY -> element.childCount == childCount + AT_MOST -> element.childCount <= childCount } } diff --git a/benchmarks/src/main/kotlin/com/google/samples/apps/nowinandroid/baselineprofile/StartupBaselineProfile.kt b/benchmarks/src/main/kotlin/com/google/samples/apps/nowinandroid/baselineprofile/StartupBaselineProfile.kt index c5a88e1bd..d8128a670 100644 --- a/benchmarks/src/main/kotlin/com/google/samples/apps/nowinandroid/baselineprofile/StartupBaselineProfile.kt +++ b/benchmarks/src/main/kotlin/com/google/samples/apps/nowinandroid/baselineprofile/StartupBaselineProfile.kt @@ -16,6 +16,7 @@ package com.google.samples.apps.nowinandroid.baselineprofile +import androidx.benchmark.macro.MacrobenchmarkScope import androidx.benchmark.macro.junit4.BaselineProfileRule import com.google.samples.apps.nowinandroid.PACKAGE_NAME import com.google.samples.apps.nowinandroid.startActivityAndAllowNotifications @@ -30,11 +31,9 @@ class StartupBaselineProfile { @get:Rule val baselineProfileRule = BaselineProfileRule() @Test - fun generate() = - baselineProfileRule.collect( - PACKAGE_NAME, - includeInStartupProfile = true, - ) { - startActivityAndAllowNotifications() - } + fun generate() = baselineProfileRule.collect( + PACKAGE_NAME, + includeInStartupProfile = true, + profileBlock = MacrobenchmarkScope::startActivityAndAllowNotifications, + ) } diff --git a/build-logic/convention/src/main/kotlin/com/google/samples/apps/nowinandroid/PrintTestApks.kt b/build-logic/convention/src/main/kotlin/com/google/samples/apps/nowinandroid/PrintTestApks.kt index 6c08216cc..4928072fc 100644 --- a/build-logic/convention/src/main/kotlin/com/google/samples/apps/nowinandroid/PrintTestApks.kt +++ b/build-logic/convention/src/main/kotlin/com/google/samples/apps/nowinandroid/PrintTestApks.kt @@ -79,14 +79,12 @@ internal abstract class PrintApkLocationTask : DefaultTask() { fun taskAction() { val hasFiles = sources.orNull?.any { directory -> directory.asFileTree.files.any { - it.isFile && it.parentFile.path.contains("build${File.separator}generated").not() + it.isFile && "build${File.separator}generated" !in it.parentFile.path } } ?: throw RuntimeException("Cannot check androidTest sources") // Don't print APK location if there are no androidTest source files - if (!hasFiles) { - return - } + if (!hasFiles) return val builtArtifacts = builtArtifactsLoader.get().load(apkFolder.get()) ?: throw RuntimeException("Cannot load APKs") diff --git a/core/common/src/main/kotlin/com/google/samples/apps/nowinandroid/core/result/Result.kt b/core/common/src/main/kotlin/com/google/samples/apps/nowinandroid/core/result/Result.kt index 6ae12d634..22376d082 100644 --- a/core/common/src/main/kotlin/com/google/samples/apps/nowinandroid/core/result/Result.kt +++ b/core/common/src/main/kotlin/com/google/samples/apps/nowinandroid/core/result/Result.kt @@ -23,15 +23,10 @@ import kotlinx.coroutines.flow.onStart sealed interface Result { data class Success(val data: T) : Result - data class Error(val exception: Throwable? = null) : Result + data class Error(val exception: Throwable) : Result data object Loading : Result } -fun Flow.asResult(): Flow> { - return this - .map> { - Result.Success(it) - } - .onStart { emit(Result.Loading) } - .catch { emit(Result.Error(it)) } -} +fun Flow.asResult(): Flow> = map> { Result.Success(it) } + .onStart { emit(Result.Loading) } + .catch { emit(Result.Error(it)) } diff --git a/core/data/src/main/kotlin/com/google/samples/apps/nowinandroid/core/data/repository/DefaultRecentSearchRepository.kt b/core/data/src/main/kotlin/com/google/samples/apps/nowinandroid/core/data/repository/DefaultRecentSearchRepository.kt index 702c2dcd2..ca7e62853 100644 --- a/core/data/src/main/kotlin/com/google/samples/apps/nowinandroid/core/data/repository/DefaultRecentSearchRepository.kt +++ b/core/data/src/main/kotlin/com/google/samples/apps/nowinandroid/core/data/repository/DefaultRecentSearchRepository.kt @@ -39,9 +39,7 @@ class DefaultRecentSearchRepository @Inject constructor( override fun getRecentSearchQueries(limit: Int): Flow> = recentSearchQueryDao.getRecentSearchQueryEntities(limit).map { searchQueries -> - searchQueries.map { - it.asExternalModel() - } + searchQueries.map { it.asExternalModel() } } override suspend fun clearRecentSearches() = recentSearchQueryDao.clearRecentSearchQueries() diff --git a/core/data/src/main/kotlin/com/google/samples/apps/nowinandroid/core/data/repository/fake/FakeRecentSearchRepository.kt b/core/data/src/main/kotlin/com/google/samples/apps/nowinandroid/core/data/repository/fake/FakeRecentSearchRepository.kt index fc649f3ec..025b51f68 100644 --- a/core/data/src/main/kotlin/com/google/samples/apps/nowinandroid/core/data/repository/fake/FakeRecentSearchRepository.kt +++ b/core/data/src/main/kotlin/com/google/samples/apps/nowinandroid/core/data/repository/fake/FakeRecentSearchRepository.kt @@ -26,10 +26,10 @@ import javax.inject.Inject * Fake implementation of the [RecentSearchRepository] */ class FakeRecentSearchRepository @Inject constructor() : RecentSearchRepository { - override suspend fun insertOrReplaceRecentSearch(searchQuery: String) { /* no-op */ } + override suspend fun insertOrReplaceRecentSearch(searchQuery: String) = Unit override fun getRecentSearchQueries(limit: Int): Flow> = flowOf(emptyList()) - override suspend fun clearRecentSearches() { /* no-op */ } + override suspend fun clearRecentSearches() = Unit } diff --git a/core/data/src/main/kotlin/com/google/samples/apps/nowinandroid/core/data/repository/fake/FakeSearchContentsRepository.kt b/core/data/src/main/kotlin/com/google/samples/apps/nowinandroid/core/data/repository/fake/FakeSearchContentsRepository.kt index d15890a10..65cced452 100644 --- a/core/data/src/main/kotlin/com/google/samples/apps/nowinandroid/core/data/repository/fake/FakeSearchContentsRepository.kt +++ b/core/data/src/main/kotlin/com/google/samples/apps/nowinandroid/core/data/repository/fake/FakeSearchContentsRepository.kt @@ -27,7 +27,7 @@ import javax.inject.Inject */ class FakeSearchContentsRepository @Inject constructor() : SearchContentsRepository { - override suspend fun populateFtsData() { /* no-op */ } + override suspend fun populateFtsData() = Unit override fun searchContents(searchQuery: String): Flow = flowOf() override fun getSearchContentsCount(): Flow = flowOf(1) } diff --git a/core/data/src/main/kotlin/com/google/samples/apps/nowinandroid/core/data/repository/fake/FakeTopicsRepository.kt b/core/data/src/main/kotlin/com/google/samples/apps/nowinandroid/core/data/repository/fake/FakeTopicsRepository.kt index 1ab9c9353..0eefc8451 100644 --- a/core/data/src/main/kotlin/com/google/samples/apps/nowinandroid/core/data/repository/fake/FakeTopicsRepository.kt +++ b/core/data/src/main/kotlin/com/google/samples/apps/nowinandroid/core/data/repository/fake/FakeTopicsRepository.kt @@ -55,9 +55,8 @@ class FakeTopicsRepository @Inject constructor( ) }.flowOn(ioDispatcher) - override fun getTopic(id: String): Flow { - return getTopics().map { it.first { topic -> topic.id == id } } - } + override fun getTopic(id: String): Flow = getTopics() + .map { it.first { topic -> topic.id == id } } override suspend fun syncWith(synchronizer: Synchronizer) = true } diff --git a/core/data/src/test/kotlin/com/google/samples/apps/nowinandroid/core/data/CompositeUserNewsResourceRepositoryTest.kt b/core/data/src/test/kotlin/com/google/samples/apps/nowinandroid/core/data/CompositeUserNewsResourceRepositoryTest.kt index 743fb7e5c..05811f4be 100644 --- a/core/data/src/test/kotlin/com/google/samples/apps/nowinandroid/core/data/CompositeUserNewsResourceRepositoryTest.kt +++ b/core/data/src/test/kotlin/com/google/samples/apps/nowinandroid/core/data/CompositeUserNewsResourceRepositoryTest.kt @@ -82,7 +82,7 @@ class CompositeUserNewsResourceRepositoryTest { // Check that only news resources with the given topic id are returned. assertEquals( sampleNewsResources - .filter { it.topics.contains(sampleTopic1) } + .filter { sampleTopic1 in it.topics } .mapToUserNewsResources(emptyUserData), userNewsResources.first(), ) @@ -104,7 +104,7 @@ class CompositeUserNewsResourceRepositoryTest { // Check that only news resources with the given topic id are returned. assertEquals( sampleNewsResources - .filter { it.topics.contains(sampleTopic1) } + .filter { sampleTopic1 in it.topics } .mapToUserNewsResources(userData), userNewsResources.first(), ) diff --git a/core/data/src/test/kotlin/com/google/samples/apps/nowinandroid/core/data/UserNewsResourceTest.kt b/core/data/src/test/kotlin/com/google/samples/apps/nowinandroid/core/data/UserNewsResourceTest.kt index a21dee863..c7dfd99d0 100644 --- a/core/data/src/test/kotlin/com/google/samples/apps/nowinandroid/core/data/UserNewsResourceTest.kt +++ b/core/data/src/test/kotlin/com/google/samples/apps/nowinandroid/core/data/UserNewsResourceTest.kt @@ -91,14 +91,14 @@ class UserNewsResourceTest { // Construct the expected FollowableTopic. val followableTopic = FollowableTopic( topic = topic, - isFollowed = userData.followedTopics.contains(topic.id), + isFollowed = topic.id in userData.followedTopics, ) assertTrue(userNewsResource.followableTopics.contains(followableTopic)) } // Check that the saved flag is set correctly. assertEquals( - userData.bookmarkedNewsResources.contains(newsResource1.id), + newsResource1.id in userData.bookmarkedNewsResources, userNewsResource.isSaved, ) } diff --git a/core/data/src/test/kotlin/com/google/samples/apps/nowinandroid/core/data/testdoubles/TestNewsResourceDao.kt b/core/data/src/test/kotlin/com/google/samples/apps/nowinandroid/core/data/testdoubles/TestNewsResourceDao.kt index 6e5c45305..dc4b78e01 100644 --- a/core/data/src/test/kotlin/com/google/samples/apps/nowinandroid/core/data/testdoubles/TestNewsResourceDao.kt +++ b/core/data/src/test/kotlin/com/google/samples/apps/nowinandroid/core/data/testdoubles/TestNewsResourceDao.kt @@ -34,9 +34,7 @@ val nonPresentInterestsIds = setOf("2") */ class TestNewsResourceDao : NewsResourceDao { - private var entitiesStateFlow = MutableStateFlow( - emptyList(), - ) + private val entitiesStateFlow = MutableStateFlow(emptyList()) internal var topicCrossReferences: List = listOf() @@ -131,7 +129,7 @@ class TestNewsResourceDao : NewsResourceDao { override suspend fun deleteNewsResources(ids: List) { val idSet = ids.toSet() entitiesStateFlow.update { entities -> - entities.filterNot { idSet.contains(it.id) } + entities.filterNot { it.id in idSet } } } } diff --git a/core/data/src/test/kotlin/com/google/samples/apps/nowinandroid/core/data/testdoubles/TestNiaNetworkDataSource.kt b/core/data/src/test/kotlin/com/google/samples/apps/nowinandroid/core/data/testdoubles/TestNiaNetworkDataSource.kt index 8e248a3aa..7f9a69959 100644 --- a/core/data/src/test/kotlin/com/google/samples/apps/nowinandroid/core/data/testdoubles/TestNiaNetworkDataSource.kt +++ b/core/data/src/test/kotlin/com/google/samples/apps/nowinandroid/core/data/testdoubles/TestNiaNetworkDataSource.kt @@ -91,11 +91,10 @@ class TestNiaNetworkDataSource : NiaNetworkDataSource { } } -fun List.after(version: Int?): List = - when (version) { - null -> this - else -> this.filter { it.changeListVersion > version } - } +fun List.after(version: Int?): List = when (version) { + null -> this + else -> filter { it.changeListVersion > version } +} /** * Return items from [this] whose id defined by [idGetter] is in [ids] if [ids] is not null @@ -105,7 +104,7 @@ private fun List.matchIds( idGetter: (T) -> String, ) = when (ids) { null -> this - else -> ids.toSet().let { idSet -> this.filter { idSet.contains(idGetter(it)) } } + else -> ids.toSet().let { idSet -> filter { idGetter(it) in idSet } } } /** diff --git a/core/data/src/test/kotlin/com/google/samples/apps/nowinandroid/core/data/testdoubles/TestTopicDao.kt b/core/data/src/test/kotlin/com/google/samples/apps/nowinandroid/core/data/testdoubles/TestTopicDao.kt index a52cc86f6..d217f55d7 100644 --- a/core/data/src/test/kotlin/com/google/samples/apps/nowinandroid/core/data/testdoubles/TestTopicDao.kt +++ b/core/data/src/test/kotlin/com/google/samples/apps/nowinandroid/core/data/testdoubles/TestTopicDao.kt @@ -28,20 +28,15 @@ import kotlinx.coroutines.flow.update */ class TestTopicDao : TopicDao { - private var entitiesStateFlow = MutableStateFlow( - emptyList(), - ) + private val entitiesStateFlow = MutableStateFlow(emptyList()) - override fun getTopicEntity(topicId: String): Flow { + override fun getTopicEntity(topicId: String): Flow = throw NotImplementedError("Unused in tests") - } - override fun getTopicEntities(): Flow> = - entitiesStateFlow + override fun getTopicEntities(): Flow> = entitiesStateFlow override fun getTopicEntities(ids: Set): Flow> = - getTopicEntities() - .map { topics -> topics.filter { it.id in ids } } + getTopicEntities().map { topics -> topics.filter { it.id in ids } } override suspend fun getOneOffTopicEntities(): List = emptyList() @@ -55,15 +50,11 @@ class TestTopicDao : TopicDao { override suspend fun upsertTopics(entities: List) { // Overwrite old values with new values - entitiesStateFlow.update { oldValues -> - (entities + oldValues).distinctBy(TopicEntity::id) - } + entitiesStateFlow.update { oldValues -> (entities + oldValues).distinctBy(TopicEntity::id) } } override suspend fun deleteTopics(ids: List) { val idSet = ids.toSet() - entitiesStateFlow.update { entities -> - entities.filterNot { idSet.contains(it.id) } - } + entitiesStateFlow.update { entities -> entities.filterNot { it.id in idSet } } } } diff --git a/core/datastore/src/main/kotlin/com/google/samples/apps/nowinandroid/core/datastore/ListToMapMigration.kt b/core/datastore/src/main/kotlin/com/google/samples/apps/nowinandroid/core/datastore/ListToMapMigration.kt index 5bff23340..c1e49a44b 100644 --- a/core/datastore/src/main/kotlin/com/google/samples/apps/nowinandroid/core/datastore/ListToMapMigration.kt +++ b/core/datastore/src/main/kotlin/com/google/samples/apps/nowinandroid/core/datastore/ListToMapMigration.kt @@ -52,7 +52,6 @@ object ListToMapMigration : DataMigration { hasDoneListToMapMigration = true } - override suspend fun shouldMigrate(currentData: UserPreferences): Boolean { - return !currentData.hasDoneListToMapMigration - } + override suspend fun shouldMigrate(currentData: UserPreferences): Boolean = + !currentData.hasDoneListToMapMigration } diff --git a/core/datastore/src/main/kotlin/com/google/samples/apps/nowinandroid/core/datastore/NiaPreferencesDataSource.kt b/core/datastore/src/main/kotlin/com/google/samples/apps/nowinandroid/core/datastore/NiaPreferencesDataSource.kt index 6dc7725c1..9a76a75a1 100644 --- a/core/datastore/src/main/kotlin/com/google/samples/apps/nowinandroid/core/datastore/NiaPreferencesDataSource.kt +++ b/core/datastore/src/main/kotlin/com/google/samples/apps/nowinandroid/core/datastore/NiaPreferencesDataSource.kt @@ -103,9 +103,7 @@ class NiaPreferencesDataSource @Inject constructor( suspend fun setDynamicColorPreference(useDynamicColor: Boolean) { userPreferences.updateData { - it.copy { - this.useDynamicColor = useDynamicColor - } + it.copy { this.useDynamicColor = useDynamicColor } } } @@ -190,9 +188,7 @@ class NiaPreferencesDataSource @Inject constructor( suspend fun setShouldHideOnboarding(shouldHideOnboarding: Boolean) { userPreferences.updateData { - it.copy { - this.shouldHideOnboarding = shouldHideOnboarding - } + it.copy { this.shouldHideOnboarding = shouldHideOnboarding } } } } diff --git a/core/designsystem/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/core/designsystem/ThemeTest.kt b/core/designsystem/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/core/designsystem/ThemeTest.kt index b10df053c..92e94f4e5 100644 --- a/core/designsystem/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/core/designsystem/ThemeTest.kt +++ b/core/designsystem/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/core/designsystem/ThemeTest.kt @@ -16,7 +16,8 @@ package com.google.samples.apps.nowinandroid.core.designsystem -import android.os.Build +import android.os.Build.VERSION.SDK_INT +import android.os.Build.VERSION_CODES import androidx.compose.material3.ColorScheme import androidx.compose.material3.MaterialTheme import androidx.compose.material3.dynamicDarkColorScheme @@ -219,60 +220,41 @@ class ThemeTest { } @Composable - private fun dynamicLightColorSchemeWithFallback(): ColorScheme { - return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { - dynamicLightColorScheme(LocalContext.current) - } else { - LightDefaultColorScheme - } + private fun dynamicLightColorSchemeWithFallback(): ColorScheme = when { + SDK_INT >= VERSION_CODES.S -> dynamicLightColorScheme(LocalContext.current) + else -> LightDefaultColorScheme } @Composable - private fun dynamicDarkColorSchemeWithFallback(): ColorScheme { - return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { - dynamicDarkColorScheme(LocalContext.current) - } else { - DarkDefaultColorScheme - } + private fun dynamicDarkColorSchemeWithFallback(): ColorScheme = when { + SDK_INT >= VERSION_CODES.S -> dynamicDarkColorScheme(LocalContext.current) + else -> DarkDefaultColorScheme } - private fun emptyGradientColors(colorScheme: ColorScheme): GradientColors { - return GradientColors(container = colorScheme.surfaceColorAtElevation(2.dp)) - } + private fun emptyGradientColors(colorScheme: ColorScheme): GradientColors = + GradientColors(container = colorScheme.surfaceColorAtElevation(2.dp)) - private fun defaultGradientColors(colorScheme: ColorScheme): GradientColors { - return GradientColors( - top = colorScheme.inverseOnSurface, - bottom = colorScheme.primaryContainer, - container = colorScheme.surface, - ) - } + private fun defaultGradientColors(colorScheme: ColorScheme): GradientColors = GradientColors( + top = colorScheme.inverseOnSurface, + bottom = colorScheme.primaryContainer, + container = colorScheme.surface, + ) - private fun dynamicGradientColorsWithFallback(colorScheme: ColorScheme): GradientColors { - return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { - emptyGradientColors(colorScheme) - } else { - defaultGradientColors(colorScheme) - } + private fun dynamicGradientColorsWithFallback(colorScheme: ColorScheme): GradientColors = when { + SDK_INT >= VERSION_CODES.S -> emptyGradientColors(colorScheme) + else -> defaultGradientColors(colorScheme) } - private fun defaultBackgroundTheme(colorScheme: ColorScheme): BackgroundTheme { - return BackgroundTheme( - color = colorScheme.surface, - tonalElevation = 2.dp, - ) - } + private fun defaultBackgroundTheme(colorScheme: ColorScheme): BackgroundTheme = BackgroundTheme( + color = colorScheme.surface, + tonalElevation = 2.dp, + ) - private fun defaultTintTheme(): TintTheme { - return TintTheme() - } + private fun defaultTintTheme(): TintTheme = TintTheme() - private fun dynamicTintThemeWithFallback(colorScheme: ColorScheme): TintTheme { - return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { - TintTheme(colorScheme.primary) - } else { - TintTheme() - } + private fun dynamicTintThemeWithFallback(colorScheme: ColorScheme): TintTheme = when { + SDK_INT >= VERSION_CODES.S -> TintTheme(colorScheme.primary) + else -> TintTheme() } /** diff --git a/core/designsystem/src/main/kotlin/com/google/samples/apps/nowinandroid/core/designsystem/component/DynamicAsyncImage.kt b/core/designsystem/src/main/kotlin/com/google/samples/apps/nowinandroid/core/designsystem/component/DynamicAsyncImage.kt index cc352107b..1092ba4c9 100644 --- a/core/designsystem/src/main/kotlin/com/google/samples/apps/nowinandroid/core/designsystem/component/DynamicAsyncImage.kt +++ b/core/designsystem/src/main/kotlin/com/google/samples/apps/nowinandroid/core/designsystem/component/DynamicAsyncImage.kt @@ -28,6 +28,7 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color.Companion.Unspecified import androidx.compose.ui.graphics.ColorFilter import androidx.compose.ui.graphics.painter.Painter import androidx.compose.ui.layout.ContentScale @@ -79,7 +80,7 @@ fun DynamicAsyncImage( contentScale = ContentScale.Crop, painter = if (isError.not() && !isLocalInspection) imageLoader else placeholder, contentDescription = contentDescription, - colorFilter = if (iconTint != null) ColorFilter.tint(iconTint) else null, + colorFilter = if (iconTint != Unspecified) ColorFilter.tint(iconTint) else null, ) } } diff --git a/core/designsystem/src/main/kotlin/com/google/samples/apps/nowinandroid/core/designsystem/component/TopAppBar.kt b/core/designsystem/src/main/kotlin/com/google/samples/apps/nowinandroid/core/designsystem/component/TopAppBar.kt index 99f935d2a..9c716918a 100644 --- a/core/designsystem/src/main/kotlin/com/google/samples/apps/nowinandroid/core/designsystem/component/TopAppBar.kt +++ b/core/designsystem/src/main/kotlin/com/google/samples/apps/nowinandroid/core/designsystem/component/TopAppBar.kt @@ -40,9 +40,9 @@ import com.google.samples.apps.nowinandroid.core.designsystem.icon.NiaIcons fun NiaTopAppBar( @StringRes titleRes: Int, navigationIcon: ImageVector, - navigationIconContentDescription: String?, + navigationIconContentDescription: String, actionIcon: ImageVector, - actionIconContentDescription: String?, + actionIconContentDescription: String, modifier: Modifier = Modifier, colors: TopAppBarColors = TopAppBarDefaults.centerAlignedTopAppBarColors(), onNavigationClick: () -> Unit = {}, diff --git a/core/designsystem/src/main/kotlin/com/google/samples/apps/nowinandroid/core/designsystem/component/scrollbar/ScrollbarExt.kt b/core/designsystem/src/main/kotlin/com/google/samples/apps/nowinandroid/core/designsystem/component/scrollbar/ScrollbarExt.kt index 7a0282bf7..0984317b9 100644 --- a/core/designsystem/src/main/kotlin/com/google/samples/apps/nowinandroid/core/designsystem/component/scrollbar/ScrollbarExt.kt +++ b/core/designsystem/src/main/kotlin/com/google/samples/apps/nowinandroid/core/designsystem/component/scrollbar/ScrollbarExt.kt @@ -229,10 +229,5 @@ fun LazyStaggeredGridState.scrollbarState( .collect { value = it } }.value -private inline fun List.floatSumOf(selector: (T) -> Float): Float { - var sum = 0f - for (element in this) { - sum += selector(element) - } - return sum -} +private inline fun List.floatSumOf(selector: (T) -> Float): Float = + fold(0f) { acc, it -> acc + selector(it) } diff --git a/core/designsystem/src/main/kotlin/com/google/samples/apps/nowinandroid/core/designsystem/theme/Tint.kt b/core/designsystem/src/main/kotlin/com/google/samples/apps/nowinandroid/core/designsystem/theme/Tint.kt index 848c8d8f5..75ab3a8f6 100644 --- a/core/designsystem/src/main/kotlin/com/google/samples/apps/nowinandroid/core/designsystem/theme/Tint.kt +++ b/core/designsystem/src/main/kotlin/com/google/samples/apps/nowinandroid/core/designsystem/theme/Tint.kt @@ -25,7 +25,7 @@ import androidx.compose.ui.graphics.Color */ @Immutable data class TintTheme( - val iconTint: Color? = null, + val iconTint: Color = Color.Unspecified, ) /** diff --git a/core/domain/src/main/kotlin/com/google/samples/apps/nowinandroid/core/domain/GetFollowableTopicsUseCase.kt b/core/domain/src/main/kotlin/com/google/samples/apps/nowinandroid/core/domain/GetFollowableTopicsUseCase.kt index c3c045d44..0167a3192 100644 --- a/core/domain/src/main/kotlin/com/google/samples/apps/nowinandroid/core/domain/GetFollowableTopicsUseCase.kt +++ b/core/domain/src/main/kotlin/com/google/samples/apps/nowinandroid/core/domain/GetFollowableTopicsUseCase.kt @@ -37,22 +37,20 @@ class GetFollowableTopicsUseCase @Inject constructor( * * @param sortBy - the field used to sort the topics. Default NONE = no sorting. */ - operator fun invoke(sortBy: TopicSortField = NONE): Flow> { - return combine( - userDataRepository.userData, - topicsRepository.getTopics(), - ) { userData, topics -> - val followedTopics = topics - .map { topic -> - FollowableTopic( - topic = topic, - isFollowed = topic.id in userData.followedTopics, - ) - } - when (sortBy) { - NAME -> followedTopics.sortedBy { it.topic.name } - else -> followedTopics + operator fun invoke(sortBy: TopicSortField = NONE): Flow> = combine( + userDataRepository.userData, + topicsRepository.getTopics(), + ) { userData, topics -> + val followedTopics = topics + .map { topic -> + FollowableTopic( + topic = topic, + isFollowed = topic.id in userData.followedTopics, + ) } + when (sortBy) { + NAME -> followedTopics.sortedBy { it.topic.name } + else -> followedTopics } } } diff --git a/core/model/src/main/kotlin/com/google/samples/apps/nowinandroid/core/model/data/UserNewsResource.kt b/core/model/src/main/kotlin/com/google/samples/apps/nowinandroid/core/model/data/UserNewsResource.kt index 4ea830022..a56bbcb8d 100644 --- a/core/model/src/main/kotlin/com/google/samples/apps/nowinandroid/core/model/data/UserNewsResource.kt +++ b/core/model/src/main/kotlin/com/google/samples/apps/nowinandroid/core/model/data/UserNewsResource.kt @@ -45,14 +45,13 @@ data class UserNewsResource internal constructor( followableTopics = newsResource.topics.map { topic -> FollowableTopic( topic = topic, - isFollowed = userData.followedTopics.contains(topic.id), + isFollowed = topic.id in userData.followedTopics, ) }, - isSaved = userData.bookmarkedNewsResources.contains(newsResource.id), - hasBeenViewed = userData.viewedNewsResources.contains(newsResource.id), + isSaved = newsResource.id in userData.bookmarkedNewsResources, + hasBeenViewed = newsResource.id in userData.viewedNewsResources, ) } -fun List.mapToUserNewsResources(userData: UserData): List { - return map { UserNewsResource(it, userData) } -} +fun List.mapToUserNewsResources(userData: UserData): List = + map { UserNewsResource(it, userData) } diff --git a/core/notifications/src/main/kotlin/com/google/samples/apps/nowinandroid/core/notifications/SystemTrayNotifier.kt b/core/notifications/src/main/kotlin/com/google/samples/apps/nowinandroid/core/notifications/SystemTrayNotifier.kt index 7e74f819c..fbc60baf1 100644 --- a/core/notifications/src/main/kotlin/com/google/samples/apps/nowinandroid/core/notifications/SystemTrayNotifier.kt +++ b/core/notifications/src/main/kotlin/com/google/samples/apps/nowinandroid/core/notifications/SystemTrayNotifier.kt @@ -24,10 +24,10 @@ import android.app.PendingIntent import android.content.ComponentName import android.content.Context import android.content.Intent -import android.content.pm.PackageManager +import android.content.pm.PackageManager.PERMISSION_GRANTED import android.os.Build.VERSION import android.os.Build.VERSION_CODES -import androidx.core.app.ActivityCompat +import androidx.core.app.ActivityCompat.checkSelfPermission import androidx.core.app.NotificationCompat import androidx.core.app.NotificationCompat.InboxStyle import androidx.core.app.NotificationManagerCompat @@ -57,30 +57,24 @@ class SystemTrayNotifier @Inject constructor( override fun postNewsNotifications( newsResources: List, ) = with(context) { - if (ActivityCompat.checkSelfPermission( - this, - permission.POST_NOTIFICATIONS, - ) != PackageManager.PERMISSION_GRANTED - ) { + if (checkSelfPermission(this, permission.POST_NOTIFICATIONS) != PERMISSION_GRANTED) { return } - val truncatedNewsResources = newsResources - .take(MAX_NUM_NOTIFICATIONS) + val truncatedNewsResources = newsResources.take(MAX_NUM_NOTIFICATIONS) - val newsNotifications = truncatedNewsResources - .map { newsResource -> - createNewsNotification { - setSmallIcon( - com.google.samples.apps.nowinandroid.core.common.R.drawable.ic_nia_notification, - ) - .setContentTitle(newsResource.title) - .setContentText(newsResource.content) - .setContentIntent(newsPendingIntent(newsResource)) - .setGroup(NEWS_NOTIFICATION_GROUP) - .setAutoCancel(true) - } + val newsNotifications = truncatedNewsResources.map { newsResource -> + createNewsNotification { + setSmallIcon( + com.google.samples.apps.nowinandroid.core.common.R.drawable.ic_nia_notification, + ) + .setContentTitle(newsResource.title) + .setContentText(newsResource.content) + .setContentIntent(newsPendingIntent(newsResource)) + .setGroup(NEWS_NOTIFICATION_GROUP) + .setAutoCancel(true) } + } val summaryNotification = createNewsNotification { val title = getString( R.string.news_notification_group_summary, @@ -117,9 +111,7 @@ class SystemTrayNotifier @Inject constructor( newsResources: List, title: String, ): InboxStyle = newsResources - .fold(InboxStyle()) { inboxStyle, newsResource -> - inboxStyle.addLine(newsResource.title) - } + .fold(InboxStyle()) { inboxStyle, newsResource -> inboxStyle.addLine(newsResource.title) } .setBigContentTitle(title) .setSummaryText(title) } diff --git a/core/testing/src/main/kotlin/com/google/samples/apps/nowinandroid/core/testing/NiaTestRunner.kt b/core/testing/src/main/kotlin/com/google/samples/apps/nowinandroid/core/testing/NiaTestRunner.kt index 30254a617..9b3b185df 100644 --- a/core/testing/src/main/kotlin/com/google/samples/apps/nowinandroid/core/testing/NiaTestRunner.kt +++ b/core/testing/src/main/kotlin/com/google/samples/apps/nowinandroid/core/testing/NiaTestRunner.kt @@ -25,7 +25,6 @@ import dagger.hilt.android.testing.HiltTestApplication * A custom runner to set up the instrumented application class for tests. */ class NiaTestRunner : AndroidJUnitRunner() { - override fun newApplication(cl: ClassLoader?, name: String?, context: Context?): Application { - return super.newApplication(cl, HiltTestApplication::class.java.name, context) - } + override fun newApplication(cl: ClassLoader, name: String, context: Context): Application = + super.newApplication(cl, HiltTestApplication::class.java.name, context) } diff --git a/core/testing/src/main/kotlin/com/google/samples/apps/nowinandroid/core/testing/repository/TestNewsRepository.kt b/core/testing/src/main/kotlin/com/google/samples/apps/nowinandroid/core/testing/repository/TestNewsRepository.kt index d0bfd21a1..ef065a9f8 100644 --- a/core/testing/src/main/kotlin/com/google/samples/apps/nowinandroid/core/testing/repository/TestNewsRepository.kt +++ b/core/testing/src/main/kotlin/com/google/samples/apps/nowinandroid/core/testing/repository/TestNewsRepository.kt @@ -43,9 +43,7 @@ class TestNewsRepository : NewsRepository { } } query.filterNewsIds?.let { filterNewsIds -> - result = newsResources.filter { - filterNewsIds.contains(it.id) - } + result = newsResources.filter { it.id in filterNewsIds } } result } diff --git a/core/testing/src/main/kotlin/com/google/samples/apps/nowinandroid/core/testing/repository/TestRecentSearchRepository.kt b/core/testing/src/main/kotlin/com/google/samples/apps/nowinandroid/core/testing/repository/TestRecentSearchRepository.kt index 961473401..f700bdc31 100644 --- a/core/testing/src/main/kotlin/com/google/samples/apps/nowinandroid/core/testing/repository/TestRecentSearchRepository.kt +++ b/core/testing/src/main/kotlin/com/google/samples/apps/nowinandroid/core/testing/repository/TestRecentSearchRepository.kt @@ -32,7 +32,5 @@ class TestRecentSearchRepository : RecentSearchRepository { cachedRecentSearches.add(RecentSearchQuery(searchQuery)) } - override suspend fun clearRecentSearches() { - cachedRecentSearches.clear() - } + override suspend fun clearRecentSearches() = cachedRecentSearches.clear() } diff --git a/core/testing/src/main/kotlin/com/google/samples/apps/nowinandroid/core/testing/repository/TestSearchContentsRepository.kt b/core/testing/src/main/kotlin/com/google/samples/apps/nowinandroid/core/testing/repository/TestSearchContentsRepository.kt index 2aa54e463..9b6151449 100644 --- a/core/testing/src/main/kotlin/com/google/samples/apps/nowinandroid/core/testing/repository/TestSearchContentsRepository.kt +++ b/core/testing/src/main/kotlin/com/google/samples/apps/nowinandroid/core/testing/repository/TestSearchContentsRepository.kt @@ -29,18 +29,15 @@ class TestSearchContentsRepository : SearchContentsRepository { private val cachedTopics: MutableList = mutableListOf() private val cachedNewsResources: MutableList = mutableListOf() - override suspend fun populateFtsData() { /* no-op */ } + override suspend fun populateFtsData() = Unit override fun searchContents(searchQuery: String): Flow = flowOf( SearchResult( topics = cachedTopics.filter { - it.name.contains(searchQuery) || - it.shortDescription.contains(searchQuery) || - it.longDescription.contains(searchQuery) + searchQuery in it.name || searchQuery in it.shortDescription || searchQuery in it.longDescription }, newsResources = cachedNewsResources.filter { - it.content.contains(searchQuery) || - it.title.contains(searchQuery) + searchQuery in it.content || searchQuery in it.title }, ), ) diff --git a/core/testing/src/main/kotlin/com/google/samples/apps/nowinandroid/core/testing/repository/TestTopicsRepository.kt b/core/testing/src/main/kotlin/com/google/samples/apps/nowinandroid/core/testing/repository/TestTopicsRepository.kt index a95469d83..ddccbbe35 100644 --- a/core/testing/src/main/kotlin/com/google/samples/apps/nowinandroid/core/testing/repository/TestTopicsRepository.kt +++ b/core/testing/src/main/kotlin/com/google/samples/apps/nowinandroid/core/testing/repository/TestTopicsRepository.kt @@ -33,9 +33,8 @@ class TestTopicsRepository : TopicsRepository { override fun getTopics(): Flow> = topicsFlow - override fun getTopic(id: String): Flow { - return topicsFlow.map { topics -> topics.find { it.id == id }!! } - } + override fun getTopic(id: String): Flow = + topicsFlow.map { topics -> topics.find { it.id == id }!! } /** * A test-only API to allow controlling the list of topics from tests. diff --git a/core/testing/src/main/kotlin/com/google/samples/apps/nowinandroid/core/testing/util/MainDispatcherRule.kt b/core/testing/src/main/kotlin/com/google/samples/apps/nowinandroid/core/testing/util/MainDispatcherRule.kt index 28155f5ad..666c4edd4 100644 --- a/core/testing/src/main/kotlin/com/google/samples/apps/nowinandroid/core/testing/util/MainDispatcherRule.kt +++ b/core/testing/src/main/kotlin/com/google/samples/apps/nowinandroid/core/testing/util/MainDispatcherRule.kt @@ -32,11 +32,7 @@ import org.junit.runner.Description class MainDispatcherRule( private val testDispatcher: TestDispatcher = UnconfinedTestDispatcher(), ) : TestWatcher() { - override fun starting(description: Description) { - Dispatchers.setMain(testDispatcher) - } + override fun starting(description: Description) = Dispatchers.setMain(testDispatcher) - override fun finished(description: Description) { - Dispatchers.resetMain() - } + override fun finished(description: Description) = Dispatchers.resetMain() } diff --git a/core/testing/src/main/kotlin/com/google/samples/apps/nowinandroid/core/testing/util/TestAnalyticsHelper.kt b/core/testing/src/main/kotlin/com/google/samples/apps/nowinandroid/core/testing/util/TestAnalyticsHelper.kt index 005784c21..5f72d30e6 100644 --- a/core/testing/src/main/kotlin/com/google/samples/apps/nowinandroid/core/testing/util/TestAnalyticsHelper.kt +++ b/core/testing/src/main/kotlin/com/google/samples/apps/nowinandroid/core/testing/util/TestAnalyticsHelper.kt @@ -26,5 +26,5 @@ class TestAnalyticsHelper : AnalyticsHelper { events.add(event) } - fun hasLogged(event: AnalyticsEvent) = events.contains(event) + fun hasLogged(event: AnalyticsEvent) = event in events } diff --git a/core/testing/src/main/kotlin/com/google/samples/apps/nowinandroid/core/testing/util/TestSyncManager.kt b/core/testing/src/main/kotlin/com/google/samples/apps/nowinandroid/core/testing/util/TestSyncManager.kt index 999b67195..ff1e2fdd9 100644 --- a/core/testing/src/main/kotlin/com/google/samples/apps/nowinandroid/core/testing/util/TestSyncManager.kt +++ b/core/testing/src/main/kotlin/com/google/samples/apps/nowinandroid/core/testing/util/TestSyncManager.kt @@ -26,9 +26,7 @@ class TestSyncManager : SyncManager { override val isSyncing: Flow = syncStatusFlow - override fun requestSync() { - TODO("Not yet implemented") - } + override fun requestSync(): Unit = TODO("Not yet implemented") /** * A test-only API to set the sync status from tests. diff --git a/core/ui/src/main/kotlin/com/google/samples/apps/nowinandroid/core/ui/JankStatsExtensions.kt b/core/ui/src/main/kotlin/com/google/samples/apps/nowinandroid/core/ui/JankStatsExtensions.kt index c9fee1ac8..ef3de1059 100644 --- a/core/ui/src/main/kotlin/com/google/samples/apps/nowinandroid/core/ui/JankStatsExtensions.kt +++ b/core/ui/src/main/kotlin/com/google/samples/apps/nowinandroid/core/ui/JankStatsExtensions.kt @@ -50,7 +50,7 @@ fun rememberMetricsStateHolder(): Holder { */ @Composable fun TrackJank( - vararg keys: Any?, + vararg keys: Any, reportMetric: suspend CoroutineScope.(state: Holder) -> Unit, ) { val metrics = rememberMetricsStateHolder() @@ -65,7 +65,7 @@ fun TrackJank( */ @Composable fun TrackDisposableJank( - vararg keys: Any?, + vararg keys: Any, reportMetric: DisposableEffectScope.(state: Holder) -> DisposableEffectResult, ) { val metrics = rememberMetricsStateHolder() diff --git a/core/ui/src/main/kotlin/com/google/samples/apps/nowinandroid/core/ui/NewsFeed.kt b/core/ui/src/main/kotlin/com/google/samples/apps/nowinandroid/core/ui/NewsFeed.kt index e2904afc3..7264c7b14 100644 --- a/core/ui/src/main/kotlin/com/google/samples/apps/nowinandroid/core/ui/NewsFeed.kt +++ b/core/ui/src/main/kotlin/com/google/samples/apps/nowinandroid/core/ui/NewsFeed.kt @@ -64,9 +64,7 @@ fun LazyStaggeredGridScope.newsFeed( key = { it.id }, contentType = { "newsFeedItem" }, ) { userNewsResource -> - val resourceUrl by remember { - mutableStateOf(Uri.parse(userNewsResource.url)) - } + val resourceUrl by remember { mutableStateOf(Uri.parse(userNewsResource.url)) } val context = LocalContext.current val analyticsHelper = LocalAnalyticsHelper.current val backgroundColor = MaterialTheme.colorScheme.background.toArgb() diff --git a/feature/bookmarks/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/bookmarks/BookmarksScreen.kt b/feature/bookmarks/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/bookmarks/BookmarksScreen.kt index 7d51c6e84..1fa429d21 100644 --- a/feature/bookmarks/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/bookmarks/BookmarksScreen.kt +++ b/feature/bookmarks/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/bookmarks/BookmarksScreen.kt @@ -47,6 +47,7 @@ import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.ColorFilter import androidx.compose.ui.platform.LocalLifecycleOwner import androidx.compose.ui.platform.testTag @@ -237,7 +238,7 @@ private fun EmptyState(modifier: Modifier = Modifier) { Image( modifier = Modifier.fillMaxWidth(), painter = painterResource(id = R.drawable.img_empty_bookmarks), - colorFilter = if (iconTint != null) ColorFilter.tint(iconTint) else null, + colorFilter = if (iconTint != Color.Unspecified) ColorFilter.tint(iconTint) else null, contentDescription = null, ) diff --git a/feature/bookmarks/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/bookmarks/navigation/BookmarksNavigation.kt b/feature/bookmarks/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/bookmarks/navigation/BookmarksNavigation.kt index ebcde4ab1..aa8237da4 100644 --- a/feature/bookmarks/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/bookmarks/navigation/BookmarksNavigation.kt +++ b/feature/bookmarks/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/bookmarks/navigation/BookmarksNavigation.kt @@ -24,7 +24,7 @@ import com.google.samples.apps.nowinandroid.feature.bookmarks.BookmarksRoute const val bookmarksRoute = "bookmarks_route" -fun NavController.navigateToBookmarks(navOptions: NavOptions? = null) { +fun NavController.navigateToBookmarks(navOptions: NavOptions) { this.navigate(bookmarksRoute, navOptions) } diff --git a/feature/foryou/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/foryou/navigation/ForYouNavigation.kt b/feature/foryou/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/foryou/navigation/ForYouNavigation.kt index 705495cc2..ca606161d 100644 --- a/feature/foryou/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/foryou/navigation/ForYouNavigation.kt +++ b/feature/foryou/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/foryou/navigation/ForYouNavigation.kt @@ -30,7 +30,7 @@ const val forYouNavigationRoute = "for_you_route/{$LINKED_NEWS_RESOURCE_ID}" private const val DEEP_LINK_URI_PATTERN = "https://www.nowinandroid.apps.samples.google.com/foryou/{$LINKED_NEWS_RESOURCE_ID}" -fun NavController.navigateToForYou(navOptions: NavOptions? = null) { +fun NavController.navigateToForYou(navOptions: NavOptions) { this.navigate(forYouNavigationRoute, navOptions) } diff --git a/feature/interests/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/interests/navigation/InterestsNavigation.kt b/feature/interests/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/interests/navigation/InterestsNavigation.kt index 7558ec48d..3bc0ad770 100644 --- a/feature/interests/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/interests/navigation/InterestsNavigation.kt +++ b/feature/interests/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/interests/navigation/InterestsNavigation.kt @@ -26,7 +26,7 @@ import com.google.samples.apps.nowinandroid.feature.interests.InterestsRoute private const val INTERESTS_GRAPH_ROUTE_PATTERN = "interests_graph" const val interestsRoute = "interests_route" -fun NavController.navigateToInterestsGraph(navOptions: NavOptions? = null) { +fun NavController.navigateToInterestsGraph(navOptions: NavOptions) { this.navigate(INTERESTS_GRAPH_ROUTE_PATTERN, navOptions) } diff --git a/feature/search/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/search/SearchScreen.kt b/feature/search/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/search/SearchScreen.kt index 65b65f61d..b6e977571 100644 --- a/feature/search/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/search/SearchScreen.kt +++ b/feature/search/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/search/SearchScreen.kt @@ -264,9 +264,7 @@ fun EmptySearchResultBody( ) { offset -> tryAnotherSearchString.getStringAnnotations(start = offset, end = offset) .firstOrNull() - ?.let { - onInterestsClick() - } + ?.let { onInterestsClick() } } } } @@ -519,9 +517,7 @@ private fun SearchTextField( } }, onValueChange = { - if (!it.contains("\n")) { - onSearchQueryChanged(it) - } + if ("\n" !in it) onSearchQueryChanged(it) }, modifier = Modifier .fillMaxWidth() diff --git a/feature/topic/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/topic/TopicViewModel.kt b/feature/topic/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/topic/TopicViewModel.kt index 6adfe0a67..ff1eee319 100644 --- a/feature/topic/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/topic/TopicViewModel.kt +++ b/feature/topic/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/topic/TopicViewModel.kt @@ -117,22 +117,16 @@ private fun topicUiState( when (followedTopicToTopicResult) { is Result.Success -> { val (followedTopics, topic) = followedTopicToTopicResult.data - val followed = followedTopics.contains(topicId) TopicUiState.Success( followableTopic = FollowableTopic( topic = topic, - isFollowed = followed, + isFollowed = topicId in followedTopics, ), ) } - is Result.Loading -> { - TopicUiState.Loading - } - - is Result.Error -> { - TopicUiState.Error - } + is Result.Loading -> TopicUiState.Loading + is Result.Error -> TopicUiState.Error } } } @@ -151,26 +145,13 @@ private fun newsUiState( val bookmark: Flow> = userDataRepository.userData .map { it.bookmarkedNewsResources } - return combine( - newsStream, - bookmark, - ::Pair, - ) + return combine(newsStream, bookmark, ::Pair) .asResult() .map { newsToBookmarksResult -> when (newsToBookmarksResult) { - is Result.Success -> { - val news = newsToBookmarksResult.data.first - NewsUiState.Success(news) - } - - is Result.Loading -> { - NewsUiState.Loading - } - - is Result.Error -> { - NewsUiState.Error - } + is Result.Success -> NewsUiState.Success(newsToBookmarksResult.data.first) + is Result.Loading -> NewsUiState.Loading + is Result.Error -> NewsUiState.Error } } } diff --git a/feature/topic/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/topic/navigation/TopicNavigation.kt b/feature/topic/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/topic/navigation/TopicNavigation.kt index c29b57d47..2d75a8d8d 100644 --- a/feature/topic/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/topic/navigation/TopicNavigation.kt +++ b/feature/topic/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/topic/navigation/TopicNavigation.kt @@ -40,7 +40,7 @@ internal class TopicArgs(val topicId: String) { fun NavController.navigateToTopic(topicId: String) { val encodedId = URLEncoder.encode(topicId, URL_CHARACTER_ENCODING) - this.navigate("topic_route/$encodedId") { + navigate("topic_route/$encodedId") { launchSingleTop = true } } diff --git a/lint/src/main/kotlin/com/google/samples/apps/nowinandroid/lint/designsystem/DesignSystemDetector.kt b/lint/src/main/kotlin/com/google/samples/apps/nowinandroid/lint/designsystem/DesignSystemDetector.kt index 4c9d55764..09af17db9 100644 --- a/lint/src/main/kotlin/com/google/samples/apps/nowinandroid/lint/designsystem/DesignSystemDetector.kt +++ b/lint/src/main/kotlin/com/google/samples/apps/nowinandroid/lint/designsystem/DesignSystemDetector.kt @@ -34,15 +34,13 @@ import org.jetbrains.uast.UQualifiedReferenceExpression */ class DesignSystemDetector : Detector(), Detector.UastScanner { - override fun getApplicableUastTypes(): List> { - return listOf( - UCallExpression::class.java, - UQualifiedReferenceExpression::class.java, - ) - } + override fun getApplicableUastTypes(): List> = listOf( + UCallExpression::class.java, + UQualifiedReferenceExpression::class.java, + ) - override fun createUastHandler(context: JavaContext): UElementHandler { - return object : UElementHandler() { + override fun createUastHandler(context: JavaContext): UElementHandler = + object : UElementHandler() { override fun visitCallExpression(node: UCallExpression) { val name = node.methodName ?: return val preferredName = METHOD_NAMES[name] ?: return @@ -55,7 +53,6 @@ class DesignSystemDetector : Detector(), Detector.UastScanner { reportIssue(context, node, name, preferredName) } } - } companion object { @JvmField From dad6f3dcdc6e62e60f92a22b32101aa927e09c2e Mon Sep 17 00:00:00 2001 From: Simon Marquis Date: Thu, 21 Dec 2023 18:45:05 +0100 Subject: [PATCH 03/35] Update core/designsystem/src/main/kotlin/com/google/samples/apps/nowinandroid/core/designsystem/component/scrollbar/ScrollbarExt.kt Co-authored-by: Don Turner --- .../core/designsystem/component/scrollbar/ScrollbarExt.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/designsystem/src/main/kotlin/com/google/samples/apps/nowinandroid/core/designsystem/component/scrollbar/ScrollbarExt.kt b/core/designsystem/src/main/kotlin/com/google/samples/apps/nowinandroid/core/designsystem/component/scrollbar/ScrollbarExt.kt index 76fab08d0..3fcc8f2c0 100644 --- a/core/designsystem/src/main/kotlin/com/google/samples/apps/nowinandroid/core/designsystem/component/scrollbar/ScrollbarExt.kt +++ b/core/designsystem/src/main/kotlin/com/google/samples/apps/nowinandroid/core/designsystem/component/scrollbar/ScrollbarExt.kt @@ -231,4 +231,4 @@ fun LazyStaggeredGridState.scrollbarState( } private inline fun List.floatSumOf(selector: (T) -> Float): Float = - fold(0f) { acc, it -> acc + selector(it) } + fold(initial = 0f) { accumulator, listItem -> accumulator + selector(listItem) } From 1afb38eb0a691395fa511cda4e507c5b342c742c Mon Sep 17 00:00:00 2001 From: Simon Marquis Date: Thu, 21 Dec 2023 18:48:05 +0100 Subject: [PATCH 04/35] Update feature/foryou/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/foryou/navigation/ForYouNavigation.kt --- .../feature/foryou/navigation/ForYouNavigation.kt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/feature/foryou/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/foryou/navigation/ForYouNavigation.kt b/feature/foryou/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/foryou/navigation/ForYouNavigation.kt index efbe67859..8e94a491a 100644 --- a/feature/foryou/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/foryou/navigation/ForYouNavigation.kt +++ b/feature/foryou/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/foryou/navigation/ForYouNavigation.kt @@ -30,9 +30,7 @@ const val FOR_YOU_ROUTE = "for_you_route/{$LINKED_NEWS_RESOURCE_ID}" private const val DEEP_LINK_URI_PATTERN = "https://www.nowinandroid.apps.samples.google.com/foryou/{$LINKED_NEWS_RESOURCE_ID}" -fun NavController.navigateToForYou(navOptions: NavOptions) { - this.navigate(FOR_YOU_ROUTE, navOptions) -} +fun NavController.navigateToForYou(navOptions: NavOptions) = navigate(FOR_YOU_ROUTE, navOptions) fun NavGraphBuilder.forYouScreen(onTopicClick: (String) -> Unit) { composable( From aee36c14949db05d53526efead12b3f3743ed835 Mon Sep 17 00:00:00 2001 From: Simon Marquis Date: Thu, 21 Dec 2023 18:50:26 +0100 Subject: [PATCH 05/35] Update feature/bookmarks/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/bookmarks/navigation/BookmarksNavigation.kt --- .../feature/bookmarks/navigation/BookmarksNavigation.kt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/feature/bookmarks/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/bookmarks/navigation/BookmarksNavigation.kt b/feature/bookmarks/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/bookmarks/navigation/BookmarksNavigation.kt index a62b2c5d1..13d0baef0 100644 --- a/feature/bookmarks/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/bookmarks/navigation/BookmarksNavigation.kt +++ b/feature/bookmarks/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/bookmarks/navigation/BookmarksNavigation.kt @@ -24,9 +24,7 @@ import com.google.samples.apps.nowinandroid.feature.bookmarks.BookmarksRoute const val BOOKMARKS_ROUTE = "bookmarks_route" -fun NavController.navigateToBookmarks(navOptions: NavOptions) { - this.navigate(BOOKMARKS_ROUTE, navOptions) -} +fun NavController.navigateToBookmarks(navOptions: NavOptions) = navigate(BOOKMARKS_ROUTE, navOptions) fun NavGraphBuilder.bookmarksScreen( onTopicClick: (String) -> Unit, From 58ecf312ffa3f0fddfbbbf5798d15f2408b2c5c7 Mon Sep 17 00:00:00 2001 From: Simon Marquis Date: Thu, 21 Dec 2023 18:50:50 +0100 Subject: [PATCH 06/35] Update feature/interests/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/interests/navigation/InterestsNavigation.kt --- .../feature/interests/navigation/InterestsNavigation.kt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/feature/interests/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/interests/navigation/InterestsNavigation.kt b/feature/interests/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/interests/navigation/InterestsNavigation.kt index d6ebaeeb7..2ad7c560b 100644 --- a/feature/interests/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/interests/navigation/InterestsNavigation.kt +++ b/feature/interests/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/interests/navigation/InterestsNavigation.kt @@ -26,9 +26,7 @@ import com.google.samples.apps.nowinandroid.feature.interests.InterestsRoute private const val INTERESTS_GRAPH_ROUTE_PATTERN = "interests_graph" const val INTERESTS_ROUTE = "interests_route" -fun NavController.navigateToInterestsGraph(navOptions: NavOptions) { - this.navigate(INTERESTS_GRAPH_ROUTE_PATTERN, navOptions) -} +fun NavController.navigateToInterestsGraph(navOptions: NavOptions) = navigate(INTERESTS_GRAPH_ROUTE_PATTERN, navOptions) fun NavGraphBuilder.interestsGraph( onTopicClick: (String) -> Unit, From 3af5b2077e88bcd079d8b52c151c240e8bb9451b Mon Sep 17 00:00:00 2001 From: Simon Marquis Date: Thu, 21 Dec 2023 18:51:17 +0100 Subject: [PATCH 07/35] Update feature/search/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/search/navigation/SearchNavigation.kt --- .../feature/search/navigation/SearchNavigation.kt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/feature/search/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/search/navigation/SearchNavigation.kt b/feature/search/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/search/navigation/SearchNavigation.kt index a449600b2..81f3576b4 100644 --- a/feature/search/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/search/navigation/SearchNavigation.kt +++ b/feature/search/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/search/navigation/SearchNavigation.kt @@ -24,9 +24,7 @@ import com.google.samples.apps.nowinandroid.feature.search.SearchRoute const val SEARCH_ROUTE = "search_route" -fun NavController.navigateToSearch(navOptions: NavOptions? = null) { - this.navigate(SEARCH_ROUTE, navOptions) -} +fun NavController.navigateToSearch(navOptions: NavOptions? = null) = navigate(SEARCH_ROUTE, navOptions) fun NavGraphBuilder.searchScreen( onBackClick: () -> Unit, From ae55eb8e1a334ed2ab60f36286b999cf70a23874 Mon Sep 17 00:00:00 2001 From: Simon Marquis Date: Fri, 2 Jun 2023 23:43:25 +0200 Subject: [PATCH 08/35] Optimize AVD to fix long vector paths Lint warning ... with SVGOM, but you'll have to check on Android Studio the AVD diff. https://googlesamples.github.io/android-custom-lint-rules/checks/VectorPath.md.html --- app/src/main/res/drawable/ic_launcher_foreground.xml | 4 ++-- app/src/main/res/drawable/ic_splash.xml | 6 +++--- .../drawable/core_designsystem_ic_placeholder_default.xml | 8 ++++---- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/app/src/main/res/drawable/ic_launcher_foreground.xml b/app/src/main/res/drawable/ic_launcher_foreground.xml index 6d5711aa5..77280bad5 100644 --- a/app/src/main/res/drawable/ic_launcher_foreground.xml +++ b/app/src/main/res/drawable/ic_launcher_foreground.xml @@ -20,10 +20,10 @@ android:viewportWidth="108" android:viewportHeight="108"> diff --git a/app/src/main/res/drawable/ic_splash.xml b/app/src/main/res/drawable/ic_splash.xml index 6de9c8c9b..144393be9 100644 --- a/app/src/main/res/drawable/ic_splash.xml +++ b/app/src/main/res/drawable/ic_splash.xml @@ -24,11 +24,11 @@ android:pathData="M0,0h108v108h-108z" android:fillColor="@color/ic_launcher_background_tint"/> - \ No newline at end of file + diff --git a/core/designsystem/src/main/res/drawable/core_designsystem_ic_placeholder_default.xml b/core/designsystem/src/main/res/drawable/core_designsystem_ic_placeholder_default.xml index a00c2de22..f5d87a103 100644 --- a/core/designsystem/src/main/res/drawable/core_designsystem_ic_placeholder_default.xml +++ b/core/designsystem/src/main/res/drawable/core_designsystem_ic_placeholder_default.xml @@ -32,12 +32,12 @@ android:fillColor="#8C4190" android:fillAlpha="0.11"/> From 4858b8355ae01b2305a7d6d9c1e2999362506e36 Mon Sep 17 00:00:00 2001 From: SimonMarquis Date: Fri, 22 Dec 2023 15:02:17 +0000 Subject: [PATCH 09/35] =?UTF-8?q?=F0=9F=A4=96=20Updates=20screenshots?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...Width_compactHeight_showsNavigationBar.png | Bin 37291 -> 37230 bytes ...idth_expandedHeight_showsNavigationBar.png | Bin 107576 -> 107363 bytes ...tWidth_mediumHeight_showsNavigationBar.png | Bin 52265 -> 52205 bytes ...idth_compactHeight_showsNavigationRail.png | Bin 77483 -> 77374 bytes ...dth_expandedHeight_showsNavigationRail.png | Bin 239201 -> 239019 bytes ...Width_mediumHeight_showsNavigationRail.png | Bin 114944 -> 114836 bytes ...idth_compactHeight_showsNavigationRail.png | Bin 59208 -> 59215 bytes ...dth_expandedHeight_showsNavigationRail.png | Bin 155955 -> 156220 bytes ...Width_mediumHeight_showsNavigationRail.png | Bin 84721 -> 84728 bytes 9 files changed, 0 insertions(+), 0 deletions(-) diff --git a/app/src/testDemo/screenshots/compactWidth_compactHeight_showsNavigationBar.png b/app/src/testDemo/screenshots/compactWidth_compactHeight_showsNavigationBar.png index edb9cfa2af84cd033ba111bc746f1ec24259effc..04ccb84241de8e88a085ef654b0540cc2e536145 100644 GIT binary patch literal 37230 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 z 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 literal 37291 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