Merge branch 'android-remote-main' into optimize-ftsdatabase

Change-Id: I269d3a5a2fba1d33f519f0e8f195c42db48cc5f9

# Conflicts:
#	core/database/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/core/database/dao/NewsResourceDaoTest.kt
pull/1268/head
Jaehwa Noh 8 months ago
commit db62cf6da6

@ -17,6 +17,8 @@
org.gradle.daemon=false
org.gradle.parallel=true
org.gradle.workers.max=2
org.gradle.configuration-cache=true
org.gradle.configuration-cache.parallel=true
kotlin.incremental=false

@ -7,6 +7,8 @@
"main"
],
"gitIgnoredAuthors": [
"renovate[bot]@users.noreply.github.com",
"github-actions[bot]@users.noreply.github.com",
"41898282+github-actions[bot]@users.noreply.github.com"
]
}

@ -37,9 +37,11 @@ jobs:
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v4
with:
cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}
- name: Check build-logic
run: ./gradlew check -p build-logic
run: ./gradlew :build-logic:convention:check
- name: Check spotless
run: ./gradlew spotlessCheck --init-script gradle/init.gradle.kts --no-configuration-cache
@ -186,6 +188,8 @@ jobs:
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v4
with:
cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}
- name: Build projects and run instrumentation tests
uses: reactivecircus/android-emulator-runner@v2

@ -7,6 +7,7 @@ on:
jobs:
baseline_profiles:
name: "Generate Baseline Profiles"
if: github.repository == 'android/nowinandroid'
runs-on: ubuntu-latest
permissions:
@ -36,6 +37,8 @@ jobs:
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v4
with:
cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}
- name: Setup Android SDK
uses: android-actions/setup-android@v3
@ -44,7 +47,7 @@ jobs:
run: yes | sdkmanager --licenses || true
- name: Check build-logic
run: ./gradlew check -p build-logic
run: ./gradlew :build-logic:convention:check
- name: Setup GMD
run: ./gradlew :benchmarks:pixel6Api33Setup
@ -52,9 +55,8 @@ jobs:
-Pandroid.experimental.testOptions.managedDevices.emulator.showKernelLogging=true
-Pandroid.testoptions.manageddevices.emulator.gpu="swiftshader_indirect"
# This generates both baseline and startup profile and adds them into the generated folder
- name: Generate Baseline Profile
run: ./gradlew :app:generateReleaseBaselineProfile
-Pandroid.testInstrumentationRunnerArguments.androidx.benchmark.enabledRules=baselineprofile
-Pandroid.testoptions.manageddevices.emulator.gpu="swiftshader_indirect"
--stacktrace
- name: Build all build type and flavor permutations including baseline profiles
run: ./gradlew :app:assemble
-Pandroid.testInstrumentationRunnerArguments.androidx.benchmark.enabledRules=baselineprofile
-Pandroid.testoptions.manageddevices.emulator.gpu="swiftshader_indirect"
-Pandroid.experimental.testOptions.managedDevices.emulator.showKernelLogging=true

@ -7,6 +7,7 @@ on:
jobs:
build:
if: github.repository == 'android/nowinandroid'
runs-on: ubuntu-latest
timeout-minutes: 120
@ -33,6 +34,8 @@ jobs:
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v4
with:
cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}
- name: Setup Android SDK
uses: android-actions/setup-android@v3

