Files
Amber/app/build.gradle.kts
greenart7c3 d8e4caad67 Fix Android Studio's inspection findings and turn off its spell check
Android Studio's batch inspections reported about 800 problems besides
spelling, which the project profile now leaves off (it mostly flagged
the translations).

Real bugs among them: the desktop's strings files had empty strings
where Android has translations (German, Spanish, Brazilian Portuguese,
Chinese), showing blank text; and IS_FDROID_BUILD, which the F-Droid
workflow flips with sed, was read as a constant the IDE wanted to
simplify away, so it is now read through BuildFlavorChecker.isFdroidBuild().
Account loads in coroutines (relay, intent and UI paths) and logout no
longer block a thread with runBlocking; the blocking ContentProvider
path and the desktop lock say why they do.

Also remove what was dead (the drawable IconRow overload, PermissionCard,
ConfirmationToastMsg, the desktop OkHttpWebSocket.Builder and
DeleteAfterType.screenCode, the QR drawer's zero corner radius math and
the strings only they used), move to the Duration overloads, give
subject-less when blocks their subject, drop redundant opt-ins, suspend
modifiers, qualifiers and SAM constructors, fix broken KDoc links, take
the ktlint and KSP plugin versions from the catalog, strip editor
metadata from the SVGs, align the Markdown tables and fix real grammar
and spelling in comments, docs and three English strings.
2026-10-26 17:28:06 -03:00

322 lines
9.5 KiB
Kotlin

