Replace the development fixture shell with method intro, question, coin entry, and result screens. Persist locked casts in private Room storage under the save policy, and document remaining P2 content and P4 history-list gaps. Co-authored-by: Cursor <cursoragent@cursor.com>
167 lines
5.4 KiB
Kotlin
167 lines
5.4 KiB
Kotlin
import groovy.json.JsonSlurper
|
|
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
|
|
|
plugins {
|
|
alias(libs.plugins.android.application)
|
|
alias(libs.plugins.kotlin.android)
|
|
alias(libs.plugins.kotlin.kapt)
|
|
alias(libs.plugins.hilt)
|
|
}
|
|
|
|
android {
|
|
namespace = "net.opcapp.flash"
|
|
compileSdk = 34
|
|
|
|
defaultConfig {
|
|
applicationId = "net.opcapp.flash"
|
|
minSdk = 26
|
|
targetSdk = 34
|
|
versionCode = 1
|
|
versionName = "0.1.0"
|
|
|
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
|
vectorDrawables.useSupportLibrary = true
|
|
|
|
javaCompileOptions {
|
|
annotationProcessorOptions {
|
|
arguments += mapOf("room.schemaLocation" to "$projectDir/schemas")
|
|
}
|
|
}
|
|
}
|
|
|
|
buildTypes {
|
|
release {
|
|
isMinifyEnabled = false
|
|
proguardFiles(
|
|
getDefaultProguardFile("proguard-android-optimize.txt"),
|
|
"proguard-rules.pro",
|
|
)
|
|
}
|
|
}
|
|
|
|
buildFeatures {
|
|
compose = true
|
|
buildConfig = false
|
|
}
|
|
|
|
composeOptions {
|
|
kotlinCompilerExtensionVersion = libs.versions.composeCompiler.get()
|
|
}
|
|
|
|
compileOptions {
|
|
sourceCompatibility = JavaVersion.VERSION_17
|
|
targetCompatibility = JavaVersion.VERSION_17
|
|
}
|
|
|
|
packaging {
|
|
resources.excludes += "/META-INF/{AL2.0,LGPL2.1}"
|
|
}
|
|
|
|
testOptions {
|
|
unitTests.isReturnDefaultValues = true
|
|
}
|
|
}
|
|
|
|
kotlin {
|
|
jvmToolchain(17)
|
|
}
|
|
|
|
kapt {
|
|
correctErrorTypes = true
|
|
}
|
|
|
|
tasks.withType<KotlinCompile>().configureEach {
|
|
kotlinOptions.jvmTarget = "17"
|
|
}
|
|
|
|
dependencies {
|
|
val composeBom = platform(libs.androidx.compose.bom)
|
|
|
|
implementation(libs.androidx.core.ktx)
|
|
implementation(libs.androidx.activity.compose)
|
|
implementation(libs.androidx.lifecycle.runtime.ktx)
|
|
implementation(libs.androidx.lifecycle.runtime.compose)
|
|
implementation(libs.androidx.lifecycle.viewmodel.compose)
|
|
implementation(composeBom)
|
|
implementation(libs.androidx.compose.ui)
|
|
implementation(libs.androidx.compose.ui.tooling.preview)
|
|
implementation(libs.androidx.compose.material3)
|
|
implementation(libs.androidx.navigation.compose)
|
|
implementation(libs.androidx.room.runtime)
|
|
implementation(libs.androidx.room.ktx)
|
|
kapt(libs.androidx.room.compiler)
|
|
implementation(libs.androidx.datastore.preferences)
|
|
implementation(libs.hilt.android)
|
|
kapt(libs.hilt.compiler)
|
|
|
|
testImplementation(libs.junit)
|
|
|
|
androidTestImplementation(composeBom)
|
|
androidTestImplementation(libs.androidx.test.ext.junit)
|
|
androidTestImplementation(libs.androidx.test.runner)
|
|
androidTestImplementation(libs.androidx.compose.ui.test.junit4)
|
|
androidTestImplementation(libs.androidx.room.testing)
|
|
|
|
debugImplementation(libs.androidx.compose.ui.tooling)
|
|
debugImplementation(libs.androidx.compose.ui.test.manifest)
|
|
}
|
|
|
|
tasks.withType<Test>().configureEach {
|
|
useJUnit()
|
|
maxParallelForks = 1
|
|
maxHeapSize = "192m"
|
|
jvmArgs("-XX:MaxMetaspaceSize=128m", "-XX:+UseSerialGC")
|
|
testLogging {
|
|
events("failed", "skipped")
|
|
exceptionFormat = org.gradle.api.tasks.testing.logging.TestExceptionFormat.FULL
|
|
}
|
|
}
|
|
|
|
tasks.register("verifyDependencyLicenses") {
|
|
group = "verification"
|
|
description = "Ensures every resolved debug runtime/test artifact has a reviewed license entry."
|
|
|
|
doLast {
|
|
@Suppress("UNCHECKED_CAST")
|
|
val manifest = JsonSlurper().parse(rootProject.file("config/dependency-licenses.json")) as Map<String, Any>
|
|
@Suppress("UNCHECKED_CAST")
|
|
val components = manifest.getValue("components") as List<Map<String, Any>>
|
|
@Suppress("UNCHECKED_CAST")
|
|
val groupPolicies = manifest.getValue("groupPolicies") as List<Map<String, Any>>
|
|
val reviewedCoordinates = components.mapNotNull { it["coordinates"] as String? }.toSet()
|
|
val resolvedCoordinates = listOf(
|
|
"debugRuntimeClasspath",
|
|
"debugUnitTestRuntimeClasspath",
|
|
"debugAndroidTestRuntimeClasspath",
|
|
)
|
|
.flatMap { configurationName ->
|
|
configurations.getByName(configurationName)
|
|
.resolvedConfiguration
|
|
.resolvedArtifacts
|
|
.mapNotNull { artifact ->
|
|
if (artifact.id.componentIdentifier !is org.gradle.api.artifacts.component.ModuleComponentIdentifier) {
|
|
return@mapNotNull null
|
|
}
|
|
val id = artifact.moduleVersion.id
|
|
"${id.group}:${id.name}:${id.version}"
|
|
}
|
|
}
|
|
.toSet()
|
|
val missing = resolvedCoordinates.filterNot { coordinates ->
|
|
if (coordinates in reviewedCoordinates) return@filterNot true
|
|
val group = coordinates.substringBefore(":")
|
|
groupPolicies.any { policy ->
|
|
val prefix = policy.getValue("groupPrefix") as String
|
|
group == prefix || group.startsWith("$prefix.")
|
|
}
|
|
}
|
|
check(missing.isEmpty()) {
|
|
"Dependencies missing reviewed license entries: ${missing.sorted().joinToString()}"
|
|
}
|
|
logger.lifecycle(
|
|
"Dependency license coverage passed for ${resolvedCoordinates.size} artifacts " +
|
|
"with ${groupPolicies.size} reviewed group policies.",
|
|
)
|
|
}
|
|
}
|