@ -2,24 +2,24 @@ androidx.activity:activity-compose:1.9.3
androidx.activity:activity-ktx:1.9.3
androidx.activity:activity:1.9.3
androidx.annotation:annotation-experimental:1.4.1
androidx.annotation:annotation-jvm:1.8.1
androidx.annotation:annotation:1.8.1
androidx.annotation:annotation-jvm:1.9.1
androidx.annotation:annotation:1.9.1
androidx.appcompat:appcompat-resources:1.6.1
androidx.arch.core:core-common:2.2.0
androidx.arch.core:core-runtime:2.2.0
androidx.autofill:autofill:1.0.0
androidx.browser:browser:1.8.0
androidx.collection:collection-jvm:1.4.4
androidx.collection:collection-ktx:1.4.4
androidx.collection:collection:1.4.4
androidx.compose.animation:animation-android:1.7.6
androidx.compose.animation:animation-core-android:1.7.6
androidx.compose.animation:animation-core:1.7.6
androidx.compose.animation:animation:1.7.6
androidx.compose.foundation:foundation-android:1.7.6
androidx.compose.foundation:foundation-layout-android:1.7.6
androidx.compose.foundation:foundation-layout:1.7.6
androidx.compose.foundation:foundation:1.7.6
androidx.collection:collection-jvm:1.5.0-beta01
androidx.collection:collection-ktx:1.5.0-beta01
androidx.collection:collection:1.5.0-beta01
androidx.compose.animation:animation-android:1.8.0-alpha07
androidx.compose.animation:animation-core-android:1.8.0-alpha07
androidx.compose.animation:animation-core:1.8.0-alpha07
androidx.compose.animation:animation:1.8.0-alpha07
androidx.compose.foundation:foundation-android:1.8.0-alpha07
androidx.compose.foundation:foundation-layout-android:1.8.0-alpha07
androidx.compose.foundation:foundation-layout:1.8.0-alpha07
androidx.compose.foundation:foundation:1.8.0-alpha07
androidx.compose.material3.adaptive:adaptive-android:1.0.0
androidx.compose.material3.adaptive:adaptive:1.0.0
androidx.compose.material3:material3-adaptive-navigation-suite-android:1.3.1
@ -32,55 +32,55 @@ androidx.compose.material:material-icons-extended-android:1.7.6
androidx.compose.material:material-icons-extended:1.7.6
androidx.compose.material:material-ripple-android:1.7.6
androidx.compose.material:material-ripple:1.7.6
androidx.compose.runtime:runtime-android:1.7.6
androidx.compose.runtime:runtime-saveable-android:1.7.6
androidx.compose.runtime:runtime-saveable:1.7.6
androidx.compose.runtime:runtime:1.7.6
androidx.compose.ui:ui-android:1.7.6
androidx.compose.ui:ui-geometry-android:1.7.6
androidx.compose.ui:ui-geometry:1.7.6
androidx.compose.ui:ui-graphics-android:1.7.6
androidx.compose.ui:ui-graphics:1.7.6
androidx.compose.ui:ui-text-android:1.7.6
androidx.compose.ui:ui-text:1.7.6
androidx.compose.ui:ui-tooling-preview-android:1.7.6
androidx.compose.ui:ui-tooling-preview:1.7.6
androidx.compose.ui:ui-unit-android:1.7.6
androidx.compose.ui:ui-unit:1.7.6
androidx.compose.ui:ui-util-android:1.7.6
androidx.compose.ui:ui-util:1.7.6
androidx.compose.ui:ui:1.7.6
androidx.compose.runtime:runtime-android:1.8.0-alpha07
androidx.compose.runtime:runtime-saveable-android:1.8.0-alpha07
androidx.compose.runtime:runtime-saveable:1.8.0-alpha07
androidx.compose.runtime:runtime:1.8.0-alpha07
androidx.compose.ui:ui-android:1.8.0-alpha07
androidx.compose.ui:ui-geometry-android:1.8.0-alpha07
androidx.compose.ui:ui-geometry:1.8.0-alpha07
androidx.compose.ui:ui-graphics-android:1.8.0-alpha07
androidx.compose.ui:ui-graphics:1.8.0-alpha07
androidx.compose.ui:ui-text-android:1.8.0-alpha07
androidx.compose.ui:ui-text:1.8.0-alpha07
androidx.compose.ui:ui-tooling-preview-android:1.8.0-alpha07
androidx.compose.ui:ui-tooling-preview:1.8.0-alpha07
androidx.compose.ui:ui-unit-android:1.8.0-alpha07
androidx.compose.ui:ui-unit:1.8.0-alpha07
androidx.compose.ui:ui-util-android:1.8.0-alpha07
androidx.compose.ui:ui-util:1.8.0-alpha07
androidx.compose.ui:ui:1.8.0-alpha07
androidx.compose:compose-bom:2024.12.01
androidx.concurrent:concurrent-futures:1.1.0
androidx.core:core-ktx:1.13.1
androidx.core:core:1.13.1
androidx.customview:customview-poolingcontainer:1.0.0
androidx.customview:customview:1.0.0
androidx.emoji2:emoji2:1.3.0
androidx.emoji2:emoji2:1.4.0
androidx.exifinterface:exifinterface:1.3.7
androidx.fragment:fragment:1.5.1
androidx.graphics:graphics-path:1.0.1
androidx.interpolator:interpolator:1.0.0
androidx.lifecycle:lifecycle-common-java8:2.8.3
androidx.lifecycle:lifecycle-common-jvm:2.8.3
androidx.lifecycle:lifecycle-common:2.8.3
androidx.lifecycle:lifecycle-livedata-core-ktx:2.8.3
androidx.lifecycle:lifecycle-livedata-core:2.8.3
androidx.lifecycle:lifecycle-livedata:2.8.3
androidx.lifecycle:lifecycle-process:2.8.3
androidx.lifecycle:lifecycle-runtime-android:2.8.3
androidx.lifecycle:lifecycle-runtime-compose-android:2.8.3
androidx.lifecycle:lifecycle-runtime-compose:2.8.3
androidx.lifecycle:lifecycle-runtime-ktx-android:2.8.3
androidx.lifecycle:lifecycle-runtime-ktx:2.8.3
androidx.lifecycle:lifecycle-runtime:2.8.3
androidx.lifecycle:lifecycle-viewmodel-android:2.8.3
androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.3
androidx.lifecycle:lifecycle-viewmodel-savedstate:2.8.3
androidx.lifecycle:lifecycle-viewmodel:2.8.3
androidx.lifecycle:lifecycle-common-java8:2.8.7
androidx.lifecycle:lifecycle-common-jvm:2.8.7
androidx.lifecycle:lifecycle-common:2.8.7
androidx.lifecycle:lifecycle-livedata-core-ktx:2.8.7
androidx.lifecycle:lifecycle-livedata-core:2.8.7
androidx.lifecycle:lifecycle-livedata:2.8.7
androidx.lifecycle:lifecycle-process:2.8.7
androidx.lifecycle:lifecycle-runtime-android:2.8.7
androidx.lifecycle:lifecycle-runtime-compose-android:2.8.7
androidx.lifecycle:lifecycle-runtime-compose:2.8.7
androidx.lifecycle:lifecycle-runtime-ktx-android:2.8.7
androidx.lifecycle:lifecycle-runtime-ktx:2.8.7
androidx.lifecycle:lifecycle-runtime:2.8.7
androidx.lifecycle:lifecycle-viewmodel-android:2.8.7
androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.7
androidx.lifecycle:lifecycle-viewmodel-savedstate:2.8.7
androidx.lifecycle:lifecycle-viewmodel:2.8.7
androidx.loader:loader:1.0.0
androidx.metrics:metrics-performance:1.0.0-beta01
androidx.profileinstaller:profileinstaller:1.3.1
androidx.profileinstaller:profileinstaller:1.4.0
androidx.savedstate:savedstate-ktx:1.2.1
androidx.savedstate:savedstate:1.2.1
androidx.startup:startup-runtime:1.1.1
@ -96,10 +96,10 @@ androidx.window:window-core:1.3.0
androidx.window:window:1.3.0
com.google.accompanist:accompanist-drawablepainter:0.32.0
com.google.code.findbugs:jsr305:3.0.2
com.google.dagger:dagger-lint-aar:2.53.1
com.google.dagger:dagger:2.53.1
com.google.dagger:hilt-android:2.53.1
com.google.dagger:hilt-core:2.53.1
com.google.dagger:dagger-lint-aar:2.54
com.google.dagger:dagger:2.54
com.google.dagger:hilt-android:2.54
com.google.dagger:hilt-core:2.54
com.google.guava:listenablefuture:1.0
com.squareup.okhttp3:okhttp:4.12.0
com.squareup.okio:okio-jvm:3.9.0

