@file:Suppress("UnstableApiUsage") import java.util.regex.Pattern fun catalogLibraryIds(file: File): List { var insideLibraries = false val tomlString = "\"([^\"]+)\"" return file.readLines() .asSequence() .map { it.substringBefore("#").trim() } .onEach { line -> if (line.startsWith("[") && line.endsWith("]")) { insideLibraries = line == "[libraries]" } } .filter { insideLibraries && it.contains("=") && it.contains("{") } .mapNotNull { line -> val definition = line.substringAfter("{").substringBeforeLast("}") val module = Regex("""module\s*=\s*$tomlString""") .find(definition) ?.groupValues ?.get(1) if (module != null) { module } else { val group = Regex("""group\s*=\s*$tomlString""") .find(definition) ?.groupValues ?.get(1) val name = Regex("""name\s*=\s*$tomlString""") .find(definition) ?.groupValues ?.get(1) if (group != null && name != null) "$group:$name" else null } } .distinct() .toList() } fun catalogAllowlistPattern(libraryIds: List): Pattern { val allowedIds = libraryIds .flatMap { id -> val group = id.substringBefore(":") val name = id.substringAfter(":") if (group == "com.mikepenz" && name.startsWith("aboutlibraries-")) { listOf("$group:$name-android") } else { listOf( "$group:$name", "$group:$name-android", "$group:$name-jvm", "$group:$name-android-debug", "$group:$name-jvm-debug", ) } } .distinct() .joinToString("|") { Pattern.quote(it) } return Pattern.compile("^(?!(?:$allowedIds)$).*") } plugins { alias(libs.plugins.android.application) alias(libs.plugins.kotlin.compose) alias(libs.plugins.kotlin.serialization) alias(libs.plugins.aboutlibraries) } kotlin { jvmToolchain(21) compilerOptions { languageVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_4) apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_4) progressiveMode.set(true) freeCompilerArgs.addAll( "-Xreturn-value-checker=check" ) } } android { namespace = "com.example.research" compileSdk = project.property("compileSdk").toString().toInt() defaultConfig { applicationId = "com.example.research" minSdk = project.property("minSdk").toString().toInt() targetSdk = project.property("targetSdk").toString().toInt() versionCode = 1 versionName = "1.0" val isFdroid = project.hasProperty("fdroid") if (isFdroid) { applicationIdSuffix = ".fdroid" versionNameSuffix = "-fdroid" } vectorDrawables { useSupportLibrary = true } } buildTypes { debug { ndk { abiFilters.clear() abiFilters += listOf("arm64-v8a", "x86_64") } } release { ndk { abiFilters.clear() abiFilters += "arm64-v8a" } isMinifyEnabled = true isShrinkResources = true proguardFiles( getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro" ) } } compileOptions { sourceCompatibility = JavaVersion.VERSION_21 targetCompatibility = JavaVersion.VERSION_21 } buildFeatures { compose = true buildConfig = true } bundle { language { enableSplit = false } } androidResources { localeFilters += listOf("en", "ru") } } aboutLibraries { collect { fetchRemoteLicense = true fetchRemoteFunding = false configPath = file("config") } library { duplicationMode = com.mikepenz.aboutlibraries.plugin.DuplicateMode.MERGE duplicationRule = com.mikepenz.aboutlibraries.plugin.DuplicateRule.SIMPLE exclusionPatterns = listOf( catalogAllowlistPattern(catalogLibraryIds(rootProject.file("gradle/libs.versions.toml"))) ) } } dependencies { implementation(libs.androidx.core) implementation(libs.androidx.lifecycle.runtime.ktx) implementation(libs.androidx.lifecycle.runtime.compose) implementation(libs.androidx.activity.compose) implementation(libs.androidx.documentfile) val composeBom = platform(libs.androidx.compose.bom) implementation(composeBom) implementation(libs.bundles.compose) implementation(libs.androidx.compose.material3.adaptive.layout) debugImplementation(libs.androidx.compose.runtime.tracing) implementation(libs.androidx.paging.runtime) implementation(libs.androidx.paging.compose) implementation(libs.androidx.profileinstaller) debugImplementation(libs.androidx.compose.ui.tooling) implementation(libs.androidx.datastore.preferences) implementation(libs.okhttp) // Coroutines with Android-optimized dispatchers implementation(libs.kotlinx.coroutines.android) implementation(libs.kotlinx.serialization.json) }