Merge branch 'android:main' into main

pull/2092/head
Pichai Takengrach 6 months ago committed by GitHub
commit d691c81c15
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -10,7 +10,7 @@ Thanks for submitting a pull request. To accept your pull request we need you do
**Ensure tests pass and code is formatted correctly** **Ensure tests pass and code is formatted correctly**
- Run local tests on the `DemoDebug` variant by running `./gradlew testDemoDebug` - Run local tests on the `DemoDebug` variant by running `./gradlew testDemoDebug`
- Fix code formatting: `./gradlew --init-script gradle/init.gradle.kts spotlessApply` - Fix code formatting: `./gradlew spotlessApply`
**Add a description** **Add a description**

@ -48,7 +48,7 @@ jobs:
run: ./gradlew :build-logic:convention:check run: ./gradlew :build-logic:convention:check
- name: Check spotless - name: Check spotless
run: ./gradlew spotlessCheck --init-script gradle/init.gradle.kts --no-configuration-cache run: ./gradlew spotlessCheck
- name: Check Dependency Guard - name: Check Dependency Guard
id: dependencyguard_verify id: dependencyguard_verify

@ -4,7 +4,6 @@
<option name="executionName" /> <option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" /> <option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" /> <option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="--init-script=gradle/init.gradle.kts" />
<option name="taskDescriptions"> <option name="taskDescriptions">
<list /> <list />
</option> </option>