@ -116,15 +116,16 @@ dependencies {
testImplementation(projects.sync.syncTest)
testImplementation(libs.kotlin.test)
testDemoImplementation(libs.androidx.navigation.testing)
testDemoImplementation(libs.robolectric)
testDemoImplementation(libs.roborazzi)
testDemoImplementation(projects.core.screenshotTesting)
testDemoImplementation(projects.core.testing)
androidTestImplementation(projects.core.testing)
androidTestImplementation(projects.core.dataTest)
androidTestImplementation(projects.core.datastoreTest)
androidTestImplementation(libs.androidx.test.espresso.core)
androidTestImplementation(libs.androidx.navigation.testing)
androidTestImplementation(libs.androidx.compose.ui.test)
androidTestImplementation(libs.hilt.android.testing)
androidTestImplementation(libs.kotlin.test)

@ -2,25 +2,25 @@ androidx.activity:activity-compose:1.9.3
androidx.activity:activity-ktx:1.9.3
androidx.activity:activity:1.9.3
androidx.annotation:annotation-experimental:1.4.1
androidx.annotation:annotation-jvm:1.8.1
androidx.annotation:annotation:1.8.1
androidx.annotation:annotation-jvm:1.9.1
androidx.annotation:annotation:1.9.1
androidx.appcompat:appcompat-resources:1.7.0
androidx.appcompat:appcompat:1.7.0
androidx.arch.core:core-common:2.2.0
androidx.arch.core:core-runtime:2.2.0
androidx.autofill:autofill:1.0.0
androidx.browser:browser:1.8.0
androidx.collection:collection-jvm:1.4.4
androidx.collection:collection-ktx:1.4.4
androidx.collection:collection:1.4.4
androidx.compose.animation:animation-android:1.7.6
androidx.compose.animation:animation-core-android:1.7.6
androidx.compose.animation:animation-core:1.7.6
androidx.compose.animation:animation:1.7.6
androidx.compose.foundation:foundation-android:1.7.6
androidx.compose.foundation:foundation-layout-android:1.7.6
androidx.compose.foundation:foundation-layout:1.7.6
androidx.compose.foundation:foundation:1.7.6
androidx.collection:collection-jvm:1.5.0-beta01
androidx.collection:collection-ktx:1.5.0-beta01
androidx.collection:collection:1.5.0-beta01
androidx.compose.animation:animation-android:1.8.0-alpha07
androidx.compose.animation:animation-core-android:1.8.0-alpha07
androidx.compose.animation:animation-core:1.8.0-alpha07
androidx.compose.animation:animation:1.8.0-alpha07
androidx.compose.foundation:foundation-android:1.8.0-alpha07
androidx.compose.foundation:foundation-layout-android:1.8.0-alpha07
androidx.compose.foundation:foundation-layout:1.8.0-alpha07
androidx.compose.foundation:foundation:1.8.0-alpha07
androidx.compose.material3.adaptive:adaptive-android:1.0.0
androidx.compose.material3.adaptive:adaptive-layout-android:1.0.0
androidx.compose.material3.adaptive:adaptive-layout:1.0.0
@ -39,25 +39,25 @@ androidx.compose.material:material-icons-extended-android:1.7.6
androidx.compose.material:material-icons-extended:1.7.6
androidx.compose.material:material-ripple-android:1.7.6
androidx.compose.material:material-ripple:1.7.6
androidx.compose.runtime:runtime-android:1.7.6
androidx.compose.runtime:runtime-saveable-android:1.7.6
androidx.compose.runtime:runtime-saveable:1.7.6
androidx.compose.runtime:runtime-tracing:1.7.6
androidx.compose.runtime:runtime:1.7.6
androidx.compose.ui:ui-android:1.7.6
androidx.compose.ui:ui-geometry-android:1.7.6
androidx.compose.ui:ui-geometry:1.7.6
androidx.compose.ui:ui-graphics-android:1.7.6
androidx.compose.ui:ui-graphics:1.7.6
androidx.compose.ui:ui-text-android:1.7.6
androidx.compose.ui:ui-text:1.7.6
androidx.compose.ui:ui-tooling-preview-android:1.7.6
androidx.compose.ui:ui-tooling-preview:1.7.6
androidx.compose.ui:ui-unit-android:1.7.6
androidx.compose.ui:ui-unit:1.7.6
androidx.compose.ui:ui-util-android:1.7.6
androidx.compose.ui:ui-util:1.7.6
androidx.compose.ui:ui:1.7.6
androidx.compose.runtime:runtime-android:1.8.0-alpha07
androidx.compose.runtime:runtime-saveable-android:1.8.0-alpha07
androidx.compose.runtime:runtime-saveable:1.8.0-alpha07
androidx.compose.runtime:runtime-tracing:1.8.0-alpha07
androidx.compose.runtime:runtime:1.8.0-alpha07
androidx.compose.ui:ui-android:1.8.0-alpha07
androidx.compose.ui:ui-geometry-android:1.8.0-alpha07
androidx.compose.ui:ui-geometry:1.8.0-alpha07
androidx.compose.ui:ui-graphics-android:1.8.0-alpha07
androidx.compose.ui:ui-graphics:1.8.0-alpha07
androidx.compose.ui:ui-text-android:1.8.0-alpha07
androidx.compose.ui:ui-text:1.8.0-alpha07
androidx.compose.ui:ui-tooling-preview-android:1.8.0-alpha07
androidx.compose.ui:ui-tooling-preview:1.8.0-alpha07
androidx.compose.ui:ui-unit-android:1.8.0-alpha07
androidx.compose.ui:ui-unit:1.8.0-alpha07
androidx.compose.ui:ui-util-android:1.8.0-alpha07
androidx.compose.ui:ui-util:1.8.0-alpha07
androidx.compose.ui:ui:1.8.0-alpha07
androidx.compose:compose-bom:2024.12.01
androidx.concurrent:concurrent-futures-ktx:1.1.0
androidx.concurrent:concurrent-futures:1.1.0
@ -79,8 +79,8 @@ androidx.datastore:datastore-preferences:1.1.1
androidx.datastore:datastore:1.1.1
androidx.documentfile:documentfile:1.0.0
androidx.drawerlayout:drawerlayout:1.0.0
androidx.emoji2:emoji2-views-helper:1.3.0
androidx.emoji2:emoji2:1.3.0
androidx.emoji2:emoji2-views-helper:1.4.0
androidx.emoji2:emoji2:1.4.0
androidx.exifinterface:exifinterface:1.3.7
androidx.fragment:fragment:1.5.4
androidx.graphics:graphics-path:1.0.1
@ -164,10 +164,10 @@ com.google.android.gms:play-services-oss-licenses:17.1.0
com.google.android.gms:play-services-stats:17.0.2
com.google.android.gms:play-services-tasks:18.2.0
com.google.code.findbugs:jsr305:3.0.2
com.google.dagger:dagger-lint-aar:2.53.1
com.google.dagger:dagger:2.53.1
com.google.dagger:hilt-android:2.53.1
com.google.dagger:hilt-core:2.53.1
com.google.dagger:dagger-lint-aar:2.54
com.google.dagger:dagger:2.54
com.google.dagger:hilt-android:2.54
com.google.dagger:hilt-core:2.54
com.google.errorprone:error_prone_annotations:2.26.0
com.google.firebase:firebase-abt:21.1.1
com.google.firebase:firebase-analytics:22.1.2
@ -216,18 +216,18 @@ org.jetbrains.kotlin:kotlin-stdlib-common:2.1.0
org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.9.0
org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.0
org.jetbrains.kotlin:kotlin-stdlib:2.1.0
org.jetbrains.kotlinx:kotlinx-coroutines-android:1.9.0
org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.9.0
org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.9.0
org.jetbrains.kotlinx:kotlinx-coroutines-core:1.9.0
org.jetbrains.kotlinx:kotlinx-coroutines-guava:1.9.0
org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.9.0
org.jetbrains.kotlinx:kotlinx-coroutines-android:1.10.1
org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.10.1
org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.10.1
org.jetbrains.kotlinx:kotlinx-coroutines-core:1.10.1
org.jetbrains.kotlinx:kotlinx-coroutines-guava:1.10.1
org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.10.1
org.jetbrains.kotlinx:kotlinx-datetime-jvm:0.6.1
org.jetbrains.kotlinx:kotlinx-datetime:0.6.1
org.jetbrains.kotlinx:kotlinx-serialization-bom:1.7.3
org.jetbrains.kotlinx:kotlinx-serialization-core-jvm:1.7.3
org.jetbrains.kotlinx:kotlinx-serialization-core:1.7.3
org.jetbrains.kotlinx:kotlinx-serialization-json-jvm:1.7.3
org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.3
org.jetbrains.kotlinx:kotlinx-serialization-bom:1.8.0
org.jetbrains.kotlinx:kotlinx-serialization-core-jvm:1.8.0
org.jetbrains.kotlinx:kotlinx-serialization-core:1.8.0
org.jetbrains.kotlinx:kotlinx-serialization-json-jvm:1.8.0
org.jetbrains.kotlinx:kotlinx-serialization-json:1.8.0
org.jetbrains:annotations:23.0.0
org.jspecify:jspecify:1.0.0

@ -21,7 +21,9 @@
<style name="NightAdjusted.Theme.Nia" parent="android:Theme.Material.Light.NoActionBar" />
<!-- The final theme we use -->
<style name="Theme.Nia" parent="NightAdjusted.Theme.Nia" />
<style name="Theme.Nia" parent="NightAdjusted.Theme.Nia">
<item name="android:forceDarkAllowed" tools:targetApi="29">false</item>
</style>
<style name="NightAdjusted.Theme.Splash" parent="Theme.SplashScreen">
<item name="android:windowLightStatusBar" tools:targetApi="23">true</item>

@ -31,6 +31,8 @@ import com.google.samples.apps.nowinandroid.core.testing.repository.TestNewsRepo
import com.google.samples.apps.nowinandroid.core.testing.repository.TestUserDataRepository
import com.google.samples.apps.nowinandroid.core.testing.util.TestNetworkMonitor
import com.google.samples.apps.nowinandroid.core.testing.util.TestTimeZoneMonitor
import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.HiltTestApplication
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
import kotlinx.coroutines.test.UnconfinedTestDispatcher
@ -38,15 +40,18 @@ import kotlinx.coroutines.test.runTest
import kotlinx.datetime.TimeZone
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
import org.robolectric.annotation.Config
import kotlin.test.assertEquals
import kotlin.test.assertTrue
/**
* Tests [NiaAppState].
*
* Note: This could become an unit test if Robolectric is added to the project and the Context
* is faked.
*/
@RunWith(RobolectricTestRunner::class)
@Config(application = HiltTestApplication::class)
@HiltAndroidTest
class NiaAppStateTest {
@get:Rule

@ -23,18 +23,17 @@ import com.google.samples.apps.nowinandroid.configureKotlinAndroid
import com.google.samples.apps.nowinandroid.configurePrintApksTask
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.apply
import org.gradle.kotlin.dsl.configure
import org.gradle.kotlin.dsl.getByType
class AndroidApplicationConventionPlugin : Plugin<Project> {
override fun apply(target: Project) {
with(target) {
with(pluginManager) {
apply("com.android.application")
apply("org.jetbrains.kotlin.android")
apply("nowinandroid.android.lint")
apply("com.dropbox.dependency-guard")
}
apply(plugin = "com.android.application")
apply(plugin = "org.jetbrains.kotlin.android")
apply(plugin = "nowinandroid.android.lint")
apply(plugin = "com.dropbox.dependency-guard")
extensions.configure<ApplicationExtension> {
configureKotlinAndroid(this)
@ -49,5 +48,4 @@ class AndroidApplicationConventionPlugin : Plugin<Project> {
}
}
}
}

@ -19,6 +19,7 @@ import com.google.firebase.crashlytics.buildtools.gradle.CrashlyticsExtension
import com.google.samples.apps.nowinandroid.libs
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.apply
import org.gradle.kotlin.dsl.configure
import org.gradle.kotlin.dsl.dependencies
import org.gradle.kotlin.dsl.exclude
@ -26,11 +27,9 @@ import org.gradle.kotlin.dsl.exclude
class AndroidApplicationFirebaseConventionPlugin : Plugin<Project> {
override fun apply(target: Project) {
with(target) {
with(pluginManager) {
apply("com.google.gms.google-services")
apply("com.google.firebase.firebase-perf")
apply("com.google.firebase.crashlytics")
}
apply(plugin = "com.google.gms.google-services")
apply(plugin = "com.google.firebase.firebase-perf")
apply(plugin = "com.google.firebase.crashlytics")
dependencies {
val bom = libs.findLibrary("firebase-bom").get()

@ -19,12 +19,14 @@ import com.android.build.api.variant.ApplicationAndroidComponentsExtension
import com.google.samples.apps.nowinandroid.configureJacoco
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.apply
import org.gradle.kotlin.dsl.getByType
class AndroidApplicationJacocoConventionPlugin : Plugin<Project> {
override fun apply(target: Project) {
with(target) {
pluginManager.apply("jacoco")
apply(plugin = "jacoco")
val androidExtension = extensions.getByType<ApplicationExtension>()
androidExtension.buildTypes.configureEach {

@ -19,17 +19,17 @@ import com.google.samples.apps.nowinandroid.configureGradleManagedDevices
import com.google.samples.apps.nowinandroid.libs
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.apply
import org.gradle.kotlin.dsl.configure
import org.gradle.kotlin.dsl.dependencies
class AndroidFeatureConventionPlugin : Plugin<Project> {
override fun apply(target: Project) {
with(target) {
pluginManager.apply {
apply("nowinandroid.android.library")
apply("nowinandroid.hilt")
apply("org.jetbrains.kotlin.plugin.serialization")
}
apply(plugin = "nowinandroid.android.library")
apply(plugin = "nowinandroid.hilt")
apply(plugin = "org.jetbrains.kotlin.plugin.serialization")
extensions.configure<LibraryExtension> {
testOptions.animationsDisabled = true
configureGradleManagedDevices(this)
@ -47,7 +47,9 @@ class AndroidFeatureConventionPlugin : Plugin<Project> {
"implementation"(libs.findLibrary("kotlinx.serialization.json").get())
"testImplementation"(libs.findLibrary("androidx.navigation.testing").get())
"androidTestImplementation"(libs.findLibrary("androidx.lifecycle.runtimeTesting").get())
"androidTestImplementation"(
libs.findLibrary("androidx.lifecycle.runtimeTesting").get(),
)
}
}
}

@ -24,17 +24,16 @@ import com.google.samples.apps.nowinandroid.disableUnnecessaryAndroidTests
import com.google.samples.apps.nowinandroid.libs
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.apply
import org.gradle.kotlin.dsl.configure
import org.gradle.kotlin.dsl.dependencies
class AndroidLibraryConventionPlugin : Plugin<Project> {
override fun apply(target: Project) {
with(target) {
with(pluginManager) {
apply("com.android.library")
apply("org.jetbrains.kotlin.android")
apply("nowinandroid.android.lint")
}
apply(plugin = "com.android.library")
apply(plugin = "org.jetbrains.kotlin.android")
apply(plugin = "nowinandroid.android.lint")
extensions.configure<LibraryExtension> {
configureKotlinAndroid(this)
@ -45,7 +44,9 @@ class AndroidLibraryConventionPlugin : Plugin<Project> {
configureGradleManagedDevices(this)
// The resource prefix is derived from the module name,
// so resources inside ":core:module1" must be prefixed with "core_module1_"
resourcePrefix = path.split("""\W""".toRegex()).drop(1).distinct().joinToString(separator = "_").lowercase() + "_"
resourcePrefix =
path.split("""\W""".toRegex()).drop(1).distinct().joinToString(separator = "_")
.lowercase() + "_"
}
extensions.configure<LibraryAndroidComponentsExtension> {
configurePrintApksTask(this)

@ -15,17 +15,18 @@
*/
import com.android.build.api.dsl.LibraryExtension
import com.android.build.api.variant.ApplicationAndroidComponentsExtension
import com.android.build.api.variant.LibraryAndroidComponentsExtension
import com.google.samples.apps.nowinandroid.configureJacoco
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.apply
import org.gradle.kotlin.dsl.getByType
class AndroidLibraryJacocoConventionPlugin : Plugin<Project> {
override fun apply(target: Project) {
with(target) {
pluginManager.apply("jacoco")
apply(plugin = "jacoco")
val androidExtension = extensions.getByType<LibraryExtension>()
androidExtension.buildTypes.configureEach {

@ -19,6 +19,7 @@ import com.android.build.api.dsl.LibraryExtension
import com.android.build.api.dsl.Lint
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.apply
import org.gradle.kotlin.dsl.configure
class AndroidLintConventionPlugin : Plugin<Project> {
@ -32,7 +33,7 @@ class AndroidLintConventionPlugin : Plugin<Project> {
configure<LibraryExtension> { lint(Lint::configure) }
else -> {
pluginManager.apply("com.android.lint")
apply(plugin = "com.android.lint")
configure<Lint>(Lint::configure)
}
}

@ -19,6 +19,7 @@ import com.google.devtools.ksp.gradle.KspExtension
import com.google.samples.apps.nowinandroid.libs
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.apply
import org.gradle.kotlin.dsl.configure
import org.gradle.kotlin.dsl.dependencies
@ -26,8 +27,8 @@ class AndroidRoomConventionPlugin : Plugin<Project> {
override fun apply(target: Project) {
with(target) {
pluginManager.apply("androidx.room")
pluginManager.apply("com.google.devtools.ksp")
apply(plugin = "androidx.room")
apply(plugin = "com.google.devtools.ksp")
extensions.configure<KspExtension> {
arg("room.generateKotlin", "true")

@ -19,15 +19,14 @@ import com.google.samples.apps.nowinandroid.configureGradleManagedDevices
import com.google.samples.apps.nowinandroid.configureKotlinAndroid
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.apply
import org.gradle.kotlin.dsl.configure
class AndroidTestConventionPlugin : Plugin<Project> {
override fun apply(target: Project) {
with(target) {
with(pluginManager) {
apply("com.android.test")
apply("org.jetbrains.kotlin.android")
}
apply(plugin = "com.android.test")
apply(plugin = "org.jetbrains.kotlin.android")
extensions.configure<TestExtension> {
configureKotlinAndroid(this)
@ -36,5 +35,4 @@ class AndroidTestConventionPlugin : Plugin<Project> {
}
}
}
}

@ -18,12 +18,14 @@ import com.android.build.gradle.api.AndroidBasePlugin
import com.google.samples.apps.nowinandroid.libs
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.apply
import org.gradle.kotlin.dsl.dependencies
class HiltConventionPlugin : Plugin<Project> {
override fun apply(target: Project) {
with(target) {
pluginManager.apply("com.google.devtools.ksp")
apply(plugin = "com.google.devtools.ksp")
dependencies {
"ksp"(libs.findLibrary("hilt.compiler").get())
}
@ -37,7 +39,7 @@ class HiltConventionPlugin : Plugin<Project> {
/** Add support for Android modules, based on [AndroidBasePlugin] */
pluginManager.withPlugin("com.android.base") {
pluginManager.apply("dagger.hilt.android.plugin")
apply(plugin = "dagger.hilt.android.plugin")
dependencies {
"implementation"(libs.findLibrary("hilt.android").get())
}

@ -18,15 +18,15 @@ import com.google.samples.apps.nowinandroid.configureKotlinJvm
import com.google.samples.apps.nowinandroid.libs
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.apply
import org.gradle.kotlin.dsl.dependencies
class JvmLibraryConventionPlugin : Plugin<Project> {
override fun apply(target: Project) {
with(target) {
with(pluginManager) {
apply("org.jetbrains.kotlin.jvm")
apply("nowinandroid.android.lint")
}
apply(plugin = "org.jetbrains.kotlin.jvm")
apply(plugin = "nowinandroid.android.lint")
configureKotlinJvm()
dependencies {
"testImplementation"(libs.findLibrary("kotlin.test").get())

@ -2,3 +2,5 @@
org.gradle.parallel=true
org.gradle.caching=true
org.gradle.configureondemand=true
org.gradle.configuration-cache=true
org.gradle.configuration-cache.parallel=true

@ -25,7 +25,7 @@ buildscript {
}
mavenCentral()
// Android Build Server
// This is used only for internal Google builds.
maven { url = uri("../nowinandroid-prebuilts/m2repository") }
}
dependencies {

@ -89,6 +89,7 @@ class OfflineFirstNewsRepositoryTest {
@Test
fun offlineFirstNewsRepository_news_resources_stream_is_backed_by_news_resource_dao() =
testScope.runTest {
subject.syncWith(synchronizer)
assertEquals(
newsResourceDao.getNewsResources()
.first()

@ -67,6 +67,8 @@ class OfflineFirstTopicsRepositoryTest {
@Test
fun offlineFirstTopicsRepository_topics_stream_is_backed_by_topics_dao() =
testScope.runTest {
subject.syncWith(synchronizer)
assertEquals(
topicDao.getTopicEntities()
.first()

@ -0,0 +1,47 @@
/*
* Copyright 2025 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.core.database.dao
import android.content.Context
import androidx.room.Room
import androidx.test.core.app.ApplicationProvider
import com.google.samples.apps.nowinandroid.core.database.NiaDatabase
import org.junit.After
import org.junit.Before
internal abstract class DatabaseTest {
private lateinit var db: NiaDatabase
protected lateinit var newsResourceDao: NewsResourceDao
protected lateinit var topicDao: TopicDao
@Before
fun setup() {
db = run {
val context = ApplicationProvider.getApplicationContext<Context>()
Room.inMemoryDatabaseBuilder(
context,
NiaDatabase::class.java,
).build()
}
newsResourceDao = db.newsResourceDao()
topicDao = db.topicDao()
}
@After
fun teardown() = db.close()
}

@ -16,10 +16,6 @@
package com.google.samples.apps.nowinandroid.core.database.dao
import android.content.Context
import androidx.room.Room
import androidx.test.core.app.ApplicationProvider
import com.google.samples.apps.nowinandroid.core.database.NiaDatabase
import com.google.samples.apps.nowinandroid.core.database.model.NewsResourceEntity
import com.google.samples.apps.nowinandroid.core.database.model.NewsResourceTopicCrossRef
import com.google.samples.apps.nowinandroid.core.database.model.TopicEntity
@ -27,36 +23,13 @@ import com.google.samples.apps.nowinandroid.core.database.model.asExternalModel
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.test.runTest
import kotlinx.datetime.Instant
import org.junit.After
import org.junit.Before
import org.junit.Test
import kotlin.test.assertEquals
/**
* Instrumentation tests for [NewsResourceDao].
*/
class NewsResourceDaoTest {
private lateinit var newsResourceDao: NewsResourceDao
private lateinit var topicDao: TopicDao
private lateinit var db: NiaDatabase
@Before
fun createDb() {
val context = ApplicationProvider.getApplicationContext<Context>()
db = Room.inMemoryDatabaseBuilder(
context,
NiaDatabase::class.java,
).build()
newsResourceDao = db.newsResourceDao()
topicDao = db.topicDao()
}
@After
fun closeDb() = db.close()
internal class NewsResourceDaoTest : DatabaseTest() {
@Test
fun newsResourceDao_fetches_items_by_descending_publish_date() = runTest {
fun getNewsResources_allEntries_areOrderedByPublishDateDesc() = runTest {
val newsResourceEntities = listOf(
testNewsResource(
id = "0",
@ -91,7 +64,7 @@ class NewsResourceDaoTest {
}
@Test
fun newsResourceDao_filters_items_by_news_ids_by_descending_publish_date() = runTest {
fun getNewsResources_filteredById_areOrderedByDescendingPublishDate() = runTest {
val newsResourceEntities = listOf(
testNewsResource(
id = "0",
@ -129,7 +102,7 @@ class NewsResourceDaoTest {
}
@Test
fun newsResourceDao_filters_items_by_topic_ids_by_descending_publish_date() = runTest {
fun getNewsResources_filteredByTopicId_areOrderedByDescendingPublishDate() = runTest {
val topicEntities = listOf(
testTopicEntity(
id = "1",
@ -189,7 +162,7 @@ class NewsResourceDaoTest {
}
@Test
fun newsResourceDao_filters_items_by_news_and_topic_ids_by_descending_publish_date() = runTest {
fun getNewsResources_filteredByIdAndTopicId_areOrderedByDescendingPublishDate() = runTest {
val topicEntities = listOf(
testTopicEntity(
id = "1",
@ -251,7 +224,7 @@ class NewsResourceDaoTest {
}
@Test
fun newsResourceDao_deletes_items_by_ids() =
fun deleteNewsResources_byId() =
runTest {
val newsResourceEntities = listOf(
testNewsResource(

@ -0,0 +1,126 @@
/*
* Copyright 2024 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.core.database.dao
import com.google.samples.apps.nowinandroid.core.database.model.TopicEntity
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.test.runTest
import org.junit.Test
import kotlin.test.assertEquals
internal class TopicDaoTest : DatabaseTest() {
@Test
fun getTopics() = runTest {
insertTopics()
val savedTopics = topicDao.getTopicEntities().first()
assertEquals(
listOf("1", "2", "3"),
savedTopics.map { it.id },
)
}
@Test
fun getTopic() = runTest {
insertTopics()
val savedTopicEntity = topicDao.getTopicEntity("2").first()
assertEquals("performance", savedTopicEntity.name)
}
@Test
fun getTopics_oneOff() = runTest {
insertTopics()
val savedTopics = topicDao.getOneOffTopicEntities()
assertEquals(
listOf("1", "2", "3"),
savedTopics.map { it.id },
)
}
@Test
fun getTopics_byId() = runTest {
insertTopics()
val savedTopics = topicDao.getTopicEntities(setOf("1", "2"))
.first()
assertEquals(listOf("compose", "performance"), savedTopics.map { it.name })
}
@Test
fun insertTopic_newEntryIsIgnoredIfAlreadyExists() = runTest {
insertTopics()
topicDao.insertOrIgnoreTopics(
listOf(testTopicEntity("1", "compose")),
)
val savedTopics = topicDao.getOneOffTopicEntities()
assertEquals(3, savedTopics.size)
}
@Test
fun upsertTopic_existingEntryIsUpdated() = runTest {
insertTopics()
topicDao.upsertTopics(
listOf(testTopicEntity("1", "newName")),
)
val savedTopics = topicDao.getOneOffTopicEntities()
assertEquals(3, savedTopics.size)
assertEquals("newName", savedTopics.first().name)
}
@Test
fun deleteTopics_byId_existingEntriesAreDeleted() = runTest {
insertTopics()
topicDao.deleteTopics(listOf("1", "2"))
val savedTopics = topicDao.getOneOffTopicEntities()
assertEquals(1, savedTopics.size)
assertEquals("3", savedTopics.first().id)
}
private suspend fun insertTopics() {
val topicEntities = listOf(
testTopicEntity("1", "compose"),
testTopicEntity("2", "performance"),
testTopicEntity("3", "headline"),
)
topicDao.insertOrIgnoreTopics(topicEntities)
}
}
private fun testTopicEntity(
id: String = "0",
name: String,
) = TopicEntity(
id = id,
name = name,
shortDescription = "",
longDescription = "",
url = "",
imageUrl = "",
)

@ -17,6 +17,8 @@
package com.google.samples.apps.nowinandroid.core.network.demo
import JvmUnitTestDemoAssetManager
import android.os.Build.VERSION.SDK_INT
import android.os.Build.VERSION_CODES.M
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.NiaNetworkDataSource
@ -28,6 +30,7 @@ import kotlinx.coroutines.withContext
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.decodeFromStream
import java.io.BufferedReader
import javax.inject.Inject
/**
@ -39,17 +42,11 @@ class DemoNiaNetworkDataSource @Inject constructor(
private val assets: DemoAssetManager = JvmUnitTestDemoAssetManager,
) : NiaNetworkDataSource {
@OptIn(ExperimentalSerializationApi::class)
override suspend fun getTopics(ids: List<String>?): List<NetworkTopic> =
withContext(ioDispatcher) {
assets.open(TOPICS_ASSET).use(networkJson::decodeFromStream)
}
getDataFromJsonFile(TOPICS_ASSET)
@OptIn(ExperimentalSerializationApi::class)
override suspend fun getNewsResources(ids: List<String>?): List<NetworkNewsResource> =
withContext(ioDispatcher) {
assets.open(NEWS_ASSET).use(networkJson::decodeFromStream)
}
getDataFromJsonFile(NEWS_ASSET)
override suspend fun getTopicChangeList(after: Int?): List<NetworkChangeList> =
getTopics().mapToChangeList(NetworkTopic::id)
@ -57,6 +54,27 @@ class DemoNiaNetworkDataSource @Inject constructor(
override suspend fun getNewsResourceChangeList(after: Int?): List<NetworkChangeList> =
getNewsResources().mapToChangeList(NetworkNewsResource::id)
/**
* Get data from the given JSON [fileName].
*/
@OptIn(ExperimentalSerializationApi::class)
private suspend inline fun <reified T> getDataFromJsonFile(fileName: String): List<T> =
withContext(ioDispatcher) {
assets.open(fileName).use { inputStream ->
if (SDK_INT <= M) {
/**
* On API 23 (M) and below we must use a workaround to avoid an exception being
* thrown during deserialization. See:
* https://github.com/Kotlin/kotlinx.serialization/issues/2457#issuecomment-1786923342
*/
inputStream.bufferedReader().use(BufferedReader::readText)
.let(networkJson::decodeFromString)
} else {
networkJson.decodeFromStream(inputStream)
}
}
}
companion object {
private const val NEWS_ASSET = "news.json"
private const val TOPICS_ASSET = "topics.json"

@ -24,7 +24,6 @@ import androidx.compose.foundation.Canvas
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.Image
import androidx.compose.foundation.draganddrop.dragAndDropSource
import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.horizontalScroll
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
@ -139,19 +138,13 @@ fun NewsResourceCardExpanded(
userNewsResource.title,
modifier = Modifier
.fillMaxWidth((.8f))
.dragAndDropSource {
detectTapGestures(
onLongPress = {
startTransfer(
DragAndDropTransferData(
ClipData.newPlainText(
sharingLabel,
sharingContent,
),
flags = dragAndDropFlags,
),
)
},
.dragAndDropSource { _ ->
DragAndDropTransferData(
ClipData.newPlainText(
sharingLabel,
sharingContent,
),
flags = dragAndDropFlags,
)
},
)

@ -39,6 +39,7 @@ org.gradle.caching=true
# Enable configuration caching between builds.
org.gradle.configuration-cache=true
org.gradle.configuration-cache.parallel=true
# This option is set because of https://github.com/google/play-services-plugins/issues/246
# to generate the Configuration Cache regardless of incompatible tasks.
# See https://github.com/android/nowinandroid/issues/1022 before using it.

@ -1,6 +1,6 @@
[versions]
accompanist = "0.37.0"
androidDesugarJdkLibs = "2.1.3"
androidDesugarJdkLibs = "2.1.4"
# AGP and tools should be updated together
androidGradlePlugin = "8.7.3"
androidTools = "31.7.3"
@ -8,6 +8,7 @@ androidxActivity = "1.9.3"
androidxAppCompat = "1.7.0"
androidxBrowser = "1.8.0"
androidxComposeBom = "2024.12.01"
androidxComposeFoundation = "1.8.0-alpha07"
androidxComposeRuntimeTracing = "1.7.6"
androidxCore = "1.15.0"
androidxCoreSplashscreen = "1.0.1"
@ -36,14 +37,14 @@ firebasePerfPlugin = "1.4.2"
gmsPlugin = "4.4.2"
googleOss = "17.1.0"
googleOssPlugin = "0.10.6"
hilt = "2.53.1"
hilt = "2.54"
hiltExt = "1.2.0"
jacoco = "0.8.12"
junit4 = "4.13.2"
kotlin = "2.1.0"
kotlinxCoroutines = "1.9.0"
kotlinxCoroutines = "1.10.1"
kotlinxDatetime = "0.6.1"
kotlinxSerializationJson = "1.7.3"
kotlinxSerializationJson = "1.8.0"
ksp = "2.1.0-1.0.29"
moduleGraph = "2.7.1"
okhttp = "4.12.0"
@ -52,7 +53,7 @@ protobufPlugin = "0.9.4"
retrofit = "2.11.0"
retrofitKotlinxSerializationJson = "1.0.0"
robolectric = "4.14.1"
roborazzi = "1.37.0"
roborazzi = "1.39.0"
room = "2.6.1"
secrets = "2.0.1"
truth = "1.4.4"
@ -69,7 +70,7 @@ androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version
androidx-benchmark-macro = { group = "androidx.benchmark", name = "benchmark-macro-junit4", version.ref = "androidxMacroBenchmark" }
androidx-browser = { group = "androidx.browser", name = "browser", version.ref = "androidxBrowser" }
androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "androidxComposeBom" }
androidx-compose-foundation = { group = "androidx.compose.foundation", name = "foundation" }
androidx-compose-foundation = { group = "androidx.compose.foundation", name = "foundation", version.ref = "androidxComposeFoundation" }
androidx-compose-foundation-layout = { group = "androidx.compose.foundation", name = "foundation-layout" }
androidx-compose-material-iconsExtended = { group = "androidx.compose.material", name = "material-icons-extended" }
androidx-compose-material3 = { group = "androidx.compose.material3", name = "material3" }

@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME

Loading…
Cancel
Save