From ec784f6d2d5c5b7bc1c4b79d31a019023f5f6b51 Mon Sep 17 00:00:00 2001 From: Don Turner Date: Fri, 5 Apr 2024 17:02:04 +0100 Subject: [PATCH 01/10] Replace kapt with ksp, update versions --- app/build.gradle.kts | 2 +- app/src/debug/AndroidManifest.xml | 3 +- app/src/main/AndroidManifest.xml | 3 +- .../todoapp/addedittask/AddEditTaskScreen.kt | 2 - .../todoapp/data/DefaultTaskRepository.kt | 1 - .../todoapp/statistics/StatisticsScreen.kt | 2 - .../todoapp/taskdetail/TaskDetailScreen.kt | 2 - .../blueprints/todoapp/tasks/TasksScreen.kt | 2 - build.gradle.kts | 1 - gradle.properties | 5 +- gradle/libs.versions.toml | 74 +++++++++---------- gradle/wrapper/gradle-wrapper.properties | 2 +- shared-test/build.gradle.kts | 3 +- 13 files changed, 46 insertions(+), 56 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 457602507..3473d2ba1 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -17,7 +17,6 @@ plugins { alias(libs.plugins.android.application) alias(libs.plugins.kotlin.android) - alias(libs.plugins.kapt) alias(libs.plugins.ksp) alias(libs.plugins.hilt) } @@ -97,6 +96,7 @@ android { composeOptions { kotlinCompilerExtensionVersion = libs.versions.androidxComposeCompiler.get() } + namespace = "com.example.android.architecture.blueprints.todoapp" tasks.withType().configureEach { kotlinOptions { diff --git a/app/src/debug/AndroidManifest.xml b/app/src/debug/AndroidManifest.xml index dbf09ddfc..0c4c62119 100644 --- a/app/src/debug/AndroidManifest.xml +++ b/app/src/debug/AndroidManifest.xml @@ -14,8 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - + - + Unit, diff --git a/app/src/main/java/com/example/android/architecture/blueprints/todoapp/taskdetail/TaskDetailScreen.kt b/app/src/main/java/com/example/android/architecture/blueprints/todoapp/taskdetail/TaskDetailScreen.kt index 814377da3..99e3ca8db 100644 --- a/app/src/main/java/com/example/android/architecture/blueprints/todoapp/taskdetail/TaskDetailScreen.kt +++ b/app/src/main/java/com/example/android/architecture/blueprints/todoapp/taskdetail/TaskDetailScreen.kt @@ -42,7 +42,6 @@ import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.ExperimentalLifecycleComposeApi import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.example.android.architecture.blueprints.todoapp.R import com.example.android.architecture.blueprints.todoapp.data.Task @@ -50,7 +49,6 @@ import com.example.android.architecture.blueprints.todoapp.util.LoadingContent import com.example.android.architecture.blueprints.todoapp.util.TaskDetailTopAppBar import com.google.accompanist.appcompattheme.AppCompatTheme -@OptIn(ExperimentalLifecycleComposeApi::class) @Composable fun TaskDetailScreen( onEditTask: (String) -> Unit, diff --git a/app/src/main/java/com/example/android/architecture/blueprints/todoapp/tasks/TasksScreen.kt b/app/src/main/java/com/example/android/architecture/blueprints/todoapp/tasks/TasksScreen.kt index 16cf81e86..964512754 100644 --- a/app/src/main/java/com/example/android/architecture/blueprints/todoapp/tasks/TasksScreen.kt +++ b/app/src/main/java/com/example/android/architecture/blueprints/todoapp/tasks/TasksScreen.kt @@ -53,7 +53,6 @@ import androidx.compose.ui.text.style.TextDecoration import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.ExperimentalLifecycleComposeApi import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.example.android.architecture.blueprints.todoapp.R import com.example.android.architecture.blueprints.todoapp.data.Task @@ -64,7 +63,6 @@ import com.example.android.architecture.blueprints.todoapp.util.LoadingContent import com.example.android.architecture.blueprints.todoapp.util.TasksTopAppBar import com.google.accompanist.appcompattheme.AppCompatTheme -@OptIn(ExperimentalLifecycleComposeApi::class) @Composable fun TasksScreen( @StringRes userMessage: Int, diff --git a/build.gradle.kts b/build.gradle.kts index 79946bd70..232e26416 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -17,7 +17,6 @@ plugins { alias(libs.plugins.android.application) apply false alias(libs.plugins.android.library) apply false alias(libs.plugins.kotlin.android) apply false - alias(libs.plugins.kapt) apply false alias(libs.plugins.ksp) apply false alias(libs.plugins.hilt) apply false } diff --git a/gradle.properties b/gradle.properties index 504538451..92c1b8ee5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -20,4 +20,7 @@ android.enableJetifier=true android.useAndroidX=true kapt.incremental.apt=true ksp.incremental.apt=true -org.gradle.unsafe.configuration-cache=true \ No newline at end of file +org.gradle.unsafe.configuration-cache=true +android.defaults.buildfeatures.buildconfig=true +android.nonTransitiveRClass=false +android.nonFinalResIds=false \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index c7415dcf8..828a79e5e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,62 +1,62 @@ [versions] -accompanist = "0.28.0" -annotation = "1.5.0" -androidDesugarJdkLibs = "1.2.2" -androidGradlePlugin = "7.4.0" -androidxActivity = "1.6.1" -androidxAppCompat = "1.5.1" -androidxArchCore = "2.1.0" +accompanist = "0.34.0" +annotation = "1.7.1" +androidDesugarJdkLibs = "2.0.4" +androidGradlePlugin = "8.3.1" +androidxActivity = "1.8.2" +androidxAppCompat = "1.6.1" +androidxArchCore = "2.2.0" androidxBrowser = "1.4.0" -androidxComposeBom = "2023.01.00" -androidxComposeCompiler = "1.4.3" +androidxComposeBom = "2024.04.00" +androidxComposeCompiler = "1.5.11" androidxCompose = "1.2.0" -androidxComposeRuntimeTracing = "1.0.0-alpha01" -androidxCore = "1.9.0" -androidxCoreSplashscreen = "1.0.0" +androidxComposeRuntimeTracing = "1.0.0-beta01" +androidxCore = "1.12.0" +androidxCoreSplashscreen = "1.0.1" androidxDataStore = "1.0.0" -androidxEspresso = "3.5.0" -androidxHiltNavigationCompose = "1.0.0" -androidxLifecycle = "2.6.0-alpha03" +androidxEspresso = "3.5.1" +androidxHiltNavigationCompose = "1.2.0" +androidxLifecycle = "2.7.0" androidxMacroBenchmark = "1.1.1" -androidxMetrics = "1.0.0-alpha03" -androidxNavigation = "2.5.3" -androidxProfileinstaller = "1.2.1" +androidxMetrics = "1.0.0-beta01" +androidxNavigation = "2.7.7" +androidxProfileinstaller = "1.3.1" androidxStartup = "1.1.1" androidxTestCore = "1.5.0" -androidxTestExt = "1.1.4" +androidxTestExt = "1.1.5" androidxTestRules = "1.5.0" -androidxTestRunner = "1.5.1" -androidxTracing = "1.1.0" -androidxUiAutomator = "2.2.0" -androidxWindowManager = "1.0.0" -androidxWork = "2.7.1" -coil = "2.2.2" +androidxTestRunner = "1.5.2" +androidxTracing = "1.2.0" +androidxUiAutomator = "2.3.0" +androidxWindowManager = "1.2.0" +androidxWork = "2.9.0" +coil = "2.6.0" # @keep -compileSdk = "33" +compileSdk = "34" hamcrest = "1.3" -hilt = "2.44.2" -hiltExt = "1.0.0" +hilt = "2.51" +hiltExt = "1.2.0" jacoco = "0.8.7" junit4 = "4.13.2" -kotlin = "1.8.10" -kotlinxCoroutines = "1.6.4" -kotlinxDatetime = "0.4.0" -kotlinxSerializationJson = "1.5.0" -ksp = "1.8.10-1.0.9" -lint = "30.3.1" +kotlin = "1.9.23" +kotlinxCoroutines = "1.8.0" +kotlinxDatetime = "0.5.0" +kotlinxSerializationJson = "1.6.3" +ksp = "1.9.22-1.0.18" +lint = "31.3.1" # @keep minSdk = "21" okhttp = "4.10.0" protobuf = "3.21.12" -protobufPlugin = "0.8.19" +protobufPlugin = "0.9.1" retrofit = "2.9.0" retrofitKotlinxSerializationJson = "0.8.0" -room = "2.5.0-rc01" +room = "2.6.1" spotless = "5.12.5" timber = "5.0.1" # @keep targetSdk = "33" -truth = "1.1.2" +truth = "1.4.2" turbine = "0.12.1" [libraries] diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 8049c684f..17655d0ef 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/shared-test/build.gradle.kts b/shared-test/build.gradle.kts index 2060fc01b..c62628a43 100644 --- a/shared-test/build.gradle.kts +++ b/shared-test/build.gradle.kts @@ -16,7 +16,6 @@ plugins { alias(libs.plugins.android.library) alias(libs.plugins.kotlin.android) - alias(libs.plugins.kapt) alias(libs.plugins.ksp) alias(libs.plugins.hilt) } @@ -39,7 +38,7 @@ dependencies { implementation(libs.androidx.test.rules) implementation(libs.hilt.android.core) implementation(libs.hilt.android.testing) - kapt(libs.hilt.compiler) + ksp(libs.hilt.compiler) // Room implementation(libs.room.runtime) From 684c5ac6d506c90284d692229745bbc10e4956ee Mon Sep 17 00:00:00 2001 From: Don Turner Date: Fri, 5 Apr 2024 17:20:28 +0100 Subject: [PATCH 02/10] Fix tests, bump target SDK --- app/build.gradle.kts | 7 ++++--- gradle.properties | 1 - gradle/libs.versions.toml | 4 ++-- shared-test/build.gradle.kts | 5 +++++ 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 3473d2ba1..bd2698f65 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -77,15 +77,16 @@ android { buildFeatures { compose = true + buildConfig = true } compileOptions { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 } kotlinOptions { - jvmTarget = "1.8" + jvmTarget = "17" } packagingOptions { diff --git a/gradle.properties b/gradle.properties index 92c1b8ee5..db9bd11c5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -21,6 +21,5 @@ android.useAndroidX=true kapt.incremental.apt=true ksp.incremental.apt=true org.gradle.unsafe.configuration-cache=true -android.defaults.buildfeatures.buildconfig=true android.nonTransitiveRClass=false android.nonFinalResIds=false \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 828a79e5e..22dd0bc12 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -42,7 +42,7 @@ kotlin = "1.9.23" kotlinxCoroutines = "1.8.0" kotlinxDatetime = "0.5.0" kotlinxSerializationJson = "1.6.3" -ksp = "1.9.22-1.0.18" +ksp = "1.9.23-1.0.20" lint = "31.3.1" # @keep minSdk = "21" @@ -55,7 +55,7 @@ room = "2.6.1" spotless = "5.12.5" timber = "5.0.1" # @keep -targetSdk = "33" +targetSdk = "34" truth = "1.4.2" turbine = "0.12.1" diff --git a/shared-test/build.gradle.kts b/shared-test/build.gradle.kts index c62628a43..7d6815085 100644 --- a/shared-test/build.gradle.kts +++ b/shared-test/build.gradle.kts @@ -26,6 +26,11 @@ android { defaultConfig { minSdk = libs.versions.minSdk.get().toInt() } + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } } dependencies { From f365158a519b1f880574e091f91a218a0ea438ba Mon Sep 17 00:00:00 2001 From: Don Turner Date: Mon, 8 Apr 2024 16:44:01 +0100 Subject: [PATCH 03/10] Update CI to use JDK 17 --- .github/workflows/blueprints.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/blueprints.yaml b/.github/workflows/blueprints.yaml index bb86bc2fe..41caf6a42 100644 --- a/.github/workflows/blueprints.yaml +++ b/.github/workflows/blueprints.yaml @@ -22,10 +22,10 @@ jobs: - name: Copy CI gradle.properties run: mkdir -p ~/.gradle ; cp .github/ci-gradle.properties ~/.gradle/gradle.properties - - name: Set up JDK 11 + - name: Set up JDK 17 uses: actions/setup-java@v1 with: - java-version: 11 + java-version: 17 - uses: actions/cache@v2 with: From b526f1fad74f8e4680ef9b34ea21d3b82d4b1e02 Mon Sep 17 00:00:00 2001 From: Don Turner Date: Mon, 8 Apr 2024 16:54:03 +0100 Subject: [PATCH 04/10] Remove deprecated warning (just to trigger fresh CI build, not from cache) --- app/build.gradle.kts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index bd2698f65..d514c9775 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -89,9 +89,9 @@ android { jvmTarget = "17" } - packagingOptions { - excludes += "META-INF/AL2.0" - excludes += "META-INF/LGPL2.1" + packaging { + jniLibs.excludes += "META-INF/AL2.0" + jniLibs.excludes += "META-INF/LGPL2.1" } composeOptions { From e8f59b50c7bd14494a34b2586ffc1b83af13debf Mon Sep 17 00:00:00 2001 From: Don Turner Date: Mon, 8 Apr 2024 16:59:00 +0100 Subject: [PATCH 05/10] Remove kapt from gradle properties and versions.toml --- gradle.properties | 1 - gradle/libs.versions.toml | 1 - 2 files changed, 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index db9bd11c5..538c1593d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -18,7 +18,6 @@ org.gradle.jvmargs=-Xmx4096m -XX:MaxPermSize=1024m -XX:+HeapDumpOnOutOfMemoryErr # org.gradle.parallel=true android.enableJetifier=true android.useAndroidX=true -kapt.incremental.apt=true ksp.incremental.apt=true org.gradle.unsafe.configuration-cache=true android.nonTransitiveRClass=false diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 22dd0bc12..e7aee083d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -149,6 +149,5 @@ hilt = { id = "com.google.dagger.hilt.android", version.ref = "hilt" } kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } -kapt = { id = "org.jetbrains.kotlin.kapt", version.ref = "kotlin" } ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" } protobuf = { id = "com.google.protobuf", version.ref = "protobufPlugin" } From c104e213cbfe6176317ab402f2b9683026feba4e Mon Sep 17 00:00:00 2001 From: Don Turner Date: Mon, 8 Apr 2024 17:02:48 +0100 Subject: [PATCH 06/10] Temporarily disable CI cache to investigate failing build --- .github/workflows/blueprints.yaml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/blueprints.yaml b/.github/workflows/blueprints.yaml index 41caf6a42..195e5a5a5 100644 --- a/.github/workflows/blueprints.yaml +++ b/.github/workflows/blueprints.yaml @@ -27,13 +27,13 @@ jobs: with: java-version: 17 - - uses: actions/cache@v2 - with: - path: | - ~/.gradle/caches/modules-* - ~/.gradle/caches/jars-* - ~/.gradle/caches/build-cache-* - key: gradle-${{ hashFiles('checksum.txt') }} + #- uses: actions/cache@v2 + # with: + # path: | + #~/.gradle/caches/modules-* + #~/.gradle/caches/jars-* + #~/.gradle/caches/build-cache-* + #key: gradle-${{ hashFiles('checksum.txt') }} - name: Build project and UnitTest run: ./gradlew assembleDebug compileDebugUnitTestKotlin From 341d1a80570b34d33956e6bf01f51d65a63849da Mon Sep 17 00:00:00 2001 From: Don Turner Date: Mon, 8 Apr 2024 17:12:31 +0100 Subject: [PATCH 07/10] Rebase main --- app/build.gradle.kts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index d514c9775..7eb56f5dc 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -129,7 +129,7 @@ dependencies { // Hilt implementation(libs.hilt.android.core) implementation(libs.androidx.hilt.navigation.compose) - kapt(libs.hilt.compiler) + ksp(libs.hilt.compiler) // Jetpack Compose val composeBom = platform(libs.androidx.compose.bom) @@ -167,7 +167,7 @@ dependencies { // JVM tests - Hilt testImplementation(libs.hilt.android.testing) - kaptTest(libs.hilt.compiler) + kspTest(libs.hilt.compiler) // Dependencies for Android unit tests androidTestImplementation(composeBom) @@ -197,5 +197,5 @@ dependencies { // AndroidX Test - Hilt testing androidTestImplementation(libs.hilt.android.testing) - kaptAndroidTest(libs.hilt.compiler) + kspAndroidTest(libs.hilt.compiler) } From be53081595da9b72da5afcd353ef487e38a3c4ad Mon Sep 17 00:00:00 2001 From: Don Turner Date: Mon, 8 Apr 2024 17:13:43 +0100 Subject: [PATCH 08/10] Revert "Temporarily disable CI cache to investigate failing build" This reverts commit c104e213cbfe6176317ab402f2b9683026feba4e. --- .github/workflows/blueprints.yaml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/blueprints.yaml b/.github/workflows/blueprints.yaml index 195e5a5a5..41caf6a42 100644 --- a/.github/workflows/blueprints.yaml +++ b/.github/workflows/blueprints.yaml @@ -27,13 +27,13 @@ jobs: with: java-version: 17 - #- uses: actions/cache@v2 - # with: - # path: | - #~/.gradle/caches/modules-* - #~/.gradle/caches/jars-* - #~/.gradle/caches/build-cache-* - #key: gradle-${{ hashFiles('checksum.txt') }} + - uses: actions/cache@v2 + with: + path: | + ~/.gradle/caches/modules-* + ~/.gradle/caches/jars-* + ~/.gradle/caches/build-cache-* + key: gradle-${{ hashFiles('checksum.txt') }} - name: Build project and UnitTest run: ./gradlew assembleDebug compileDebugUnitTestKotlin From 898d32da3cd06bb065c26b73cf6f8f993bbfb5f3 Mon Sep 17 00:00:00 2001 From: Don Turner Date: Mon, 8 Apr 2024 18:09:55 +0100 Subject: [PATCH 09/10] Fix spotless --- .../blueprints/todoapp/data/DefaultTaskRepository.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/app/src/main/java/com/example/android/architecture/blueprints/todoapp/data/DefaultTaskRepository.kt b/app/src/main/java/com/example/android/architecture/blueprints/todoapp/data/DefaultTaskRepository.kt index 3f7d4429d..1be692081 100644 --- a/app/src/main/java/com/example/android/architecture/blueprints/todoapp/data/DefaultTaskRepository.kt +++ b/app/src/main/java/com/example/android/architecture/blueprints/todoapp/data/DefaultTaskRepository.kt @@ -22,7 +22,6 @@ import com.example.android.architecture.blueprints.todoapp.di.ApplicationScope import com.example.android.architecture.blueprints.todoapp.di.DefaultDispatcher import java.util.UUID import javax.inject.Inject -import javax.inject.Singleton import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.Flow From 738708203760e19453a6c8d01723000d083f393c Mon Sep 17 00:00:00 2001 From: Don Turner Date: Mon, 8 Apr 2024 18:15:05 +0100 Subject: [PATCH 10/10] Update Spotless and ktlint, apply rule changes to code --- .../addedittask/AddEditTaskScreenTest.kt | 2 +- .../todoapp/data/source/local/TaskDaoTest.kt | 13 +++---- .../taskdetail/TaskDetailScreenTest.kt | 2 +- .../blueprints/todoapp/TodoNavGraph.kt | 10 ++++-- .../todoapp/addedittask/AddEditTaskScreen.kt | 2 +- .../addedittask/AddEditTaskViewModel.kt | 2 +- .../todoapp/data/DefaultTaskRepository.kt | 4 +-- .../todoapp/data/ModelMappingExt.kt | 12 ++++--- .../blueprints/todoapp/data/Task.kt | 2 +- .../todoapp/data/source/local/LocalTask.kt | 2 +- .../blueprints/todoapp/di/CoroutinesModule.kt | 5 ++- .../todoapp/statistics/StatisticsViewModel.kt | 35 +++++++++--------- .../{StatisticsUtils.kt => StatsResult.kt} | 1 - .../todoapp/taskdetail/TaskDetailScreen.kt | 4 +-- .../todoapp/taskdetail/TaskDetailViewModel.kt | 23 ++++++------ .../blueprints/todoapp/tasks/TasksScreen.kt | 14 +++----- .../todoapp/tasks/TasksViewModel.kt | 36 +++++++++++-------- .../blueprints/todoapp/util/ComposeUtils.kt | 2 +- .../todoapp/util/CoroutinesUtils.kt | 4 +-- .../blueprints/todoapp/util/TodoDrawer.kt | 7 ++-- .../blueprints/todoapp/util/TopAppBars.kt | 30 +++++++++++----- .../todoapp/data/DefaultTaskRepositoryTest.kt | 15 ++++---- .../todoapp/statistics/StatisticsUtilsTest.kt | 6 ++-- gradle/init.gradle.kts | 14 ++++++-- 24 files changed, 139 insertions(+), 108 deletions(-) rename app/src/main/java/com/example/android/architecture/blueprints/todoapp/statistics/{StatisticsUtils.kt => StatsResult.kt} (99%) diff --git a/app/src/androidTest/java/com/example/android/architecture/blueprints/todoapp/addedittask/AddEditTaskScreenTest.kt b/app/src/androidTest/java/com/example/android/architecture/blueprints/todoapp/addedittask/AddEditTaskScreenTest.kt index f7b68a521..c34a1bd50 100644 --- a/app/src/androidTest/java/com/example/android/architecture/blueprints/todoapp/addedittask/AddEditTaskScreenTest.kt +++ b/app/src/androidTest/java/com/example/android/architecture/blueprints/todoapp/addedittask/AddEditTaskScreenTest.kt @@ -76,7 +76,7 @@ class AddEditTaskScreenTest { viewModel = AddEditTaskViewModel(repository, SavedStateHandle()), topBarTitle = R.string.add_task, onTaskUpdate = { }, - onBack = { }, + onBack = { } ) } } diff --git a/app/src/androidTest/java/com/example/android/architecture/blueprints/todoapp/data/source/local/TaskDaoTest.kt b/app/src/androidTest/java/com/example/android/architecture/blueprints/todoapp/data/source/local/TaskDaoTest.kt index 4575af69e..8927d06ca 100644 --- a/app/src/androidTest/java/com/example/android/architecture/blueprints/todoapp/data/source/local/TaskDaoTest.kt +++ b/app/src/androidTest/java/com/example/android/architecture/blueprints/todoapp/data/source/local/TaskDaoTest.kt @@ -45,6 +45,7 @@ class TaskDaoTest { ToDoDatabase::class.java ).allowMainThreadQueries().build() } + @Test fun insertTaskAndGetById() = runTest { // GIVEN - insert a task @@ -52,7 +53,7 @@ class TaskDaoTest { title = "title", description = "description", id = "id", - isCompleted = false, + isCompleted = false ) database.taskDao().upsert(task) @@ -74,7 +75,7 @@ class TaskDaoTest { title = "title", description = "description", id = "id", - isCompleted = false, + isCompleted = false ) database.taskDao().upsert(task) @@ -102,7 +103,7 @@ class TaskDaoTest { title = "title", description = "description", id = "id", - isCompleted = false, + isCompleted = false ) database.taskDao().upsert(task) @@ -124,7 +125,7 @@ class TaskDaoTest { title = "title", description = "description", id = "id", - isCompleted = false, + isCompleted = false ) database.taskDao().upsert(originalTask) @@ -175,7 +176,7 @@ class TaskDaoTest { title = "title", description = "description", id = "id", - isCompleted = false, + isCompleted = false ) database.taskDao().upsert(task) @@ -195,7 +196,7 @@ class TaskDaoTest { title = "title", description = "description", id = "id", - isCompleted = false, + isCompleted = false ) ) diff --git a/app/src/androidTest/java/com/example/android/architecture/blueprints/todoapp/taskdetail/TaskDetailScreenTest.kt b/app/src/androidTest/java/com/example/android/architecture/blueprints/todoapp/taskdetail/TaskDetailScreenTest.kt index 666f76747..96bbb2946 100644 --- a/app/src/androidTest/java/com/example/android/architecture/blueprints/todoapp/taskdetail/TaskDetailScreenTest.kt +++ b/app/src/androidTest/java/com/example/android/architecture/blueprints/todoapp/taskdetail/TaskDetailScreenTest.kt @@ -109,7 +109,7 @@ class TaskDetailScreenTest { ), onEditTask = { /*TODO*/ }, onBack = { }, - onDeleteTask = { }, + onDeleteTask = { } ) } } diff --git a/app/src/main/java/com/example/android/architecture/blueprints/todoapp/TodoNavGraph.kt b/app/src/main/java/com/example/android/architecture/blueprints/todoapp/TodoNavGraph.kt index c488d87d5..aa9e6c01a 100644 --- a/app/src/main/java/com/example/android/architecture/blueprints/todoapp/TodoNavGraph.kt +++ b/app/src/main/java/com/example/android/architecture/blueprints/todoapp/TodoNavGraph.kt @@ -65,7 +65,10 @@ fun TodoNavGraph( composable( TodoDestinations.TASKS_ROUTE, arguments = listOf( - navArgument(USER_MESSAGE_ARG) { type = NavType.IntType; defaultValue = 0 } + navArgument(USER_MESSAGE_ARG) { + type = NavType.IntType + defaultValue = 0 + } ) ) { entry -> AppModalDrawer(drawerState, currentRoute, navActions) { @@ -87,7 +90,10 @@ fun TodoNavGraph( TodoDestinations.ADD_EDIT_TASK_ROUTE, arguments = listOf( navArgument(TITLE_ARG) { type = NavType.IntType }, - navArgument(TASK_ID_ARG) { type = NavType.StringType; nullable = true }, + navArgument(TASK_ID_ARG) { + type = NavType.StringType + nullable = true + } ) ) { entry -> val taskId = entry.arguments?.getString(TASK_ID_ARG) diff --git a/app/src/main/java/com/example/android/architecture/blueprints/todoapp/addedittask/AddEditTaskScreen.kt b/app/src/main/java/com/example/android/architecture/blueprints/todoapp/addedittask/AddEditTaskScreen.kt index 0c4cfccf5..e9eed6e58 100644 --- a/app/src/main/java/com/example/android/architecture/blueprints/todoapp/addedittask/AddEditTaskScreen.kt +++ b/app/src/main/java/com/example/android/architecture/blueprints/todoapp/addedittask/AddEditTaskScreen.kt @@ -114,7 +114,7 @@ private fun AddEditTaskContent( // Show the loading spinner—`loading` is `true` in this code path state = rememberSwipeRefreshState(true), onRefresh = { /* DO NOTHING */ }, - content = { }, + content = { } ) } else { Column( diff --git a/app/src/main/java/com/example/android/architecture/blueprints/todoapp/addedittask/AddEditTaskViewModel.kt b/app/src/main/java/com/example/android/architecture/blueprints/todoapp/addedittask/AddEditTaskViewModel.kt index 247573042..828df5c4c 100644 --- a/app/src/main/java/com/example/android/architecture/blueprints/todoapp/addedittask/AddEditTaskViewModel.kt +++ b/app/src/main/java/com/example/android/architecture/blueprints/todoapp/addedittask/AddEditTaskViewModel.kt @@ -114,7 +114,7 @@ class AddEditTaskViewModel @Inject constructor( taskRepository.updateTask( taskId, title = uiState.value.title, - description = uiState.value.description, + description = uiState.value.description ) _uiState.update { it.copy(isTaskSaved = true) diff --git a/app/src/main/java/com/example/android/architecture/blueprints/todoapp/data/DefaultTaskRepository.kt b/app/src/main/java/com/example/android/architecture/blueprints/todoapp/data/DefaultTaskRepository.kt index 1be692081..2a29069b1 100644 --- a/app/src/main/java/com/example/android/architecture/blueprints/todoapp/data/DefaultTaskRepository.kt +++ b/app/src/main/java/com/example/android/architecture/blueprints/todoapp/data/DefaultTaskRepository.kt @@ -43,7 +43,7 @@ class DefaultTaskRepository @Inject constructor( private val networkDataSource: NetworkDataSource, private val localDataSource: TaskDao, @DefaultDispatcher private val dispatcher: CoroutineDispatcher, - @ApplicationScope private val scope: CoroutineScope, + @ApplicationScope private val scope: CoroutineScope ) : TaskRepository { override suspend fun createTask(title: String, description: String): String { @@ -55,7 +55,7 @@ class DefaultTaskRepository @Inject constructor( val task = Task( title = title, description = description, - id = taskId, + id = taskId ) localDataSource.upsert(task.toLocal()) saveTasksToNetwork() diff --git a/app/src/main/java/com/example/android/architecture/blueprints/todoapp/data/ModelMappingExt.kt b/app/src/main/java/com/example/android/architecture/blueprints/todoapp/data/ModelMappingExt.kt index 38b14282f..67014ec26 100644 --- a/app/src/main/java/com/example/android/architecture/blueprints/todoapp/data/ModelMappingExt.kt +++ b/app/src/main/java/com/example/android/architecture/blueprints/todoapp/data/ModelMappingExt.kt @@ -39,7 +39,7 @@ fun Task.toLocal() = LocalTask( id = id, title = title, description = description, - isCompleted = isCompleted, + isCompleted = isCompleted ) fun List.toLocal() = map(Task::toLocal) @@ -49,7 +49,7 @@ fun LocalTask.toExternal() = Task( id = id, title = title, description = description, - isCompleted = isCompleted, + isCompleted = isCompleted ) // Note: JvmName is used to provide a unique name for each extension function with the same name. @@ -63,7 +63,7 @@ fun NetworkTask.toLocal() = LocalTask( id = id, title = title, description = shortDescription, - isCompleted = (status == TaskStatus.COMPLETE), + isCompleted = (status == TaskStatus.COMPLETE) ) @JvmName("networkToLocal") @@ -74,7 +74,11 @@ fun LocalTask.toNetwork() = NetworkTask( id = id, title = title, shortDescription = description, - status = if (isCompleted) { TaskStatus.COMPLETE } else { TaskStatus.ACTIVE } + status = if (isCompleted) { + TaskStatus.COMPLETE + } else { + TaskStatus.ACTIVE + } ) fun List.toNetwork() = map(LocalTask::toNetwork) diff --git a/app/src/main/java/com/example/android/architecture/blueprints/todoapp/data/Task.kt b/app/src/main/java/com/example/android/architecture/blueprints/todoapp/data/Task.kt index 91377071c..2752b3466 100644 --- a/app/src/main/java/com/example/android/architecture/blueprints/todoapp/data/Task.kt +++ b/app/src/main/java/com/example/android/architecture/blueprints/todoapp/data/Task.kt @@ -31,7 +31,7 @@ data class Task( val title: String = "", val description: String = "", val isCompleted: Boolean = false, - val id: String, + val id: String ) { val titleForList: String diff --git a/app/src/main/java/com/example/android/architecture/blueprints/todoapp/data/source/local/LocalTask.kt b/app/src/main/java/com/example/android/architecture/blueprints/todoapp/data/source/local/LocalTask.kt index 9d9b084e4..0b49b78f8 100644 --- a/app/src/main/java/com/example/android/architecture/blueprints/todoapp/data/source/local/LocalTask.kt +++ b/app/src/main/java/com/example/android/architecture/blueprints/todoapp/data/source/local/LocalTask.kt @@ -33,5 +33,5 @@ data class LocalTask( @PrimaryKey val id: String, var title: String, var description: String, - var isCompleted: Boolean, + var isCompleted: Boolean ) diff --git a/app/src/main/java/com/example/android/architecture/blueprints/todoapp/di/CoroutinesModule.kt b/app/src/main/java/com/example/android/architecture/blueprints/todoapp/di/CoroutinesModule.kt index 262d52e39..bc88b8c24 100644 --- a/app/src/main/java/com/example/android/architecture/blueprints/todoapp/di/CoroutinesModule.kt +++ b/app/src/main/java/com/example/android/architecture/blueprints/todoapp/di/CoroutinesModule.kt @@ -54,7 +54,6 @@ object CoroutinesModule { @Provides @Singleton @ApplicationScope - fun providesCoroutineScope( - @DefaultDispatcher dispatcher: CoroutineDispatcher - ): CoroutineScope = CoroutineScope(SupervisorJob() + dispatcher) + fun providesCoroutineScope(@DefaultDispatcher dispatcher: CoroutineDispatcher): CoroutineScope = + CoroutineScope(SupervisorJob() + dispatcher) } diff --git a/app/src/main/java/com/example/android/architecture/blueprints/todoapp/statistics/StatisticsViewModel.kt b/app/src/main/java/com/example/android/architecture/blueprints/todoapp/statistics/StatisticsViewModel.kt index 4db5c1f22..43773f50e 100644 --- a/app/src/main/java/com/example/android/architecture/blueprints/todoapp/statistics/StatisticsViewModel.kt +++ b/app/src/main/java/com/example/android/architecture/blueprints/todoapp/statistics/StatisticsViewModel.kt @@ -66,23 +66,22 @@ class StatisticsViewModel @Inject constructor( } } - private fun produceStatisticsUiState(taskLoad: Async>) = - when (taskLoad) { - Async.Loading -> { - StatisticsUiState(isLoading = true, isEmpty = true) - } - is Async.Error -> { - // TODO: Show error message? - StatisticsUiState(isEmpty = true, isLoading = false) - } - is Async.Success -> { - val stats = getActiveAndCompletedStats(taskLoad.data) - StatisticsUiState( - isEmpty = taskLoad.data.isEmpty(), - activeTasksPercent = stats.activeTasksPercent, - completedTasksPercent = stats.completedTasksPercent, - isLoading = false - ) - } + private fun produceStatisticsUiState(taskLoad: Async>) = when (taskLoad) { + Async.Loading -> { + StatisticsUiState(isLoading = true, isEmpty = true) } + is Async.Error -> { + // TODO: Show error message? + StatisticsUiState(isEmpty = true, isLoading = false) + } + is Async.Success -> { + val stats = getActiveAndCompletedStats(taskLoad.data) + StatisticsUiState( + isEmpty = taskLoad.data.isEmpty(), + activeTasksPercent = stats.activeTasksPercent, + completedTasksPercent = stats.completedTasksPercent, + isLoading = false + ) + } + } } diff --git a/app/src/main/java/com/example/android/architecture/blueprints/todoapp/statistics/StatisticsUtils.kt b/app/src/main/java/com/example/android/architecture/blueprints/todoapp/statistics/StatsResult.kt similarity index 99% rename from app/src/main/java/com/example/android/architecture/blueprints/todoapp/statistics/StatisticsUtils.kt rename to app/src/main/java/com/example/android/architecture/blueprints/todoapp/statistics/StatsResult.kt index 99942a94c..5524f412c 100644 --- a/app/src/main/java/com/example/android/architecture/blueprints/todoapp/statistics/StatisticsUtils.kt +++ b/app/src/main/java/com/example/android/architecture/blueprints/todoapp/statistics/StatsResult.kt @@ -22,7 +22,6 @@ import com.example.android.architecture.blueprints.todoapp.data.Task * Function that does some trivial computation. Used to showcase unit tests. */ internal fun getActiveAndCompletedStats(tasks: List): StatsResult { - return if (tasks.isEmpty()) { StatsResult(0f, 0f) } else { diff --git a/app/src/main/java/com/example/android/architecture/blueprints/todoapp/taskdetail/TaskDetailScreen.kt b/app/src/main/java/com/example/android/architecture/blueprints/todoapp/taskdetail/TaskDetailScreen.kt index 99e3ca8db..e76f81a1e 100644 --- a/app/src/main/java/com/example/android/architecture/blueprints/todoapp/taskdetail/TaskDetailScreen.kt +++ b/app/src/main/java/com/example/android/architecture/blueprints/todoapp/taskdetail/TaskDetailScreen.kt @@ -110,7 +110,7 @@ private fun EditTaskContent( ) { val screenPadding = Modifier.padding( horizontal = dimensionResource(id = R.dimen.horizontal_margin), - vertical = dimensionResource(id = R.dimen.vertical_margin), + vertical = dimensionResource(id = R.dimen.vertical_margin) ) val commonModifier = modifier .fillMaxWidth() @@ -131,7 +131,7 @@ private fun EditTaskContent( Row( Modifier .fillMaxWidth() - .then(screenPadding), + .then(screenPadding) ) { if (task != null) { diff --git a/app/src/main/java/com/example/android/architecture/blueprints/todoapp/taskdetail/TaskDetailViewModel.kt b/app/src/main/java/com/example/android/architecture/blueprints/todoapp/taskdetail/TaskDetailViewModel.kt index 080b22c04..2abb9979a 100644 --- a/app/src/main/java/com/example/android/architecture/blueprints/todoapp/taskdetail/TaskDetailViewModel.kt +++ b/app/src/main/java/com/example/android/architecture/blueprints/todoapp/taskdetail/TaskDetailViewModel.kt @@ -56,15 +56,18 @@ class TaskDetailViewModel @Inject constructor( val taskId: String = savedStateHandle[TodoDestinationsArgs.TASK_ID_ARG]!! - private val _userMessage: MutableStateFlow = MutableStateFlow(null) - private val _isLoading = MutableStateFlow(false) - private val _isTaskDeleted = MutableStateFlow(false) - private val _taskAsync = taskRepository.getTaskStream(taskId) + private val userMessage: MutableStateFlow = MutableStateFlow(null) + private val isLoading = MutableStateFlow(false) + private val isTaskDeleted = MutableStateFlow(false) + private val taskAsync = taskRepository.getTaskStream(taskId) .map { handleTask(it) } .catch { emit(Async.Error(R.string.loading_task_error)) } val uiState: StateFlow = combine( - _userMessage, _isLoading, _isTaskDeleted, _taskAsync + userMessage, + isLoading, + isTaskDeleted, + taskAsync ) { userMessage, isLoading, isTaskDeleted, taskAsync -> when (taskAsync) { Async.Loading -> { @@ -94,7 +97,7 @@ class TaskDetailViewModel @Inject constructor( fun deleteTask() = viewModelScope.launch { taskRepository.deleteTask(taskId) - _isTaskDeleted.value = true + isTaskDeleted.value = true } fun setCompleted(completed: Boolean) = viewModelScope.launch { @@ -109,19 +112,19 @@ class TaskDetailViewModel @Inject constructor( } fun refresh() { - _isLoading.value = true + isLoading.value = true viewModelScope.launch { taskRepository.refreshTask(taskId) - _isLoading.value = false + isLoading.value = false } } fun snackbarMessageShown() { - _userMessage.value = null + userMessage.value = null } private fun showSnackbarMessage(message: Int) { - _userMessage.value = message + userMessage.value = message } private fun handleTask(task: Task?): Async { diff --git a/app/src/main/java/com/example/android/architecture/blueprints/todoapp/tasks/TasksScreen.kt b/app/src/main/java/com/example/android/architecture/blueprints/todoapp/tasks/TasksScreen.kt index 964512754..2aaf793af 100644 --- a/app/src/main/java/com/example/android/architecture/blueprints/todoapp/tasks/TasksScreen.kt +++ b/app/src/main/java/com/example/android/architecture/blueprints/todoapp/tasks/TasksScreen.kt @@ -172,18 +172,14 @@ private fun TasksContent( } @Composable -private fun TaskItem( - task: Task, - onCheckedChange: (Boolean) -> Unit, - onTaskClick: (Task) -> Unit -) { +private fun TaskItem(task: Task, onCheckedChange: (Boolean) -> Unit, onTaskClick: (Task) -> Unit) { Row( verticalAlignment = Alignment.CenterVertically, modifier = Modifier .fillMaxWidth() .padding( horizontal = dimensionResource(id = R.dimen.horizontal_margin), - vertical = dimensionResource(id = R.dimen.list_item_padding), + vertical = dimensionResource(id = R.dimen.list_item_padding) ) .clickable { onTaskClick(task) } ) { @@ -263,14 +259,14 @@ private fun TasksContentPreview() { description = "Description 5", isCompleted = true, id = "ID 5" - ), + ) ), currentFilteringLabel = R.string.label_all, noTasksLabel = R.string.no_tasks_all, noTasksIconRes = R.drawable.logo_no_fill, onRefresh = { }, onTaskClick = { }, - onTaskCheckedChange = { _, _ -> }, + onTaskCheckedChange = { _, _ -> } ) } } @@ -289,7 +285,7 @@ private fun TasksContentEmptyPreview() { noTasksIconRes = R.drawable.logo_no_fill, onRefresh = { }, onTaskClick = { }, - onTaskCheckedChange = { _, _ -> }, + onTaskCheckedChange = { _, _ -> } ) } } diff --git a/app/src/main/java/com/example/android/architecture/blueprints/todoapp/tasks/TasksViewModel.kt b/app/src/main/java/com/example/android/architecture/blueprints/todoapp/tasks/TasksViewModel.kt index 9868f80a7..b6930e881 100644 --- a/app/src/main/java/com/example/android/architecture/blueprints/todoapp/tasks/TasksViewModel.kt +++ b/app/src/main/java/com/example/android/architecture/blueprints/todoapp/tasks/TasksViewModel.kt @@ -60,21 +60,24 @@ class TasksViewModel @Inject constructor( private val savedStateHandle: SavedStateHandle ) : ViewModel() { - private val _savedFilterType = + private val savedFilterType = savedStateHandle.getStateFlow(TASKS_FILTER_SAVED_STATE_KEY, ALL_TASKS) - private val _filterUiInfo = _savedFilterType.map { getFilterUiInfo(it) }.distinctUntilChanged() - private val _userMessage: MutableStateFlow = MutableStateFlow(null) - private val _isLoading = MutableStateFlow(false) - private val _filteredTasksAsync = - combine(taskRepository.getTasksStream(), _savedFilterType) { tasks, type -> + private val filterUiInfo = savedFilterType.map { getFilterUiInfo(it) }.distinctUntilChanged() + private val userMessage: MutableStateFlow = MutableStateFlow(null) + private val isLoading = MutableStateFlow(false) + private val filteredTasksAsync = + combine(taskRepository.getTasksStream(), savedFilterType) { tasks, type -> filterTasks(tasks, type) } .map { Async.Success(it) } .catch>> { emit(Async.Error(R.string.loading_tasks_error)) } val uiState: StateFlow = combine( - _filterUiInfo, _isLoading, _userMessage, _filteredTasksAsync + filterUiInfo, + isLoading, + userMessage, + filteredTasksAsync ) { filterUiInfo, isLoading, userMessage, tasksAsync -> when (tasksAsync) { Async.Loading -> { @@ -130,18 +133,18 @@ class TasksViewModel @Inject constructor( } fun snackbarMessageShown() { - _userMessage.value = null + userMessage.value = null } private fun showSnackbarMessage(message: Int) { - _userMessage.value = message + userMessage.value = message } fun refresh() { - _isLoading.value = true + isLoading.value = true viewModelScope.launch { taskRepository.refresh() - _isLoading.value = false + isLoading.value = false } } @@ -166,19 +169,22 @@ class TasksViewModel @Inject constructor( when (requestType) { ALL_TASKS -> { FilteringUiInfo( - R.string.label_all, R.string.no_tasks_all, + R.string.label_all, + R.string.no_tasks_all, R.drawable.logo_no_fill ) } ACTIVE_TASKS -> { FilteringUiInfo( - R.string.label_active, R.string.no_tasks_active, + R.string.label_active, + R.string.no_tasks_active, R.drawable.ic_check_circle_96dp ) } COMPLETED_TASKS -> { FilteringUiInfo( - R.string.label_completed, R.string.no_tasks_completed, + R.string.label_completed, + R.string.no_tasks_completed, R.drawable.ic_verified_user_96dp ) } @@ -191,5 +197,5 @@ const val TASKS_FILTER_SAVED_STATE_KEY = "TASKS_FILTER_SAVED_STATE_KEY" data class FilteringUiInfo( val currentFilteringLabel: Int = R.string.label_all, val noTasksLabel: Int = R.string.no_tasks_all, - val noTaskIconRes: Int = R.drawable.logo_no_fill, + val noTaskIconRes: Int = R.drawable.logo_no_fill ) diff --git a/app/src/main/java/com/example/android/architecture/blueprints/todoapp/util/ComposeUtils.kt b/app/src/main/java/com/example/android/architecture/blueprints/todoapp/util/ComposeUtils.kt index 84d641712..7ba7ae60f 100644 --- a/app/src/main/java/com/example/android/architecture/blueprints/todoapp/util/ComposeUtils.kt +++ b/app/src/main/java/com/example/android/architecture/blueprints/todoapp/util/ComposeUtils.kt @@ -50,7 +50,7 @@ fun LoadingContent( state = rememberSwipeRefreshState(loading), onRefresh = onRefresh, modifier = modifier, - content = content, + content = content ) } } diff --git a/app/src/main/java/com/example/android/architecture/blueprints/todoapp/util/CoroutinesUtils.kt b/app/src/main/java/com/example/android/architecture/blueprints/todoapp/util/CoroutinesUtils.kt index 318b2c90e..ed6c8ea86 100644 --- a/app/src/main/java/com/example/android/architecture/blueprints/todoapp/util/CoroutinesUtils.kt +++ b/app/src/main/java/com/example/android/architecture/blueprints/todoapp/util/CoroutinesUtils.kt @@ -18,7 +18,7 @@ package com.example.android.architecture.blueprints.todoapp.util import kotlinx.coroutines.flow.SharingStarted -private const val StopTimeoutMillis: Long = 5000 +private const val STOP_TIMEOUT_MILLIS: Long = 5000 /** * A [SharingStarted] meant to be used with a [StateFlow] to expose data to the UI. @@ -29,4 +29,4 @@ private const val StopTimeoutMillis: Long = 5000 * back, the latest value is replayed and the upstream flows are executed again. This is done to * save resources when the app is in the background but let users switch between apps quickly. */ -val WhileUiSubscribed: SharingStarted = SharingStarted.WhileSubscribed(StopTimeoutMillis) +val WhileUiSubscribed: SharingStarted = SharingStarted.WhileSubscribed(STOP_TIMEOUT_MILLIS) diff --git a/app/src/main/java/com/example/android/architecture/blueprints/todoapp/util/TodoDrawer.kt b/app/src/main/java/com/example/android/architecture/blueprints/todoapp/util/TodoDrawer.kt index 8e5ed06af..18b850b00 100644 --- a/app/src/main/java/com/example/android/architecture/blueprints/todoapp/util/TodoDrawer.kt +++ b/app/src/main/java/com/example/android/architecture/blueprints/todoapp/util/TodoDrawer.kt @@ -106,9 +106,7 @@ private fun AppDrawer( } @Composable -private fun DrawerHeader( - modifier: Modifier = Modifier -) { +private fun DrawerHeader(modifier: Modifier = Modifier) { Column( horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center, @@ -158,7 +156,8 @@ private fun DrawerButton( ) { Icon( painter = painter, - contentDescription = null, // decorative + // decorative + contentDescription = null, tint = tintColor ) Spacer(Modifier.width(16.dp)) diff --git a/app/src/main/java/com/example/android/architecture/blueprints/todoapp/util/TopAppBars.kt b/app/src/main/java/com/example/android/architecture/blueprints/todoapp/util/TopAppBars.kt index abf26cc2e..2ab4bab07 100644 --- a/app/src/main/java/com/example/android/architecture/blueprints/todoapp/util/TopAppBars.kt +++ b/app/src/main/java/com/example/android/architecture/blueprints/todoapp/util/TopAppBars.kt @@ -84,32 +84,44 @@ private fun FilterTasksMenu( ) } ) { closeMenu -> - DropdownMenuItem(onClick = { onFilterAllTasks(); closeMenu() }) { + DropdownMenuItem(onClick = { + onFilterAllTasks() + closeMenu() + }) { Text(text = stringResource(id = R.string.nav_all)) } - DropdownMenuItem(onClick = { onFilterActiveTasks(); closeMenu() }) { + DropdownMenuItem(onClick = { + onFilterActiveTasks() + closeMenu() + }) { Text(text = stringResource(id = R.string.nav_active)) } - DropdownMenuItem(onClick = { onFilterCompletedTasks(); closeMenu() }) { + DropdownMenuItem(onClick = { + onFilterCompletedTasks() + closeMenu() + }) { Text(text = stringResource(id = R.string.nav_completed)) } } } @Composable -private fun MoreTasksMenu( - onClearCompletedTasks: () -> Unit, - onRefresh: () -> Unit -) { +private fun MoreTasksMenu(onClearCompletedTasks: () -> Unit, onRefresh: () -> Unit) { TopAppBarDropdownMenu( iconContent = { Icon(Icons.Filled.MoreVert, stringResource(id = R.string.menu_more)) } ) { closeMenu -> - DropdownMenuItem(onClick = { onClearCompletedTasks(); closeMenu() }) { + DropdownMenuItem(onClick = { + onClearCompletedTasks() + closeMenu() + }) { Text(text = stringResource(id = R.string.menu_clear)) } - DropdownMenuItem(onClick = { onRefresh(); closeMenu() }) { + DropdownMenuItem(onClick = { + onRefresh() + closeMenu() + }) { Text(text = stringResource(id = R.string.refresh)) } } diff --git a/app/src/test/java/com/example/android/architecture/blueprints/todoapp/data/DefaultTaskRepositoryTest.kt b/app/src/test/java/com/example/android/architecture/blueprints/todoapp/data/DefaultTaskRepositoryTest.kt index 1c41c8654..39a69cf22 100644 --- a/app/src/test/java/com/example/android/architecture/blueprints/todoapp/data/DefaultTaskRepositoryTest.kt +++ b/app/src/test/java/com/example/android/architecture/blueprints/todoapp/data/DefaultTaskRepositoryTest.kt @@ -144,14 +144,13 @@ class DefaultTaskRepositoryTest { } @Test - fun getTasks_WithRemoteDataSourceUnavailable_tasksAreRetrievedFromLocal() = - testScope.runTest { - // When the remote data source is unavailable - networkDataSource.tasks = null - - // The repository fetches from the local source - assertThat(taskRepository.getTasks()).isEqualTo(localTasks.toExternal()) - } + fun getTasks_WithRemoteDataSourceUnavailable_tasksAreRetrievedFromLocal() = testScope.runTest { + // When the remote data source is unavailable + networkDataSource.tasks = null + + // The repository fetches from the local source + assertThat(taskRepository.getTasks()).isEqualTo(localTasks.toExternal()) + } @Test(expected = Exception::class) fun getTasks_WithBothDataSourcesUnavailable_throwsError() = testScope.runTest { diff --git a/app/src/test/java/com/example/android/architecture/blueprints/todoapp/statistics/StatisticsUtilsTest.kt b/app/src/test/java/com/example/android/architecture/blueprints/todoapp/statistics/StatisticsUtilsTest.kt index d35aab169..0c5a59482 100644 --- a/app/src/test/java/com/example/android/architecture/blueprints/todoapp/statistics/StatisticsUtilsTest.kt +++ b/app/src/test/java/com/example/android/architecture/blueprints/todoapp/statistics/StatisticsUtilsTest.kt @@ -33,7 +33,7 @@ class StatisticsUtilsTest { id = "id", title = "title", description = "desc", - isCompleted = false, + isCompleted = false ) ) // When the list of tasks is computed with an active task @@ -51,7 +51,7 @@ class StatisticsUtilsTest { id = "id", title = "title", description = "desc", - isCompleted = true, + isCompleted = true ) ) // When the list of tasks is computed with a completed task @@ -70,7 +70,7 @@ class StatisticsUtilsTest { Task(id = "2", title = "title", description = "desc", isCompleted = true), Task(id = "3", title = "title", description = "desc", isCompleted = true), Task(id = "4", title = "title", description = "desc", isCompleted = false), - Task(id = "5", title = "title", description = "desc", isCompleted = false), + Task(id = "5", title = "title", description = "desc", isCompleted = false) ) // When the list of tasks is computed val result = getActiveAndCompletedStats(tasks) diff --git a/gradle/init.gradle.kts b/gradle/init.gradle.kts index 82b61b7e4..fe51bef7f 100644 --- a/gradle/init.gradle.kts +++ b/gradle/init.gradle.kts @@ -18,10 +18,10 @@ // Spotless itself is not gradle configuration cache compliant. // Note that the init script needs to be run with the configuration cache turned off. -val ktlintVersion = "0.44.0" +val ktlintVersion = "1.1.1" initscript { - val spotlessVersion = "6.13.0" + val spotlessVersion = "6.25.0" repositories { mavenCentral() @@ -39,7 +39,15 @@ rootProject { kotlin { target("**/*.kt") targetExclude("**/build/**/*.kt") - ktlint(ktlintVersion).userData(mapOf("android" to "true")) + ktlint(ktlintVersion) + .editorConfigOverride( + mapOf( + "ktlint_code_style" to "android_studio", + // Avoid applying naming rules to Composable functions since they + // start with an uppercase letter. + "ktlint_function_naming_ignore_when_annotated_with" to "Composable" + ) + ) licenseHeaderFile(rootProject.file("spotless/copyright.kt")) } format("kts") {