import java.io.FileInputStream
import java.util.Properties
plugins {
alias(libs.plugins.androidApplication)
alias(libs.plugins.gradle.ktlint)
alias(libs.plugins.detekt)
alias(libs.plugins.kotlin.ksp)
alias(libs.plugins.jetbrainsComposeCompiler)
}
android {
namespace = "com.greenart7c3.nostrsigner"
compileSdk = 37
// AGP strips native libraries with this NDK while packaging, so it is an
// APK input: pinned (and installed by the reproducibility Dockerfile) so
// release and verification builds strip identically across AGP bumps.
ndkVersion = "28.2.13676358"
defaultConfig {
applicationId = "com.greenart7c3.nostrsigner"
minSdk = 26
versionCode = libs.versions.amberVersionCode.get().toInt()
versionName = libs.versions.amberVersionName.get()
buildConfigField("boolean", "IS_FDROID_BUILD", "false")
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {
useSupportLibrary = true
}
}
lint {
// Any new warning fails the build (enforced by the pre-commit/pre-push hooks and CI)
warningsAsErrors = true
abortOnError = true
disable += listOf(
"MissingTranslation",
"LocalContextGetResourceValueCall",
// Version bumps are handled deliberately, not because a hook went red the
// day a new release was published
"AndroidGradlePluginVersion",
"GradleDependency",
"NewerVersionAvailable",
// Resource shrinking is a release-packaging decision, tracked separately
"NotShrinkingResources",
)
}
androidResources {
// Still @Incubating in AGP.
@Suppress("UnstableApiUsage")
localeFilters += listOf(
"bn-rBD",
"cs",
"cy-rGB",
"da-rDK",
"de",
"el-rGR",
"en-rGB",
"eo",
"es",
"es-rES",
"es-rMX",
"es-rUS",
"et-rEE",
"fa",
"fi-rFI",
"fo-rFO",
"fr",
"fr-rCA",
"gu-rIN",
"hi-rIN",
"hr-rHR",
"hu",
"in",
"in-rID",
"it-rIT",
"iw-rIL",
"ja",
"kk-rKZ",
"ko-rKR",
"ks-rIN",
"ku-rTR",
"lt-rLT",
"ne-rNP",
"nl",
"nl-rBE",
"pcm-rNG",
"pl-rPL",
"pt-rBR",
"pt-rPT",
"ru",
"ru-rUA",
"sa-rIN",
"sl-rSI",
"so-rSO",
"sr-rSP",
"ss-rZA",
"sv-rSE",
"sw-rKE",
"sw-rTZ",
"ta",
"th",
"tr",
"uk",
"ur-rIN",
"uz-rUZ",
"vi-rVN",
"zh",
"zh-rCN",
"zh-rHK",
"zh-rSG",
"zh-rTW",
)
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_21
targetCompatibility = JavaVersion.VERSION_21
}
if (System.getenv("SIGN_RELEASE") != null) {
val keystorePropertiesFile = rootProject.file("keystore.properties")
val keystoreProperties = Properties()
keystoreProperties.load(FileInputStream(keystorePropertiesFile))
signingConfigs {
create("release") {
keyAlias = keystoreProperties["keyAlias"] as String
keyPassword = keystoreProperties["keyPassword"] as String
storeFile = file(keystoreProperties["storeFile"] as String)
storePassword = keystoreProperties["storePassword"] as String
}
}
}
buildTypes {
release {
if (System.getenv("SIGN_RELEASE") != null) {
signingConfig = signingConfigs.getByName("release")
}
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
isMinifyEnabled = true
resValue("string", "app_name", "@string/app_name_release")
}
debug {
applicationIdSuffix = ".debug"
versionNameSuffix = "-DEBUG"
resValue("string", "app_name", "@string/app_name_debug")
}
}
flavorDimensions += "version"
productFlavors {
register("free") {
isDefault = true
dimension = "version"
}
register("offline") {
dimension = "version"
}
// Online variant (same network stack as `free`) built and uploaded by CI on
// every push so changes can be installed and reviewed per commit. The distinct
// applicationId suffix lets it sit side-by-side with a production install.
register("benchmark") {
dimension = "version"
applicationIdSuffix = ".benchmark"
versionNameSuffix = "-BENCHMARK"
}
}
// Built-in Tor (Arti) for the online flavors: TorManager, the JNI bridge and
// the prebuilt libamber_arti.so of every ABI split (built by tools/arti/build.sh).
sourceSets {
listOf("free", "benchmark").forEach { flavor ->
named(flavor) {
kotlin.directories.add("src/tor/java")
jniLibs.directories.add("src/tor/jniLibs")
}
}
}
splits {
abi {
isEnable = true
reset()
include("x86", "x86_64", "arm64-v8a", "armeabi-v7a")
isUniversalApk = true
}
}
buildFeatures {
compose = true
buildConfig = true
resValues = true
}
packaging {
resources {
excludes += "/META-INF/{AL2.0,LGPL2.1}"
excludes += "META-INF/versions/9/OSGI-INF/MANIFEST.MF"
}
jniLibs.useLegacyPackaging = true
// Already stripped by tools/arti/build.sh; ship it byte-identical to the
// committed file so it can be checked against a rebuild of tools/arti.
jniLibs.keepDebugSymbols += "**/libamber_arti.so"
}
}
// The benchmark flavor is built as a release APK, where the release build type's
// resValue sets app_name to "Amber". Build-type resValues take precedence over
// product-flavor resValues, so override app_name here via the variant API (the
// highest-priority tier) to give the side-by-side benchmark install its own
// launcher name.
androidComponents {
onVariants(selector().withFlavor("version" to "benchmark")) { variant ->
variant.resValues.put(
variant.makeResValueKey("string", "app_name"),
com.android.build.api.variant.ResValue("@string/app_name_benchmark"),
)
}
}
composeCompiler {
reportsDestination.set(layout.buildDirectory.dir("compose_compiler"))
}
ksp {
arg("room.schemaLocation", "$projectDir/schemas")
}
dependencies {
implementation(project(":common"))
implementation(libs.quartz) {
exclude(group = "net.java.dev.jna")
}
// Quartz ships jackson-databind but no longer the Kotlin module.
implementation(libs.jackson.module.kotlin)
implementation(libs.jna) {
artifact {
type = "aar"
}
}
implementation(libs.core.ktx)
implementation(libs.activity.compose)
implementation(libs.ui)
implementation(libs.ui.tooling.preview)
// Navigation
implementation(libs.navigation.compose)
implementation(libs.material3)
implementation(libs.material.icons.extended)
implementation(libs.appcompat)
implementation(libs.work.runtime.ktx)
implementation(libs.material3.window)
implementation(libs.paging.common)
implementation(libs.paging.compose)
implementation(libs.paging.runtime)
testImplementation(libs.junit)
testImplementation(libs.mockk)
testImplementation(libs.kotlinx.coroutines.test)
// JVM-side native secp256k1 so unit tests can exercise ECDH (NIP-44 v3).
testImplementation(libs.secp256k1.jni.jvm)
androidTestImplementation(libs.ext.junit)
androidTestImplementation(libs.espresso.core)
androidTestImplementation(libs.ui.test.junit4)
androidTestImplementation(libs.room.testing)
debugImplementation(libs.leakcanary)
debugImplementation(libs.ui.tooling)
debugImplementation(libs.ui.test.manifest)
implementation(libs.security.crypto.ktx)
// Lifecycle
implementation(libs.lifecycle.runtime.compose)
implementation(libs.lifecycle.viewmodel.compose)
implementation(libs.lifecycle.runtime.ktx)
// For QR generation
implementation(libs.core)
implementation(libs.zxing.android.embedded)
// Biometrics
implementation(libs.biometric.ktx)
ksp(libs.room.compiler)
implementation(libs.room.ktx)
implementation(libs.room.runtime)
implementation(libs.room.paging)
"freeImplementation"(libs.okhttp)
"freeImplementation"(libs.okhttpCoroutines)
// benchmark mirrors the `free` online network stack
"benchmarkImplementation"(libs.okhttp)
"benchmarkImplementation"(libs.okhttpCoroutines)
// Load images from the web.
implementation(libs.coil.compose)
// view GIFs
implementation(libs.coil.gif)
// view svgs
implementation(libs.coil.svg)
// enables network for coil
implementation(libs.coil.okhttp)
implementation(libs.storage)
implementation(libs.datastore.preferences)
implementation(libs.security.crypto)
implementation(libs.lifecycle.process)
implementation(libs.kotlinx.collections.immutable)
}