@ -26,7 +26,7 @@ The main Android app lives in the `app/` folder. Feature modules live in `featur
The app and Android libraries have two product flavors: `demo` and `prod`, and two build types: `debug` and `release`. The app and Android libraries have two product flavors: `demo` and `prod`, and two build types: `debug` and `release`.
- Build: `./gradlew assemble{Variant}`. Typically `assembleDemoDebug`. - Build: `./gradlew assemble{Variant}`. Typically `assembleDemoDebug`.
- Fix linting/formatting: `./gradlew --init-script gradle/init.gradle.kts spotlessApply` - Fix linting/formatting: `./gradlew spotlessApply`
- Run local tests: `./gradlew {variant}Test` - Run local tests: `./gradlew {variant}Test`
- Run single test: `./gradlew {variant}Test --tests "com.example.myapp.MyTestClass"` - Run single test: `./gradlew {variant}Test --tests "com.example.myapp.MyTestClass"`
- Run local screenshot tests: `./gradlew verifyRoborazziDemoDebug` - Run local screenshot tests: `./gradlew verifyRoborazziDemoDebug`

@ -54,7 +54,7 @@ graph TB
:core:data[data]:::android-library :core:data[data]:::android-library
:core:database[database]:::android-library :core:database[database]:::android-library
:core:datastore[datastore]:::android-library :core:datastore[datastore]:::android-library
:core:datastore-proto[datastore-proto]:::android-library :core:datastore-proto[datastore-proto]:::jvm-library
:core:designsystem[designsystem]:::android-library :core:designsystem[designsystem]:::android-library
:core:domain[domain]:::android-library :core:domain[domain]:::android-library
:core:model[model]:::jvm-library :core:model[model]:::jvm-library

@ -18,7 +18,7 @@ package com.google.samples.apps.nowinandroid.util
import android.util.Log import android.util.Log
import androidx.profileinstaller.ProfileVerifier import androidx.profileinstaller.ProfileVerifier
import com.google.samples.apps.nowinandroid.core.network.di.ApplicationScope import com.google.samples.apps.nowinandroid.core.common.network.di.ApplicationScope
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.guava.await import kotlinx.coroutines.guava.await
import kotlinx.coroutines.launch import kotlinx.coroutines.launch

@ -54,7 +54,7 @@ graph TB
:core:data[data]:::android-library :core:data[data]:::android-library
:core:database[database]:::android-library :core:database[database]:::android-library
:core:datastore[datastore]:::android-library :core:datastore[datastore]:::android-library
:core:datastore-proto[datastore-proto]:::android-library :core:datastore-proto[datastore-proto]:::jvm-library
:core:designsystem[designsystem]:::android-library :core:designsystem[designsystem]:::android-library
:core:domain[domain]:::android-library :core:domain[domain]:::android-library
:core:model[model]:::jvm-library :core:model[model]:::jvm-library

@ -45,6 +45,7 @@ dependencies {
compileOnly(libs.kotlin.gradlePlugin) compileOnly(libs.kotlin.gradlePlugin)
compileOnly(libs.ksp.gradlePlugin) compileOnly(libs.ksp.gradlePlugin)
compileOnly(libs.room.gradlePlugin) compileOnly(libs.room.gradlePlugin)
compileOnly(libs.spotless.gradlePlugin)
implementation(libs.truth) implementation(libs.truth)
lintChecks(libs.androidx.lint.gradle) lintChecks(libs.androidx.lint.gradle)
} }

@ -1,17 +1,17 @@
/* /*
* Copyright 2022 The Android Open Source Project * Copyright 2022 The Android Open Source Project
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* https://www.apache.org/licenses/LICENSE-2.0 * https://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import com.android.build.api.dsl.ApplicationExtension import com.android.build.api.dsl.ApplicationExtension

@ -1,17 +1,17 @@
/* /*
* Copyright 2022 The Android Open Source Project * Copyright 2022 The Android Open Source Project
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* https://www.apache.org/licenses/LICENSE-2.0 * https://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import com.android.build.api.dsl.ApplicationExtension import com.android.build.api.dsl.ApplicationExtension
@ -20,12 +20,13 @@ import com.google.samples.apps.nowinandroid.configureBadgingTasks
import com.google.samples.apps.nowinandroid.configureGradleManagedDevices import com.google.samples.apps.nowinandroid.configureGradleManagedDevices
import com.google.samples.apps.nowinandroid.configureKotlinAndroid import com.google.samples.apps.nowinandroid.configureKotlinAndroid
import com.google.samples.apps.nowinandroid.configurePrintApksTask import com.google.samples.apps.nowinandroid.configurePrintApksTask
import com.google.samples.apps.nowinandroid.configureSpotlessForAndroid
import org.gradle.api.Plugin import org.gradle.api.Plugin
import org.gradle.api.Project import org.gradle.api.Project
import org.gradle.kotlin.dsl.apply import org.gradle.kotlin.dsl.apply
import org.gradle.kotlin.dsl.configure import org.gradle.kotlin.dsl.configure
class AndroidApplicationConventionPlugin : Plugin<Project> { abstract class AndroidApplicationConventionPlugin : Plugin<Project> {
override fun apply(target: Project) { override fun apply(target: Project) {
with(target) { with(target) {
apply(plugin = "com.android.application") apply(plugin = "com.android.application")
@ -42,6 +43,7 @@ class AndroidApplicationConventionPlugin : Plugin<Project> {
configurePrintApksTask(this) configurePrintApksTask(this)
configureBadgingTasks(this) configureBadgingTasks(this)
} }
configureSpotlessForAndroid()
} }
} }
} }

@ -1,17 +1,17 @@
/* /*
* Copyright 2022 The Android Open Source Project * Copyright 2022 The Android Open Source Project
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* https://www.apache.org/licenses/LICENSE-2.0 * https://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import com.android.build.api.dsl.ApplicationExtension import com.android.build.api.dsl.ApplicationExtension
@ -41,7 +41,7 @@ class AndroidApplicationFirebaseConventionPlugin : Plugin<Project> {
datastore-proto brings in protobuf dependencies. These are the source of truth datastore-proto brings in protobuf dependencies. These are the source of truth
for Now in Android. for Now in Android.
That's why the duplicate classes from below dependencies are excluded. That's why the duplicate classes from below dependencies are excluded.
*/ */
exclude(group = "com.google.protobuf", module = "protobuf-javalite") exclude(group = "com.google.protobuf", module = "protobuf-javalite")
exclude(group = "com.google.firebase", module = "protolite-well-known-types") exclude(group = "com.google.firebase", module = "protolite-well-known-types")
} }

@ -1,17 +1,17 @@
/* /*
* Copyright 2023 The Android Open Source Project * Copyright 2023 The Android Open Source Project
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* https://www.apache.org/licenses/LICENSE-2.0 * https://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import com.android.build.api.dsl.ApplicationExtension import com.android.build.api.dsl.ApplicationExtension

@ -1,17 +1,17 @@
/* /*
* Copyright 2022 The Android Open Source Project * Copyright 2022 The Android Open Source Project
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* https://www.apache.org/licenses/LICENSE-2.0 * https://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import com.android.build.api.dsl.ApplicationExtension import com.android.build.api.dsl.ApplicationExtension

@ -1,20 +1,19 @@
/* /*
* Copyright 2022 The Android Open Source Project * Copyright 2022 The Android Open Source Project
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* https://www.apache.org/licenses/LICENSE-2.0 * https://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import com.google.samples.apps.nowinandroid.libs
import org.gradle.api.Plugin import org.gradle.api.Plugin
import org.gradle.api.Project import org.gradle.api.Project
import org.gradle.kotlin.dsl.apply import org.gradle.kotlin.dsl.apply

@ -1,17 +1,17 @@
/* /*
* Copyright 2022 The Android Open Source Project * Copyright 2022 The Android Open Source Project
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* https://www.apache.org/licenses/LICENSE-2.0 * https://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import com.android.build.api.dsl.LibraryExtension import com.android.build.api.dsl.LibraryExtension

@ -1,17 +1,17 @@
/* /*
* Copyright 2022 The Android Open Source Project * Copyright 2022 The Android Open Source Project
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* https://www.apache.org/licenses/LICENSE-2.0 * https://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import com.android.build.api.dsl.LibraryExtension import com.android.build.api.dsl.LibraryExtension

@ -1,17 +1,17 @@
/* /*
* Copyright 2022 The Android Open Source Project * Copyright 2022 The Android Open Source Project
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* https://www.apache.org/licenses/LICENSE-2.0 * https://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import com.android.build.api.dsl.LibraryExtension import com.android.build.api.dsl.LibraryExtension
@ -20,6 +20,7 @@ import com.google.samples.apps.nowinandroid.configureFlavors
import com.google.samples.apps.nowinandroid.configureGradleManagedDevices import com.google.samples.apps.nowinandroid.configureGradleManagedDevices
import com.google.samples.apps.nowinandroid.configureKotlinAndroid import com.google.samples.apps.nowinandroid.configureKotlinAndroid
import com.google.samples.apps.nowinandroid.configurePrintApksTask import com.google.samples.apps.nowinandroid.configurePrintApksTask
import com.google.samples.apps.nowinandroid.configureSpotlessForAndroid
import com.google.samples.apps.nowinandroid.disableUnnecessaryAndroidTests import com.google.samples.apps.nowinandroid.disableUnnecessaryAndroidTests
import com.google.samples.apps.nowinandroid.libs import com.google.samples.apps.nowinandroid.libs
import org.gradle.api.Plugin import org.gradle.api.Plugin
@ -28,7 +29,7 @@ import org.gradle.kotlin.dsl.apply
import org.gradle.kotlin.dsl.configure import org.gradle.kotlin.dsl.configure
import org.gradle.kotlin.dsl.dependencies import org.gradle.kotlin.dsl.dependencies
class AndroidLibraryConventionPlugin : Plugin<Project> { abstract class AndroidLibraryConventionPlugin : Plugin<Project> {
override fun apply(target: Project) { override fun apply(target: Project) {
with(target) { with(target) {
apply(plugin = "com.android.library") apply(plugin = "com.android.library")
@ -52,6 +53,7 @@ class AndroidLibraryConventionPlugin : Plugin<Project> {
configurePrintApksTask(this) configurePrintApksTask(this)
disableUnnecessaryAndroidTests(target) disableUnnecessaryAndroidTests(target)
} }
configureSpotlessForAndroid()
dependencies { dependencies {
"androidTestImplementation"(libs.findLibrary("kotlin.test").get()) "androidTestImplementation"(libs.findLibrary("kotlin.test").get())
"testImplementation"(libs.findLibrary("kotlin.test").get()) "testImplementation"(libs.findLibrary("kotlin.test").get())

@ -1,17 +1,17 @@
/* /*
* Copyright 2022 The Android Open Source Project * Copyright 2022 The Android Open Source Project
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* https://www.apache.org/licenses/LICENSE-2.0 * https://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import com.android.build.api.dsl.LibraryExtension import com.android.build.api.dsl.LibraryExtension

@ -1,17 +1,17 @@
/* /*
* Copyright 2022 The Android Open Source Project * Copyright 2022 The Android Open Source Project
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* https://www.apache.org/licenses/LICENSE-2.0 * https://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import com.android.build.api.dsl.ApplicationExtension import com.android.build.api.dsl.ApplicationExtension

@ -1,17 +1,17 @@
/* /*
* Copyright 2022 The Android Open Source Project * Copyright 2022 The Android Open Source Project
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* https://www.apache.org/licenses/LICENSE-2.0 * https://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import androidx.room.gradle.RoomExtension import androidx.room.gradle.RoomExtension

@ -1,17 +1,17 @@
/* /*
* Copyright 2022 The Android Open Source Project * Copyright 2022 The Android Open Source Project
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* https://www.apache.org/licenses/LICENSE-2.0 * https://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import com.android.build.api.dsl.TestExtension import com.android.build.api.dsl.TestExtension

@ -1,17 +1,17 @@
/* /*
* Copyright 2023 The Android Open Source Project * Copyright 2023 The Android Open Source Project
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* https://www.apache.org/licenses/LICENSE-2.0 * https://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import com.android.build.gradle.api.AndroidBasePlugin import com.android.build.gradle.api.AndroidBasePlugin

@ -1,33 +1,35 @@
/* /*
* Copyright 2023 The Android Open Source Project * Copyright 2023 The Android Open Source Project
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* https://www.apache.org/licenses/LICENSE-2.0 * https://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import com.google.samples.apps.nowinandroid.configureKotlinJvm import com.google.samples.apps.nowinandroid.configureKotlinJvm
import com.google.samples.apps.nowinandroid.configureSpotlessForJvm
import com.google.samples.apps.nowinandroid.libs import com.google.samples.apps.nowinandroid.libs
import org.gradle.api.Plugin import org.gradle.api.Plugin
import org.gradle.api.Project import org.gradle.api.Project
import org.gradle.kotlin.dsl.apply import org.gradle.kotlin.dsl.apply
import org.gradle.kotlin.dsl.dependencies import org.gradle.kotlin.dsl.dependencies
class JvmLibraryConventionPlugin : Plugin<Project> { abstract class JvmLibraryConventionPlugin : Plugin<Project> {
override fun apply(target: Project) { override fun apply(target: Project) {
with(target) { with(target) {
apply(plugin = "org.jetbrains.kotlin.jvm") apply(plugin = "org.jetbrains.kotlin.jvm")
apply(plugin = "nowinandroid.android.lint") apply(plugin = "nowinandroid.android.lint")
configureKotlinJvm() configureKotlinJvm()
configureSpotlessForJvm()
dependencies { dependencies {
"testImplementation"(libs.findLibrary("kotlin.test").get()) "testImplementation"(libs.findLibrary("kotlin.test").get())
} }

@ -15,12 +15,24 @@
*/ */
import com.google.samples.apps.nowinandroid.configureGraphTasks import com.google.samples.apps.nowinandroid.configureGraphTasks
import com.google.samples.apps.nowinandroid.configureSpotlessForRootProject
import org.gradle.api.Plugin import org.gradle.api.Plugin
import org.gradle.api.Project import org.gradle.api.Project
import org.gradle.api.configuration.BuildFeatures
import javax.inject.Inject
abstract class RootPlugin : Plugin<Project> {
@get:Inject abstract val buildFeatures: BuildFeatures
class RootPlugin : Plugin<Project> {
override fun apply(target: Project) { override fun apply(target: Project) {
require(target.path == ":") require(target.path == ":")
target.subprojects { configureGraphTasks() } if (!buildFeatures.isIsolatedProjectsEnabled()) {
target.subprojects { configureGraphTasks() }
}
target.configureSpotlessForRootProject()
} }
} }
private fun BuildFeatures.isIsolatedProjectsEnabled(): Boolean {
return isolatedProjects.active.getOrElse(false)
}

@ -1,17 +1,17 @@
/* /*
* Copyright 2023 The Android Open Source Project * Copyright 2023 The Android Open Source Project
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* https://www.apache.org/licenses/LICENSE-2.0 * https://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.google.samples.apps.nowinandroid package com.google.samples.apps.nowinandroid
@ -30,6 +30,6 @@ import org.gradle.api.Project
internal fun LibraryAndroidComponentsExtension.disableUnnecessaryAndroidTests( internal fun LibraryAndroidComponentsExtension.disableUnnecessaryAndroidTests(
project: Project, project: Project,
) = beforeVariants { ) = beforeVariants {
it.androidTest.enable = it.androidTest.enable it.androidTest.enable = it.androidTest.enable &&
&& project.projectDir.resolve("src/androidTest").exists() project.projectDir.resolve("src/androidTest").exists()
} }

@ -1,17 +1,17 @@
/* /*
* Copyright 2023 The Android Open Source Project * Copyright 2023 The Android Open Source Project
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* https://www.apache.org/licenses/LICENSE-2.0 * https://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.google.samples.apps.nowinandroid package com.google.samples.apps.nowinandroid
@ -123,7 +123,6 @@ fun Project.configureBadgingTasks(
badging = project.layout.buildDirectory.file( badging = project.layout.buildDirectory.file(
"outputs/apk_from_bundle/${variant.name}/${variant.name}-badging.txt", "outputs/apk_from_bundle/${variant.name}/${variant.name}-badging.txt",
) )
} }
val updateBadgingTaskName = "update${capitalizedVariantName}Badging" val updateBadgingTaskName = "update${capitalizedVariantName}Badging"
@ -141,7 +140,6 @@ fun Project.configureBadgingTasks(
this.updateBadgingTaskName = updateBadgingTaskName this.updateBadgingTaskName = updateBadgingTaskName
output = project.layout.buildDirectory.dir("intermediates/$checkBadgingTaskName") output = project.layout.buildDirectory.dir("intermediates/$checkBadgingTaskName")
} }
} }
} }

@ -1,17 +1,17 @@
/* /*
* Copyright 2023 The Android Open Source Project * Copyright 2023 The Android Open Source Project
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* https://www.apache.org/licenses/LICENSE-2.0 * https://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.google.samples.apps.nowinandroid package com.google.samples.apps.nowinandroid
@ -34,7 +34,6 @@ internal fun configureGradleManagedDevices(
val allDevices = listOf(pixel4, pixel6, pixelC) val allDevices = listOf(pixel4, pixel6, pixelC)
val ciDevices = listOf(pixel4, pixelC) val ciDevices = listOf(pixel4, pixelC)
commonExtension.testOptions.apply { commonExtension.testOptions.apply {
@Suppress("UnstableApiUsage") @Suppress("UnstableApiUsage")
managedDevices { managedDevices {

@ -17,12 +17,10 @@
package com.google.samples.apps.nowinandroid package com.google.samples.apps.nowinandroid
import com.android.build.api.artifact.ScopedArtifact import com.android.build.api.artifact.ScopedArtifact
import com.android.build.api.dsl.BuildType
import com.android.build.api.dsl.CommonExtension import com.android.build.api.dsl.CommonExtension
import com.android.build.api.variant.AndroidComponentsExtension import com.android.build.api.variant.AndroidComponentsExtension
import com.android.build.api.variant.ScopedArtifacts import com.android.build.api.variant.ScopedArtifacts
import com.android.build.api.variant.SourceDirectories import com.android.build.api.variant.SourceDirectories
import org.gradle.api.NamedDomainObjectContainer
import org.gradle.api.Project import org.gradle.api.Project
import org.gradle.api.file.Directory import org.gradle.api.file.Directory
import org.gradle.api.file.RegularFile import org.gradle.api.file.RegularFile
@ -86,7 +84,6 @@ internal fun Project.configureJacoco(
"create${variant.name.capitalize()}CombinedCoverageReport", "create${variant.name.capitalize()}CombinedCoverageReport",
JacocoReport::class, JacocoReport::class,
) { ) {
classDirectories.setFrom( classDirectories.setFrom(
allJars, allJars,
allDirectories.map { dirs -> allDirectories.map { dirs ->
@ -107,7 +104,7 @@ internal fun Project.configureJacoco(
sourceDirectories.setFrom( sourceDirectories.setFrom(
files( files(
variant.sources.java.toFilePaths(), variant.sources.java.toFilePaths(),
variant.sources.kotlin.toFilePaths() variant.sources.kotlin.toFilePaths(),
), ),
) )
@ -120,7 +117,6 @@ internal fun Project.configureJacoco(
) )
} }
variant.artifacts.forScope(ScopedArtifacts.Scope.PROJECT) variant.artifacts.forScope(ScopedArtifacts.Scope.PROJECT)
.use(reportTask) .use(reportTask)
.toGet( .toGet(

@ -103,7 +103,7 @@ private inline fun <reified T : KotlinBaseExtension> Project.configureKotlin() =
* The binary signature changes. The error on the declaration is no longer reported. * The binary signature changes. The error on the declaration is no longer reported.
* '-Xconsistent-data-class-copy-visibility' compiler flag and ConsistentCopyVisibility annotation are now unnecessary. * '-Xconsistent-data-class-copy-visibility' compiler flag and ConsistentCopyVisibility annotation are now unnecessary.
*/ */
"-Xconsistent-data-class-copy-visibility" "-Xconsistent-data-class-copy-visibility",
) )
} }
} }

@ -1,17 +1,17 @@
/* /*
* Copyright 2022 The Android Open Source Project * Copyright 2022 The Android Open Source Project
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* https://www.apache.org/licenses/LICENSE-2.0 * https://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.google.samples.apps.nowinandroid package com.google.samples.apps.nowinandroid

@ -1,3 +1,19 @@
/*
* Copyright 2026 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.samples.apps.nowinandroid package com.google.samples.apps.nowinandroid
import com.android.build.api.dsl.ApplicationExtension import com.android.build.api.dsl.ApplicationExtension
@ -8,7 +24,7 @@ import org.gradle.kotlin.dsl.invoke
@Suppress("EnumEntryName") @Suppress("EnumEntryName")
enum class FlavorDimension { enum class FlavorDimension {
contentType contentType,
} }
// The content for the app can either come from local static data which is useful for demo // The content for the app can either come from local static data which is useful for demo

@ -1,17 +1,17 @@
/* /*
* Copyright 2022 The Android Open Source Project * Copyright 2022 The Android Open Source Project
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* https://www.apache.org/licenses/LICENSE-2.0 * https://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.google.samples.apps.nowinandroid package com.google.samples.apps.nowinandroid
@ -49,7 +49,9 @@ internal fun Project.configurePrintApksTask(extension: AndroidComponentsExtensio
javaSources.zip(kotlinSources) { javaDirs, kotlinDirs -> javaSources.zip(kotlinSources) { javaDirs, kotlinDirs ->
javaDirs + kotlinDirs javaDirs + kotlinDirs
} }
} else javaSources ?: kotlinSources } else {
javaSources ?: kotlinSources
}
if (artifact != null && testSources != null) { if (artifact != null && testSources != null) {
tasks.register( tasks.register(
@ -96,8 +98,9 @@ internal abstract class PrintApkLocationTask : DefaultTask() {
val builtArtifacts = builtArtifactsLoader.get().load(apkFolder.get()) val builtArtifacts = builtArtifactsLoader.get().load(apkFolder.get())
?: throw RuntimeException("Cannot load APKs") ?: throw RuntimeException("Cannot load APKs")
if (builtArtifacts.elements.size != 1) if (builtArtifacts.elements.size != 1) {
throw RuntimeException("Expected one APK !") throw RuntimeException("Expected one APK !")
}
val apk = File(builtArtifacts.elements.single().outputFile).toPath() val apk = File(builtArtifacts.elements.single().outputFile).toPath()
println(apk) println(apk)
} }

@ -1,17 +1,17 @@
/* /*
* Copyright 2023 The Android Open Source Project * Copyright 2023 The Android Open Source Project
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* https://www.apache.org/licenses/LICENSE-2.0 * https://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.google.samples.apps.nowinandroid package com.google.samples.apps.nowinandroid

@ -0,0 +1,80 @@
/*
* Copyright 2026 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.samples.apps.nowinandroid
import com.diffplug.gradle.spotless.SpotlessExtension
import org.gradle.api.Project
import org.gradle.kotlin.dsl.apply
import org.gradle.kotlin.dsl.configure
internal fun Project.configureSpotlessForAndroid() {
configureSpotlessCommon()
extensions.configure<SpotlessExtension> {
format("xml") {
target("src/**/*.xml")
// Look for the first XML tag that isn't a comment (<!--) or the xml declaration (<?xml)
licenseHeaderFile(rootDir.resolve("spotless/copyright.xml"), "(<[^!?])")
endWithNewline()
}
}
}
internal fun Project.configureSpotlessForJvm() {
configureSpotlessCommon()
}
internal fun Project.configureSpotlessForRootProject() {
apply(plugin = "com.diffplug.spotless")
extensions.configure<SpotlessExtension> {
kotlin {
target("build-logic/convention/src/**/*.kt")
ktlint(libs.findVersion("ktlint").get().requiredVersion).editorConfigOverride(
mapOf("android" to "true"),
)
licenseHeaderFile(rootDir.resolve("spotless/copyright.kt"))
endWithNewline()
}
format("kts") {
target("*.kts")
target("build-logic/*.kts")
target("build-logic/convention/*.kts")
// Look for the first line that doesn't have a block comment (assumed to be the license)
licenseHeaderFile(rootDir.resolve("spotless/copyright.kts"), "(^(?![\\/ ]\\*).*$)")
endWithNewline()
}
}
}
private fun Project.configureSpotlessCommon() {
apply(plugin = "com.diffplug.spotless")
extensions.configure<SpotlessExtension> {
kotlin {
target("src/**/*.kt")
ktlint(libs.findVersion("ktlint").get().requiredVersion).editorConfigOverride(
mapOf("android" to "true"),
)
licenseHeaderFile(rootDir.resolve("spotless/copyright.kt"))
endWithNewline()
}
format("kts") {
target("*.kts")
// Look for the first line that doesn't have a block comment (assumed to be the license)
licenseHeaderFile(rootDir.resolve("spotless/copyright.kts"), "(^(?![\\/ ]\\*).*$)")
endWithNewline()
}
}
}

@ -38,5 +38,6 @@ plugins {
alias(libs.plugins.roborazzi) apply false alias(libs.plugins.roborazzi) apply false
alias(libs.plugins.google.osslicenses) apply false alias(libs.plugins.google.osslicenses) apply false
alias(libs.plugins.room) apply false alias(libs.plugins.room) apply false
alias(libs.plugins.spotless) apply false
alias(libs.plugins.nowinandroid.root) alias(libs.plugins.nowinandroid.root)
} }

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.google.samples.apps.nowinandroid.core.network package com.google.samples.apps.nowinandroid.core.common.network
import javax.inject.Qualifier import javax.inject.Qualifier
import kotlin.annotation.AnnotationRetention.RUNTIME import kotlin.annotation.AnnotationRetention.RUNTIME

@ -1,5 +1,5 @@
/* /*
* Copyright 2023 The Android Open Source Project * Copyright 2026 The Android Open Source Project
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -14,10 +14,10 @@
* limitations under the License. * limitations under the License.
*/ */
package com.google.samples.apps.nowinandroid.core.network.di package com.google.samples.apps.nowinandroid.core.common.network.di
import com.google.samples.apps.nowinandroid.core.network.Dispatcher import com.google.samples.apps.nowinandroid.core.common.network.Dispatcher
import com.google.samples.apps.nowinandroid.core.network.NiaDispatchers.Default import com.google.samples.apps.nowinandroid.core.common.network.NiaDispatchers.Default
import dagger.Module import dagger.Module
import dagger.Provides import dagger.Provides
import dagger.hilt.InstallIn import dagger.hilt.InstallIn

@ -1,5 +1,5 @@
/* /*
* Copyright 2022 The Android Open Source Project * Copyright 2026 The Android Open Source Project
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -14,11 +14,11 @@
* limitations under the License. * limitations under the License.
*/ */
package com.google.samples.apps.nowinandroid.core.network.di package com.google.samples.apps.nowinandroid.core.common.network.di
import com.google.samples.apps.nowinandroid.core.network.Dispatcher import com.google.samples.apps.nowinandroid.core.common.network.Dispatcher
import com.google.samples.apps.nowinandroid.core.network.NiaDispatchers.Default import com.google.samples.apps.nowinandroid.core.common.network.NiaDispatchers.Default
import com.google.samples.apps.nowinandroid.core.network.NiaDispatchers.IO import com.google.samples.apps.nowinandroid.core.common.network.NiaDispatchers.IO
import dagger.Module import dagger.Module
import dagger.Provides import dagger.Provides
import dagger.hilt.InstallIn import dagger.hilt.InstallIn

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.google.samples.apps.nowinandroid.core.result package com.google.samples.apps.nowinandroid.core.common.result
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.catch

@ -1,5 +1,5 @@
/* /*
* Copyright 2022 The Android Open Source Project * Copyright 2026 The Android Open Source Project
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.google.samples.apps.nowinandroid.core.result package com.google.samples.apps.nowinandroid.core.common.result
import app.cash.turbine.test import app.cash.turbine.test
import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.flow
@ -40,6 +40,7 @@ class ResultKtTest {
"Test Done", "Test Done",
errorResult.exception.message, errorResult.exception.message,
) )
Result.Loading, Result.Loading,
is Result.Success, is Result.Success,
-> throw IllegalStateException( -> throw IllegalStateException(

@ -19,7 +19,7 @@ graph TB
:core:data-test[data-test]:::android-library :core:data-test[data-test]:::android-library
:core:database[database]:::android-library :core:database[database]:::android-library
:core:datastore[datastore]:::android-library :core:datastore[datastore]:::android-library
:core:datastore-proto[datastore-proto]:::android-library :core:datastore-proto[datastore-proto]:::jvm-library
:core:model[model]:::jvm-library :core:model[model]:::jvm-library
:core:network[network]:::android-library :core:network[network]:::android-library
:core:notifications[notifications]:::android-library :core:notifications[notifications]:::android-library

@ -16,13 +16,13 @@
package com.google.samples.apps.nowinandroid.core.data.test.repository package com.google.samples.apps.nowinandroid.core.data.test.repository
import com.google.samples.apps.nowinandroid.core.common.network.Dispatcher
import com.google.samples.apps.nowinandroid.core.common.network.NiaDispatchers.IO
import com.google.samples.apps.nowinandroid.core.data.Synchronizer import com.google.samples.apps.nowinandroid.core.data.Synchronizer
import com.google.samples.apps.nowinandroid.core.data.model.asExternalModel import com.google.samples.apps.nowinandroid.core.data.model.asExternalModel
import com.google.samples.apps.nowinandroid.core.data.repository.NewsRepository import com.google.samples.apps.nowinandroid.core.data.repository.NewsRepository
import com.google.samples.apps.nowinandroid.core.data.repository.NewsResourceQuery import com.google.samples.apps.nowinandroid.core.data.repository.NewsResourceQuery
import com.google.samples.apps.nowinandroid.core.model.data.NewsResource import com.google.samples.apps.nowinandroid.core.model.data.NewsResource
import com.google.samples.apps.nowinandroid.core.network.Dispatcher
import com.google.samples.apps.nowinandroid.core.network.NiaDispatchers.IO
import com.google.samples.apps.nowinandroid.core.network.demo.DemoNiaNetworkDataSource import com.google.samples.apps.nowinandroid.core.network.demo.DemoNiaNetworkDataSource
import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow

@ -16,11 +16,11 @@
package com.google.samples.apps.nowinandroid.core.data.test.repository package com.google.samples.apps.nowinandroid.core.data.test.repository
import com.google.samples.apps.nowinandroid.core.common.network.Dispatcher
import com.google.samples.apps.nowinandroid.core.common.network.NiaDispatchers.IO
import com.google.samples.apps.nowinandroid.core.data.Synchronizer import com.google.samples.apps.nowinandroid.core.data.Synchronizer
import com.google.samples.apps.nowinandroid.core.data.repository.TopicsRepository import com.google.samples.apps.nowinandroid.core.data.repository.TopicsRepository
import com.google.samples.apps.nowinandroid.core.model.data.Topic import com.google.samples.apps.nowinandroid.core.model.data.Topic
import com.google.samples.apps.nowinandroid.core.network.Dispatcher
import com.google.samples.apps.nowinandroid.core.network.NiaDispatchers.IO
import com.google.samples.apps.nowinandroid.core.network.demo.DemoNiaNetworkDataSource import com.google.samples.apps.nowinandroid.core.network.demo.DemoNiaNetworkDataSource
import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow

@ -18,7 +18,7 @@ graph TB
:core:data[data]:::android-library :core:data[data]:::android-library
:core:database[database]:::android-library :core:database[database]:::android-library
:core:datastore[datastore]:::android-library :core:datastore[datastore]:::android-library
:core:datastore-proto[datastore-proto]:::android-library :core:datastore-proto[datastore-proto]:::jvm-library
:core:model[model]:::jvm-library :core:model[model]:::jvm-library
:core:network[network]:::android-library :core:network[network]:::android-library
:core:notifications[notifications]:::android-library :core:notifications[notifications]:::android-library

@ -16,6 +16,8 @@
package com.google.samples.apps.nowinandroid.core.data.repository package com.google.samples.apps.nowinandroid.core.data.repository
import com.google.samples.apps.nowinandroid.core.common.network.Dispatcher
import com.google.samples.apps.nowinandroid.core.common.network.NiaDispatchers.IO
import com.google.samples.apps.nowinandroid.core.database.dao.NewsResourceDao import com.google.samples.apps.nowinandroid.core.database.dao.NewsResourceDao
import com.google.samples.apps.nowinandroid.core.database.dao.NewsResourceFtsDao import com.google.samples.apps.nowinandroid.core.database.dao.NewsResourceFtsDao
import com.google.samples.apps.nowinandroid.core.database.dao.TopicDao import com.google.samples.apps.nowinandroid.core.database.dao.TopicDao
@ -24,8 +26,6 @@ import com.google.samples.apps.nowinandroid.core.database.model.PopulatedNewsRes
import com.google.samples.apps.nowinandroid.core.database.model.asExternalModel import com.google.samples.apps.nowinandroid.core.database.model.asExternalModel
import com.google.samples.apps.nowinandroid.core.database.model.asFtsEntity import com.google.samples.apps.nowinandroid.core.database.model.asFtsEntity
import com.google.samples.apps.nowinandroid.core.model.data.SearchResult import com.google.samples.apps.nowinandroid.core.model.data.SearchResult
import com.google.samples.apps.nowinandroid.core.network.Dispatcher
import com.google.samples.apps.nowinandroid.core.network.NiaDispatchers.IO
import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.combine

@ -25,8 +25,8 @@ import android.net.NetworkRequest
import android.net.NetworkRequest.Builder import android.net.NetworkRequest.Builder
import androidx.core.content.getSystemService import androidx.core.content.getSystemService
import androidx.tracing.trace import androidx.tracing.trace
import com.google.samples.apps.nowinandroid.core.network.Dispatcher import com.google.samples.apps.nowinandroid.core.common.network.Dispatcher
import com.google.samples.apps.nowinandroid.core.network.NiaDispatchers.IO import com.google.samples.apps.nowinandroid.core.common.network.NiaDispatchers.IO
import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.channels.awaitClose

@ -23,9 +23,9 @@ import android.content.IntentFilter
import android.os.Build.VERSION import android.os.Build.VERSION
import android.os.Build.VERSION_CODES import android.os.Build.VERSION_CODES
import androidx.tracing.trace import androidx.tracing.trace
import com.google.samples.apps.nowinandroid.core.network.Dispatcher import com.google.samples.apps.nowinandroid.core.common.network.Dispatcher
import com.google.samples.apps.nowinandroid.core.network.NiaDispatchers.IO import com.google.samples.apps.nowinandroid.core.common.network.NiaDispatchers.IO
import com.google.samples.apps.nowinandroid.core.network.di.ApplicationScope import com.google.samples.apps.nowinandroid.core.common.network.di.ApplicationScope
import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope

@ -13,7 +13,7 @@ config:
graph TB graph TB
subgraph :core subgraph :core
direction TB direction TB
:core:datastore-proto[datastore-proto]:::android-library :core:datastore-proto[datastore-proto]:::jvm-library
end end
classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000;

@ -15,23 +15,19 @@
*/ */
plugins { plugins {
alias(libs.plugins.nowinandroid.android.library) alias(libs.plugins.nowinandroid.jvm.library)
alias(libs.plugins.protobuf) alias(libs.plugins.protobuf)
} }
android {
namespace = "com.google.samples.apps.nowinandroid.core.datastore.proto"
}
// Setup protobuf configuration, generating lite Java and Kotlin classes // Setup protobuf configuration, generating lite Java and Kotlin classes
protobuf { protobuf {
protoc { protoc {
artifact = libs.protobuf.protoc.get().toString() artifact = libs.protobuf.protoc.get().toString()
} }
generateProtoTasks { generateProtoTasks {
all().forEach { task -> all().configureEach {
task.builtins { builtins {
register("java") { named("java") {
option("lite") option("lite")
} }
register("kotlin") { register("kotlin") {
@ -42,14 +38,6 @@ protobuf {
} }
} }
androidComponents.beforeVariants {
android.sourceSets.register(it.name) {
val buildDir = layout.buildDirectory.get().asFile
java.srcDir(buildDir.resolve("generated/source/proto/${it.name}/java"))
kotlin.srcDir(buildDir.resolve("generated/source/proto/${it.name}/kotlin"))
}
}
dependencies { dependencies {
api(libs.protobuf.kotlin.lite) api(libs.protobuf.kotlin.lite)
} }

@ -15,7 +15,7 @@ graph TB
direction TB direction TB
:core:common[common]:::jvm-library :core:common[common]:::jvm-library
:core:datastore[datastore]:::android-library :core:datastore[datastore]:::android-library
:core:datastore-proto[datastore-proto]:::android-library :core:datastore-proto[datastore-proto]:::jvm-library
:core:datastore-test[datastore-test]:::android-library :core:datastore-test[datastore-test]:::android-library
:core:model[model]:::jvm-library :core:model[model]:::jvm-library
end end

@ -15,7 +15,7 @@ graph TB
direction TB direction TB
:core:common[common]:::jvm-library :core:common[common]:::jvm-library
:core:datastore[datastore]:::android-library :core:datastore[datastore]:::android-library
:core:datastore-proto[datastore-proto]:::android-library :core:datastore-proto[datastore-proto]:::jvm-library
:core:model[model]:::jvm-library :core:model[model]:::jvm-library
end end

@ -20,12 +20,12 @@ import android.content.Context
import androidx.datastore.core.DataStore import androidx.datastore.core.DataStore
import androidx.datastore.core.DataStoreFactory import androidx.datastore.core.DataStoreFactory
import androidx.datastore.dataStoreFile import androidx.datastore.dataStoreFile
import com.google.samples.apps.nowinandroid.core.common.network.Dispatcher
import com.google.samples.apps.nowinandroid.core.common.network.NiaDispatchers.IO
import com.google.samples.apps.nowinandroid.core.common.network.di.ApplicationScope
import com.google.samples.apps.nowinandroid.core.datastore.IntToStringIdsMigration import com.google.samples.apps.nowinandroid.core.datastore.IntToStringIdsMigration
import com.google.samples.apps.nowinandroid.core.datastore.UserPreferences import com.google.samples.apps.nowinandroid.core.datastore.UserPreferences
import com.google.samples.apps.nowinandroid.core.datastore.UserPreferencesSerializer import com.google.samples.apps.nowinandroid.core.datastore.UserPreferencesSerializer
import com.google.samples.apps.nowinandroid.core.network.Dispatcher
import com.google.samples.apps.nowinandroid.core.network.NiaDispatchers.IO
import com.google.samples.apps.nowinandroid.core.network.di.ApplicationScope
import dagger.Module import dagger.Module
import dagger.Provides import dagger.Provides
import dagger.hilt.InstallIn import dagger.hilt.InstallIn

@ -18,7 +18,7 @@ graph TB
:core:data[data]:::android-library :core:data[data]:::android-library
:core:database[database]:::android-library :core:database[database]:::android-library
:core:datastore[datastore]:::android-library :core:datastore[datastore]:::android-library
:core:datastore-proto[datastore-proto]:::android-library :core:datastore-proto[datastore-proto]:::jvm-library
:core:domain[domain]:::android-library :core:domain[domain]:::android-library
:core:model[model]:::jvm-library :core:model[model]:::jvm-library
:core:network[network]:::android-library :core:network[network]:::android-library

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

@ -19,8 +19,8 @@ package com.google.samples.apps.nowinandroid.core.network.demo
import JvmUnitTestDemoAssetManager import JvmUnitTestDemoAssetManager
import android.os.Build.VERSION.SDK_INT import android.os.Build.VERSION.SDK_INT
import android.os.Build.VERSION_CODES.M import android.os.Build.VERSION_CODES.M
import com.google.samples.apps.nowinandroid.core.network.Dispatcher import com.google.samples.apps.nowinandroid.core.common.network.Dispatcher
import com.google.samples.apps.nowinandroid.core.network.NiaDispatchers.IO import com.google.samples.apps.nowinandroid.core.common.network.NiaDispatchers.IO
import com.google.samples.apps.nowinandroid.core.network.NiaNetworkDataSource import com.google.samples.apps.nowinandroid.core.network.NiaNetworkDataSource
import com.google.samples.apps.nowinandroid.core.network.model.NetworkChangeList import com.google.samples.apps.nowinandroid.core.network.model.NetworkChangeList
import com.google.samples.apps.nowinandroid.core.network.model.NetworkNewsResource import com.google.samples.apps.nowinandroid.core.network.model.NetworkNewsResource

@ -18,7 +18,7 @@ graph TB
:core:data[data]:::android-library :core:data[data]:::android-library
:core:database[database]:::android-library :core:database[database]:::android-library
:core:datastore[datastore]:::android-library :core:datastore[datastore]:::android-library
:core:datastore-proto[datastore-proto]:::android-library :core:datastore-proto[datastore-proto]:::jvm-library
:core:model[model]:::jvm-library :core:model[model]:::jvm-library
:core:network[network]:::android-library :core:network[network]:::android-library
:core:notifications[notifications]:::android-library :core:notifications[notifications]:::android-library

@ -16,10 +16,10 @@
package com.google.samples.apps.nowinandroid.core.testing.di package com.google.samples.apps.nowinandroid.core.testing.di
import com.google.samples.apps.nowinandroid.core.network.Dispatcher import com.google.samples.apps.nowinandroid.core.common.network.Dispatcher
import com.google.samples.apps.nowinandroid.core.network.NiaDispatchers.Default import com.google.samples.apps.nowinandroid.core.common.network.NiaDispatchers.Default
import com.google.samples.apps.nowinandroid.core.network.NiaDispatchers.IO import com.google.samples.apps.nowinandroid.core.common.network.NiaDispatchers.IO
import com.google.samples.apps.nowinandroid.core.network.di.DispatchersModule import com.google.samples.apps.nowinandroid.core.common.network.di.DispatchersModule
import dagger.Module import dagger.Module
import dagger.Provides import dagger.Provides
import dagger.hilt.components.SingletonComponent import dagger.hilt.components.SingletonComponent

@ -16,14 +16,16 @@
package com.google.samples.apps.nowinandroid.core.ui package com.google.samples.apps.nowinandroid.core.ui
import androidx.compose.ui.tooling.preview.Devices
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
/** /**
* Multipreview annotation that represents various device sizes. Add this annotation to a composable * Multipreview annotation that represents various device sizes. Add this annotation to a composable
* to render various devices. * to render various devices.
*/ */
@Preview(name = "phone", device = "spec:shape=Normal,width=360,height=640,unit=dp,dpi=480") @Preview(name = "phone", device = Devices.PHONE, showBackground = true)
@Preview(name = "landscape", device = "spec:shape=Normal,width=640,height=360,unit=dp,dpi=480") @Preview(name = "phone_in_landscape", widthDp = 891, heightDp = 411, showBackground = true)
@Preview(name = "foldable", device = "spec:shape=Normal,width=673,height=841,unit=dp,dpi=480") @Preview(name = "foldable", device = Devices.FOLDABLE, showBackground = true)
@Preview(name = "tablet", device = "spec:shape=Normal,width=1280,height=800,unit=dp,dpi=480") @Preview(name = "tablet", device = Devices.TABLET, showBackground = true)
@Preview(name = "desktop", device = Devices.DESKTOP, showBackground = true)
annotation class DevicePreviews annotation class DevicePreviews

@ -30,7 +30,7 @@ graph TB
:core:data[data]:::android-library :core:data[data]:::android-library
:core:database[database]:::android-library :core:database[database]:::android-library
:core:datastore[datastore]:::android-library :core:datastore[datastore]:::android-library
:core:datastore-proto[datastore-proto]:::android-library :core:datastore-proto[datastore-proto]:::jvm-library
:core:designsystem[designsystem]:::android-library :core:designsystem[designsystem]:::android-library
:core:model[model]:::jvm-library :core:model[model]:::jvm-library
:core:navigation[navigation]:::android-library :core:navigation[navigation]:::android-library

@ -155,7 +155,7 @@ private fun LoadingState(modifier: Modifier = Modifier) {
modifier = modifier modifier = modifier
.fillMaxWidth() .fillMaxWidth()
.wrapContentSize() .wrapContentSize()
.testTag("forYou:loading"), .testTag("bookmarks:loading"),
contentDesc = stringResource(id = R.string.feature_bookmarks_api_loading), contentDesc = stringResource(id = R.string.feature_bookmarks_api_loading),
) )
} }

@ -30,7 +30,7 @@ graph TB
:core:data[data]:::android-library :core:data[data]:::android-library
:core:database[database]:::android-library :core:database[database]:::android-library
:core:datastore[datastore]:::android-library :core:datastore[datastore]:::android-library
:core:datastore-proto[datastore-proto]:::android-library :core:datastore-proto[datastore-proto]:::jvm-library
:core:designsystem[designsystem]:::android-library :core:designsystem[designsystem]:::android-library
:core:domain[domain]:::android-library :core:domain[domain]:::android-library
:core:model[model]:::jvm-library :core:model[model]:::jvm-library

@ -1,3 +1,101 @@
# :feature:interests:impl module # `:feature:interests:impl`
## Dependency graph
![Dependency graph](../../../docs/images/graphs/dep_graph_feature_interests_impl.svg) ## Module dependency graph
<!--region graph-->
```mermaid
---
config:
layout: elk
elk:
nodePlacementStrategy: SIMPLE
---
graph TB
subgraph :feature
direction TB
subgraph :feature:interests
direction TB
:feature:interests:api[api]:::android-library
:feature:interests:impl[impl]:::android-library
end
subgraph :feature:topic
direction TB
:feature:topic:api[api]:::android-library
end
end
subgraph :core
direction TB
:core:analytics[analytics]:::android-library
:core:common[common]:::jvm-library
:core:data[data]:::android-library
:core:database[database]:::android-library
:core:datastore[datastore]:::android-library
:core:datastore-proto[datastore-proto]:::android-library
:core:designsystem[designsystem]:::android-library
:core:domain[domain]:::android-library
:core:model[model]:::jvm-library
:core:navigation[navigation]:::android-library
:core:network[network]:::android-library
:core:notifications[notifications]:::android-library
:core:ui[ui]:::android-library
end
:core:data -.-> :core:analytics
:core:data --> :core:common
:core:data --> :core:database
:core:data --> :core:datastore
:core:data --> :core:network
:core:data -.-> :core:notifications
:core:database --> :core:model
:core:datastore -.-> :core:common
:core:datastore --> :core:datastore-proto
:core:datastore --> :core:model
:core:domain --> :core:data
:core:domain --> :core:model
:core:network --> :core:common
:core:network --> :core:model
:core:notifications -.-> :core:common
:core:notifications --> :core:model
:core:ui --> :core:analytics
:core:ui --> :core:designsystem
:core:ui --> :core:model
:feature:interests:api --> :core:navigation
:feature:interests:impl -.-> :core:designsystem
:feature:interests:impl -.-> :core:domain
:feature:interests:impl -.-> :core:ui
:feature:interests:impl -.-> :feature:interests:api
:feature:interests:impl -.-> :feature:topic:api
:feature:topic:api -.-> :core:designsystem
:feature:topic:api --> :core:navigation
:feature:topic:api -.-> :core:ui
classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000;
classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000;
classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000;
classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000;
classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000;
classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000;
```
<details><summary>📋 Graph legend</summary>
```mermaid
graph TB
application[application]:::android-application
feature[feature]:::android-feature
library[library]:::android-library
jvm[jvm]:::jvm-library
application -.-> feature
library --> jvm
classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000;
classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000;
classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000;
classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000;
classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000;
classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000;
```
</details>
<!--endregion-->

@ -25,7 +25,7 @@ graph TB
:core:data[data]:::android-library :core:data[data]:::android-library
:core:database[database]:::android-library :core:database[database]:::android-library
:core:datastore[datastore]:::android-library :core:datastore[datastore]:::android-library
:core:datastore-proto[datastore-proto]:::android-library :core:datastore-proto[datastore-proto]:::jvm-library
:core:domain[domain]:::android-library :core:domain[domain]:::android-library
:core:model[model]:::jvm-library :core:model[model]:::jvm-library
:core:navigation[navigation]:::android-library :core:navigation[navigation]:::android-library

@ -25,4 +25,3 @@ android {
dependencies { dependencies {
implementation(projects.core.domain) implementation(projects.core.domain)
} }

@ -34,7 +34,7 @@ graph TB
:core:data[data]:::android-library :core:data[data]:::android-library
:core:database[database]:::android-library :core:database[database]:::android-library
:core:datastore[datastore]:::android-library :core:datastore[datastore]:::android-library
:core:datastore-proto[datastore-proto]:::android-library :core:datastore-proto[datastore-proto]:::jvm-library
:core:designsystem[designsystem]:::android-library :core:designsystem[designsystem]:::android-library
:core:domain[domain]:::android-library :core:domain[domain]:::android-library
:core:model[model]:::jvm-library :core:model[model]:::jvm-library

@ -25,7 +25,7 @@ graph TB
:core:data[data]:::android-library :core:data[data]:::android-library
:core:database[database]:::android-library :core:database[database]:::android-library
:core:datastore[datastore]:::android-library :core:datastore[datastore]:::android-library
:core:datastore-proto[datastore-proto]:::android-library :core:datastore-proto[datastore-proto]:::jvm-library
:core:designsystem[designsystem]:::android-library :core:designsystem[designsystem]:::android-library
:core:model[model]:::jvm-library :core:model[model]:::jvm-library
:core:network[network]:::android-library :core:network[network]:::android-library

@ -1,3 +1,66 @@
# :feature:topic:api module # `:feature:topic:api`
## Dependency graph
![Dependency graph](../../../docs/images/graphs/dep_graph_feature_topic_api.svg) ## Module dependency graph
<!--region graph-->
```mermaid
---
config:
layout: elk
elk:
nodePlacementStrategy: SIMPLE
---
graph TB
subgraph :feature
direction TB
subgraph :feature:topic
direction TB
:feature:topic:api[api]:::android-library
end
end
subgraph :core
direction TB
:core:analytics[analytics]:::android-library
:core:designsystem[designsystem]:::android-library
:core:model[model]:::jvm-library
:core:navigation[navigation]:::android-library
:core:ui[ui]:::android-library
end
:core:ui --> :core:analytics
:core:ui --> :core:designsystem
:core:ui --> :core:model
:feature:topic:api -.-> :core:designsystem
:feature:topic:api --> :core:navigation
:feature:topic:api -.-> :core:ui
classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000;
classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000;
classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000;
classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000;
classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000;
classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000;
```
<details><summary>📋 Graph legend</summary>
```mermaid
graph TB
application[application]:::android-application
feature[feature]:::android-feature
library[library]:::android-library
jvm[jvm]:::jvm-library
application -.-> feature
library --> jvm
classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000;
classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000;
classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000;
classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000;
classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000;
classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000;
```
</details>
<!--endregion-->

@ -1,3 +1,92 @@
# :feature:topic:impl module # `:feature:topic:impl`
## Dependency graph
![Dependency graph](../../../docs/images/graphs/dep_graph_feature_topic_impl.svg) ## Module dependency graph
<!--region graph-->
```mermaid
---
config:
layout: elk
elk:
nodePlacementStrategy: SIMPLE
---
graph TB
subgraph :feature
direction TB
subgraph :feature:topic
direction TB
:feature:topic:api[api]:::android-library
:feature:topic:impl[impl]:::android-library
end
end
subgraph :core
direction TB
:core:analytics[analytics]:::android-library
:core:common[common]:::jvm-library
:core:data[data]:::android-library
:core:database[database]:::android-library
:core:datastore[datastore]:::android-library
:core:datastore-proto[datastore-proto]:::android-library
:core:designsystem[designsystem]:::android-library
:core:model[model]:::jvm-library
:core:navigation[navigation]:::android-library
:core:network[network]:::android-library
:core:notifications[notifications]:::android-library
:core:ui[ui]:::android-library
end
:core:data -.-> :core:analytics
:core:data --> :core:common
:core:data --> :core:database
:core:data --> :core:datastore
:core:data --> :core:network
:core:data -.-> :core:notifications
:core:database --> :core:model
:core:datastore -.-> :core:common
:core:datastore --> :core:datastore-proto
:core:datastore --> :core:model
:core:network --> :core:common
:core:network --> :core:model
:core:notifications -.-> :core:common
:core:notifications --> :core:model
:core:ui --> :core:analytics
:core:ui --> :core:designsystem
:core:ui --> :core:model
:feature:topic:api -.-> :core:designsystem
:feature:topic:api --> :core:navigation
:feature:topic:api -.-> :core:ui
:feature:topic:impl -.-> :core:data
:feature:topic:impl -.-> :core:designsystem
:feature:topic:impl -.-> :core:ui
:feature:topic:impl -.-> :feature:topic:api
classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000;
classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000;
classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000;
classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000;
classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000;
classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000;
```
<details><summary>📋 Graph legend</summary>
```mermaid
graph TB
application[application]:::android-application
feature[feature]:::android-feature
library[library]:::android-library
jvm[jvm]:::jvm-library
application -.-> feature
library --> jvm
classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000;
classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000;
classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000;
classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000;
classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000;
classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000;
```
</details>
<!--endregion-->

@ -18,6 +18,8 @@ package com.google.samples.apps.nowinandroid.feature.topic.impl
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.google.samples.apps.nowinandroid.core.common.result.Result
import com.google.samples.apps.nowinandroid.core.common.result.asResult
import com.google.samples.apps.nowinandroid.core.data.repository.NewsResourceQuery import com.google.samples.apps.nowinandroid.core.data.repository.NewsResourceQuery
import com.google.samples.apps.nowinandroid.core.data.repository.TopicsRepository import com.google.samples.apps.nowinandroid.core.data.repository.TopicsRepository
import com.google.samples.apps.nowinandroid.core.data.repository.UserDataRepository import com.google.samples.apps.nowinandroid.core.data.repository.UserDataRepository
@ -25,8 +27,6 @@ import com.google.samples.apps.nowinandroid.core.data.repository.UserNewsResourc
import com.google.samples.apps.nowinandroid.core.model.data.FollowableTopic import com.google.samples.apps.nowinandroid.core.model.data.FollowableTopic
import com.google.samples.apps.nowinandroid.core.model.data.Topic import com.google.samples.apps.nowinandroid.core.model.data.Topic
import com.google.samples.apps.nowinandroid.core.model.data.UserNewsResource import com.google.samples.apps.nowinandroid.core.model.data.UserNewsResource
import com.google.samples.apps.nowinandroid.core.result.Result
import com.google.samples.apps.nowinandroid.core.result.asResult
import dagger.assisted.Assisted import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject import dagger.assisted.AssistedInject

@ -64,6 +64,4 @@ roborazzi.test.verify=true
# https://issuetracker.google.com/issues/295039976 # https://issuetracker.google.com/issues/295039976
android.injected.androidTest.leaveApksInstalledAfterRun=true android.injected.androidTest.leaveApksInstalledAfterRun=true
# Blockers: ksp.project.isolation.enabled=true
# - https://github.com/google/protobuf-gradle-plugin/issues/787
android.newDsl=false

@ -1,59 +0,0 @@
/*
* Copyright 2022 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.
*/
val ktlintVersion = "1.4.0"
initscript {
val spotlessVersion = "6.25.0"
repositories {
mavenCentral()
}
dependencies {
classpath("com.diffplug.spotless:spotless-plugin-gradle:$spotlessVersion")
}
}
rootProject {
subprojects {
apply<com.diffplug.gradle.spotless.SpotlessPlugin>()
extensions.configure<com.diffplug.gradle.spotless.SpotlessExtension> {
kotlin {
target("**/*.kt")
targetExclude("**/build/**/*.kt")
ktlint(ktlintVersion).editorConfigOverride(
mapOf(
"android" to "true",
),
)
licenseHeaderFile(rootProject.file("spotless/copyright.kt"))
}
format("kts") {
target("**/*.kts")
targetExclude("**/build/**/*.kts")
// Look for the first line that doesn't have a block comment (assumed to be the license)
licenseHeaderFile(rootProject.file("spotless/copyright.kts"), "(^(?![\\/ ]\\*).*$)")
}
format("xml") {
target("**/*.xml")
targetExclude("**/build/**/*.xml")
// Look for the first XML tag that isn't a comment (<!--) or the xml declaration (<?xml)
licenseHeaderFile(rootProject.file("spotless/copyright.xml"), "(<[^!?])")
}
}
}
}

@ -51,14 +51,16 @@ kotlinxCoroutines = "1.10.1"
kotlinxDatetime = "0.6.1" kotlinxDatetime = "0.6.1"
kotlinxSerializationJson = "1.8.0" kotlinxSerializationJson = "1.8.0"
ksp = "2.3.4" ksp = "2.3.4"
ktlint = "1.4.0"
okhttp = "4.12.0" okhttp = "4.12.0"
protobuf = "4.29.2" protobuf = "4.29.2"
protobufPlugin = "0.9.5" protobufPlugin = "0.9.6"
retrofit = "2.11.0" retrofit = "2.11.0"
retrofitKotlinxSerializationJson = "1.0.0" retrofitKotlinxSerializationJson = "1.0.0"
robolectric = "4.16" robolectric = "4.16"
roborazzi = "1.56.0" roborazzi = "1.56.0"
room = "2.8.3" room = "2.8.3"
spotless = "8.3.0"
truth = "1.4.4" truth = "1.4.4"
turbine = "1.2.0" turbine = "1.2.0"
uiTestJunit4 = "1.9.0-rc01" uiTestJunit4 = "1.9.0-rc01"
@ -171,6 +173,7 @@ kotlin-gradlePlugin = { group = "org.jetbrains.kotlin", name = "kotlin-gradle-pl
ksp-gradlePlugin = { group = "com.google.devtools.ksp", name = "com.google.devtools.ksp.gradle.plugin", version.ref = "ksp" } ksp-gradlePlugin = { group = "com.google.devtools.ksp", name = "com.google.devtools.ksp.gradle.plugin", version.ref = "ksp" }
room-gradlePlugin = { group = "androidx.room", name = "room-gradle-plugin", version.ref = "room" } room-gradlePlugin = { group = "androidx.room", name = "room-gradle-plugin", version.ref = "room" }
androidx-compose-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4", version.ref = "uiTestJunit4" } androidx-compose-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4", version.ref = "uiTestJunit4" }
spotless-gradlePlugin = { group = "com.diffplug.spotless", name = "spotless-plugin-gradle", version.ref = "spotless" }
[plugins] [plugins]
android-application = { id = "com.android.application", version.ref = "androidGradlePlugin" } android-application = { id = "com.android.application", version.ref = "androidGradlePlugin" }
@ -191,6 +194,7 @@ google-osslicenses = { id = "com.google.android.gms.oss-licenses-plugin", versio
protobuf = { id = "com.google.protobuf", version.ref = "protobufPlugin" } protobuf = { id = "com.google.protobuf", version.ref = "protobufPlugin" }
roborazzi = { id = "io.github.takahirom.roborazzi", version.ref = "roborazzi" } roborazzi = { id = "io.github.takahirom.roborazzi", version.ref = "roborazzi" }
room = { id = "androidx.room", version.ref = "room" } room = { id = "androidx.room", version.ref = "room" }
spotless = { id = "com.diffplug.spotless", version.ref = "spotless" }
# Plugins defined by this project # Plugins defined by this project
nowinandroid-android-application = { id = "nowinandroid.android.application" } nowinandroid-android-application = { id = "nowinandroid.android.application" }

Binary file not shown.

@ -1,7 +1,7 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionSha256Sum=0d585f69da091fc5b2beced877feab55a3064d43b8a1d46aeb07996b0915e0e0 distributionSha256Sum=60ea723356d81263e8002fec0fcf9e2b0eee0c0850c7a3d7ab0a63f2ccc601f3
distributionUrl=https\://services.gradle.org/distributions/gradle-9.3.0-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.0-bin.zip
networkTimeout=10000 networkTimeout=10000
validateDistributionUrl=true validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME

2
gradlew vendored

@ -57,7 +57,7 @@
# Darwin, MinGW, and NonStop. # Darwin, MinGW, and NonStop.
# #
# (3) This script is generated from the Groovy template # (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # https://github.com/gradle/gradle/blob/b631911858264c0b6e4d6603d677ff5218766cee/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project. # within the Gradle project.
# #
# You can find Gradle at https://github.com/gradle/gradle/. # You can find Gradle at https://github.com/gradle/gradle/.

@ -23,7 +23,7 @@ graph TB
:core:data[data]:::android-library :core:data[data]:::android-library
:core:database[database]:::android-library :core:database[database]:::android-library
:core:datastore[datastore]:::android-library :core:datastore[datastore]:::android-library
:core:datastore-proto[datastore-proto]:::android-library :core:datastore-proto[datastore-proto]:::jvm-library
:core:model[model]:::jvm-library :core:model[model]:::jvm-library
:core:network[network]:::android-library :core:network[network]:::android-library
:core:notifications[notifications]:::android-library :core:notifications[notifications]:::android-library

@ -22,7 +22,7 @@ graph TB
:core:data[data]:::android-library :core:data[data]:::android-library
:core:database[database]:::android-library :core:database[database]:::android-library
:core:datastore[datastore]:::android-library :core:datastore[datastore]:::android-library
:core:datastore-proto[datastore-proto]:::android-library :core:datastore-proto[datastore-proto]:::jvm-library
:core:model[model]:::jvm-library :core:model[model]:::jvm-library
:core:network[network]:::android-library :core:network[network]:::android-library
:core:notifications[notifications]:::android-library :core:notifications[notifications]:::android-library

@ -25,14 +25,14 @@ import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.OutOfQuotaPolicy import androidx.work.OutOfQuotaPolicy
import androidx.work.WorkerParameters import androidx.work.WorkerParameters
import com.google.samples.apps.nowinandroid.core.analytics.AnalyticsHelper import com.google.samples.apps.nowinandroid.core.analytics.AnalyticsHelper
import com.google.samples.apps.nowinandroid.core.common.network.Dispatcher
import com.google.samples.apps.nowinandroid.core.common.network.NiaDispatchers.IO
import com.google.samples.apps.nowinandroid.core.data.Synchronizer import com.google.samples.apps.nowinandroid.core.data.Synchronizer
import com.google.samples.apps.nowinandroid.core.data.repository.NewsRepository import com.google.samples.apps.nowinandroid.core.data.repository.NewsRepository
import com.google.samples.apps.nowinandroid.core.data.repository.SearchContentsRepository import com.google.samples.apps.nowinandroid.core.data.repository.SearchContentsRepository
import com.google.samples.apps.nowinandroid.core.data.repository.TopicsRepository import com.google.samples.apps.nowinandroid.core.data.repository.TopicsRepository
import com.google.samples.apps.nowinandroid.core.datastore.ChangeListVersions import com.google.samples.apps.nowinandroid.core.datastore.ChangeListVersions
import com.google.samples.apps.nowinandroid.core.datastore.NiaPreferencesDataSource import com.google.samples.apps.nowinandroid.core.datastore.NiaPreferencesDataSource
import com.google.samples.apps.nowinandroid.core.network.Dispatcher
import com.google.samples.apps.nowinandroid.core.network.NiaDispatchers.IO
import com.google.samples.apps.nowinandroid.sync.initializers.SyncConstraints import com.google.samples.apps.nowinandroid.sync.initializers.SyncConstraints
import com.google.samples.apps.nowinandroid.sync.initializers.syncForegroundInfo import com.google.samples.apps.nowinandroid.sync.initializers.syncForegroundInfo
import com.google.samples.apps.nowinandroid.sync.status.SyncSubscriber import com.google.samples.apps.nowinandroid.sync.status.SyncSubscriber

@ -88,7 +88,7 @@ done
if [[ -n "$run_checks" ]]; then if [[ -n "$run_checks" ]]; then
# pre-push usually executes in the repository root, but just to be safe... # pre-push usually executes in the repository root, but just to be safe...
cd "$(git rev-parse --show-toplevel)" cd "$(git rev-parse --show-toplevel)"
./gradlew --init-script gradle/init.gradle.kts --no-configuration-cache check ./gradlew check
exit $? exit $?
fi fi

Loading…
Cancel
Save