diff --git a/Habitica/build.gradle b/Habitica/build.gradle deleted file mode 100644 index 33371003e..000000000 --- a/Habitica/build.gradle +++ /dev/null @@ -1,382 +0,0 @@ -plugins { - id 'com.android.application' - id 'org.jetbrains.kotlin.android' - id 'kotlin-kapt' - id 'dagger.hilt.android.plugin' - - id 'com.google.gms.google-services' - id 'com.google.firebase.crashlytics' - id 'androidx.navigation.safeargs' - id 'com.google.firebase.firebase-perf' - - id 'jacoco-report-aggregation' - id 'org.jetbrains.kotlin.plugin.compose' - id("kotlin-parcelize") -} - -apply plugin: 'kotlin-android' -apply plugin: "realm-android" - -repositories { - mavenLocal() - mavenCentral() - google() - - maven { url "https://jitpack.io" } -} - -dependencies { - implementation fileTree(include: ['*.jar'], dir: '../common/libs') - //Networking - implementation "com.squareup.okhttp3:okhttp:$okhttp_version" - implementation "com.squareup.okhttp3:logging-interceptor:$okhttp_version" - //REST API handling - implementation("com.squareup.retrofit2:retrofit:$retrofit_version") { - exclude module: 'okhttp' - } - implementation "com.squareup.retrofit2:converter-gson:$retrofit_version" - - //Dependency Injection - implementation "com.google.dagger:hilt-android:$daggerhilt_version" - kapt "com.google.dagger:hilt-compiler:$daggerhilt_version" - compileOnly 'javax.annotation:javax.annotation-api:1.3.2' - //App Compatibility and Material Design - implementation "androidx.appcompat:appcompat:$appcompat_version" - implementation 'com.google.android.material:material:1.12.0' - implementation "androidx.recyclerview:recyclerview:$recyclerview_version" - implementation "androidx.preference:preference-ktx:$preferences_version" - implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0" - - //Desugaring - coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.4' - - implementation('com.jaredrummler:android-device-names:2.1.1') - - // IAP Handling / Verification - implementation "com.android.billingclient:billing-ktx:7.0.0" - implementation 'fr.avianey.com.viewpagerindicator:library:2.4.1@aar' - - implementation("io.coil-kt:coil-compose:$coil_version") - - //Analytics - implementation "com.amplitude:analytics-android:$amplitude_version" - - //Tests - testImplementation 'androidx.test:core:1.6.1' - testImplementation "io.mockk:mockk:$mockk_version" - testImplementation "io.mockk:mockk-android:$mockk_version" - testImplementation "io.kotest:kotest-runner-junit5:$kotest_version" - testImplementation "io.kotest:kotest-assertions-core:$kotest_version" - testImplementation "io.kotest:kotest-framework-datatest:$kotest_version" - androidTestImplementation ('com.kaspersky.android-components:kaspresso:1.5.1') { - exclude module: "protobuf-lite" - } - androidTestImplementation "com.kaspersky.android-components:kaspresso-compose-support:1.5.1" - - androidTestImplementation 'androidx.test:runner:1.6.2' - androidTestImplementation 'androidx.test:rules:1.6.1' - debugImplementation 'androidx.fragment:fragment-testing:1.8.2' - androidTestImplementation 'androidx.test:core-ktx:1.6.1' - debugImplementation "androidx.test:monitor:1.7.2" - androidTestImplementation 'androidx.test.ext:junit-ktx:1.2.1' - androidTestImplementation "io.mockk:mockk-android:$mockk_version" - androidTestImplementation "io.mockk:mockk-agent:$mockk_version" - androidTestImplementation "io.kotest:kotest-assertions-core:$kotest_version" - androidTestImplementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version" - - androidTestUtil("androidx.test:orchestrator:1.5.0") - - implementation 'com.facebook.shimmer:shimmer:0.5.0' - - //Leak Detection - debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.10' - //Push Notifications - implementation platform("com.google.firebase:firebase-bom:$firebase_bom") - implementation 'com.google.firebase:firebase-analytics-ktx' - implementation 'com.google.firebase:firebase-crashlytics-ktx' - implementation 'com.google.firebase:firebase-messaging-ktx' - implementation 'com.google.firebase:firebase-config-ktx' - implementation 'com.google.firebase:firebase-perf-ktx' - implementation "com.google.android.gms:play-services-auth:$play_auth_version" - implementation 'com.google.android.flexbox:flexbox:3.0.0' - implementation "com.google.android.gms:play-services-wearable:$play_wearables_version" - - implementation "androidx.core:core-ktx:$core_ktx_version" - implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version" - implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version" - implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version" - implementation "androidx.navigation:navigation-fragment-ktx:$navigation_version" - implementation "androidx.navigation:navigation-ui-ktx:$navigation_version" - implementation "androidx.fragment:fragment-ktx:1.8.2" - implementation "androidx.paging:paging-runtime-ktx:$paging_version" - implementation "androidx.paging:paging-compose:$paging_version" - implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version" - implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version" - implementation "androidx.compose.material3:material3:1.2.1" - implementation "com.google.accompanist:accompanist-systemuicontroller:$accompanist_version" - - implementation 'com.google.android.play:review:2.0.1' - implementation 'com.google.android.play:review-ktx:2.0.1' - - implementation 'androidx.activity:activity-compose:1.9.1' - implementation "androidx.compose.runtime:runtime-livedata:$compose_version" - implementation "androidx.compose.animation:animation:$compose_version" - implementation "androidx.compose.ui:ui-text-google-fonts:$compose_version" - implementation "androidx.compose.ui:ui-tooling:$compose_version" - implementation "androidx.lifecycle:lifecycle-viewmodel-compose:$lifecycle_version" - - implementation project(':common') - implementation project(':shared') - - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" - - implementation 'com.gu.android:toolargetool:0.3.0' -} - -android { - compileSdk target_sdk - testOptions { - unitTests { - includeAndroidResources = true - } - animationsDisabled = true - } - - namespace "com.habitrpg.android.habitica" - - defaultConfig { - minSdkVersion min_sdk - compileSdk target_sdk - applicationId "com.habitrpg.android.habitica" - vectorDrawables.useSupportLibrary = true - buildConfigField "String", "STORE", "\"google\"" - buildConfigField "String", "TESTING_LEVEL", "\"production\"" - resourceConfigurations += ['en', 'bg', 'de', 'en-rGB', 'es', 'fr', 'hr-rHR', 'in', 'it', 'iw', 'ja', 'ko', 'lt', 'nl', 'pl', 'pt-rBR', 'pt-rPT', 'ru', 'tr', 'uk', 'zh', 'zh-rTW'] - - versionCode app_version_code - versionName app_version_name - - targetSdkVersion target_sdk - - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - testInstrumentationRunnerArguments clearPackageData: 'true' - - def formattedDate = new Date().format('yyMMdd') - archivesBaseName = "Habitica-${formattedDate}${versionCode}" - } - - buildFeatures { - viewBinding true - compose true - renderScript true - buildConfig = true - aidl true - } - - signingConfigs { - release - } - flavorDimensions.add("buildType") - - buildTypes { - debug { - //applicationIdSuffix ".debug" - debuggable true - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - // Disable fabric build ID generation for debug builds - ext.enableCrashlytics = false - ext.alwaysUpdateBuildId = false - //resValue "string", "content_provider", "com.habitrpg.android.habitica.debug.fileprovider" - resValue "string", "content_provider", "com.habitrpg.android.habitica.fileprovider" - resValue "string", "app_name", "Habitica Debug" - enableUnitTestCoverage false - enableAndroidTestCoverage false - } - debugIAP { - signingConfig signingConfigs.release - debuggable true - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - // Disable fabric build ID generation for debug builds - ext.enableCrashlytics = false - ext.alwaysUpdateBuildId = false - resValue "string", "content_provider", "com.habitrpg.android.habitica.fileprovider" - resValue "string", "app_name", "Habitica Debug" - } - release { - signingConfig signingConfigs.release - debuggable false - minifyEnabled true - shrinkResources true - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - resValue "string", "content_provider", "com.habitrpg.android.habitica.fileprovider" - resValue "string", "app_name", "Habitica" - } - } - - productFlavors { - dev { - dimension "buildType" - } - - staff { - dimension "buildType" - buildConfigField "String", "TESTING_LEVEL", "\"staff\"" - resValue "string", "app_name", "Habitica Staff" - versionCode app_version_code + 8 - } - - partners { - dimension "buildType" - buildConfigField "String", "TESTING_LEVEL", "\"partners\"" - resValue "string", "app_name", "Habitica" - versionCode app_version_code + 6 - } - - alpha { - dimension "buildType" - buildConfigField "String", "TESTING_LEVEL", "\"alpha\"" - resValue "string", "app_name", "Habitica Alpha" - versionCode app_version_code + 4 - } - - beta { - buildConfigField "String", "TESTING_LEVEL", "\"beta\"" - dimension "buildType" - versionCode app_version_code + 2 - } - - prod { - buildConfigField "String", "TESTING_LEVEL", "\"production\"" - dimension "buildType" - versionCode app_version_code - } - } - - sourceSets { - main { - manifest.srcFile 'AndroidManifest.xml' - java.srcDirs = ['src/main/java'] - resources.srcDirs = ['src/main/java'] - aidl.srcDirs = ['src/main/java'] - renderscript.srcDirs = ['src/main/java'] - res.srcDirs = ['res'] - assets.srcDirs = ['assets'] - } - test { - java.srcDir("src/test/java") - } - debugIAP { java.srcDirs = ['src/debug/java'] } - release { java.srcDirs = ['src/release/java'] } - } - - compileOptions { - coreLibraryDesugaringEnabled true - - sourceCompatibility JavaVersion.VERSION_11 - targetCompatibility JavaVersion.VERSION_11 - } - - kotlinOptions { - jvmTarget = JavaVersion.VERSION_11.toString() - } - - bundle { - language { - // Specifies that the app bundle should not support - // configuration APKs for language resources. These - // resources are instead packaged with each base and - // dynamic feature APK. - enableSplit = false - } - } - lint { - abortOnError false - disable 'MissingTranslation', 'InvalidPackage' - enable 'LogConditional', 'IconExpectedSize', 'MissingRegistered', 'TypographyQuotes' - } - - packagingOptions { - resources.excludes.add("META-INF/*") - } -} - -android.testOptions { - unitTests.all { - useJUnitPlatform() - } - unitTests.returnDefaultValues = true -} - -Properties props = new Properties() -def propFile = new File('signingrelease.properties') -if (propFile.canRead()) { - props.load(new FileInputStream(propFile)) - - if (props != null && props.containsKey('STORE_FILE') && props.containsKey('STORE_PASSWORD') && - props.containsKey('KEY_ALIAS') && props.containsKey('KEY_PASSWORD')) { - android.signingConfigs.release.storeFile = file(props['STORE_FILE']) - android.signingConfigs.release.storePassword = props['STORE_PASSWORD'] - android.signingConfigs.release.keyAlias = props['KEY_ALIAS'] - android.signingConfigs.release.keyPassword = props['KEY_PASSWORD'] - } else { - println 'signing.properties found but some entries are missing' - android.buildTypes.release.signingConfig = null - } -} else { - println 'signing.properties not found' - android.buildTypes.release.signingConfig = null -} - -// Add Habitica Properties to buildConfigField -final File HRPG_PROPS_FILE = new File(projectDir.absolutePath + '/../habitica.properties') -if (HRPG_PROPS_FILE.canRead()) { - Properties HRPG_PROPS = new Properties() - HRPG_PROPS.load(new FileInputStream(HRPG_PROPS_FILE)) - - if (HRPG_PROPS != null) { - android.buildTypes.configureEach { buildType -> - HRPG_PROPS.any { property -> - buildType.buildConfigField "String", property.key, "\"${property.value}\"" - } - } - } else { - throw new MissingResourceException('habitica.properties found but some entries are missing') - } -} else { - throw new MissingResourceException('habitica.properties not found') -} - -// Add Habitica Resources to resources -final File HRPG_RES_FILE = new File(projectDir.absolutePath + '/../habitica.resources') -if (HRPG_RES_FILE.canRead()) { - Properties HRPG_RES = new Properties() - HRPG_RES.load(new FileInputStream(HRPG_RES_FILE)) - - if (HRPG_RES != null) { - android.buildTypes.configureEach { buildType -> - HRPG_RES.any { property -> - buildType.resValue "string", property.key, "\"${property.value}\"" - } - } - } else { - throw new MissingResourceException('habitica.resources found but some entries are missing') - } -} else { - throw new MissingResourceException('habitica.resources not found') -} - -tasks.configureEach { task -> - if (task.name == "lint") { - task.enabled = false - } -} - -gradle.projectsEvaluated { - tasks.withType(JavaCompile).configureEach { - options.compilerArgs << "-Xmaxerrs" << "500" - } -} - -apply plugin: 'com.google.gms.google-services' diff --git a/Habitica/build.gradle.kts b/Habitica/build.gradle.kts new file mode 100644 index 000000000..418dcdb51 --- /dev/null +++ b/Habitica/build.gradle.kts @@ -0,0 +1,218 @@ +import com.android.build.gradle.internal.lint.AndroidLintTask + +plugins { + `jacoco-report-aggregation` + alias(libs.plugins.kotlin.android) + alias(libs.plugins.android.application) + alias(libs.plugins.hilt) + alias(libs.plugins.navigation) + alias(libs.plugins.ksp) + id("kotlin-parcelize") + id("kotlin-kapt") + alias(libs.plugins.kotlin.compose) + alias(libs.plugins.realm) + alias(libs.plugins.habitrpg.application) + alias(libs.plugins.habitrpg.convention) + alias(libs.plugins.crashlytics) + alias(libs.plugins.firebase.perf) + alias(libs.plugins.google.service) +} + +android { + compileSdk = libs.versions.targetSdk.get().toInt() + namespace = "com.habitrpg.android.habitica" + + defaultConfig { + applicationId = "com.habitrpg.android.habitica" + minSdk = libs.versions.minSdk.get().toInt() + compileSdk = libs.versions.targetSdk.get().toInt() + vectorDrawables.useSupportLibrary = true + + targetSdk = libs.versions.targetSdk.get().toInt() + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + testInstrumentationRunnerArguments["clearPackageData"] = "true" + resourceConfigurations.addAll( + listOf("en", "bg", "de", "en-rGB", "es", "fr", "hr-rHR", "in", "it", "iw", "ja", "ko", "lt", "nl", "pl", "pt-rBR", "pt-rPT", "ru", "tr", "uk", "zh", "zh-rTW") + ) + + buildConfigField("String", "STORE", "\"google\"") + buildConfigField("String", "TESTING_LEVEL", "\"production\"") + } + + buildFeatures { + viewBinding = true + compose = true + renderScript = true + buildConfig = true + aidl = true + } + + buildTypes { + debug { + // Keep it commented! + //applicationIdSuffix ".debug" + isDebuggable = true + isMinifyEnabled = false + proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") + // Disable fabric build ID generation for debug builds + ext["enableCrashlytics"] = false + ext["alwaysUpdateBuildId"] = false + enableUnitTestCoverage = false + resValue("string", "content_provider", "com.habitrpg.android.habitica.debug.fileprovider") + resValue("string", "content_provider", "com.habitrpg.android.habitica.fileprovider") + resValue("string", "app_name", "Habitica Debug") + } + create("debugIAP") { + signingConfigs.asMap["release"]?.let { releaseSigning -> signingConfig = releaseSigning } + isDebuggable = true + isMinifyEnabled = false + enableUnitTestCoverage = false + enableAndroidTestCoverage = false + proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") + // Disable fabric build ID generation for debug builds + ext["enableCrashlytics"] = false + ext["alwaysUpdateBuildId"] = false + resValue("string", "content_provider", "com.habitrpg.android.habitica.fileprovider") + resValue("string", "app_name", "Habitica Debug") + } + release { + signingConfigs.asMap["release"]?.let { releaseSigning -> signingConfig = releaseSigning } + isDebuggable = false + isMinifyEnabled = true + isShrinkResources = true + proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") + resValue("string", "content_provider", "com.habitrpg.android.habitica.fileprovider") + resValue("string", "app_name", "Habitica") + } + } + + sourceSets { + getByName("main") { + manifest.srcFile("AndroidManifest.xml") + java.srcDirs("src/main/java") + resources.srcDirs("src/main/java") + aidl.srcDirs("src/main/java") + renderscript.srcDirs("src/main/java") + res.srcDirs("res") + assets.srcDirs("assets") + } + getByName("test") { java.srcDir("src/test/java") } + getByName("debugIAP") { java.srcDirs("src/debug/java") } + getByName("release") { java.srcDirs("src/release/java") } + } + + compileOptions { + isCoreLibraryDesugaringEnabled = true + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + } + + testOptions { + unitTests { + isIncludeAndroidResources = true + isReturnDefaultValues = true + all { it.useJUnitPlatform() } + } + animationsDisabled = true + } + + lint { + abortOnError = false + disable.addAll(listOf("MissingTranslation", "InvalidPackage")) + enable.addAll(listOf("LogConditional", "IconExpectedSize", "MissingRegistered", "TypographyQuotes")) + } + + bundle.language.enableSplit = false + packaging.resources.excludes.add("META-INF/*") + kotlinOptions.jvmTarget = JavaVersion.VERSION_11.toString() +} + +tasks.withType { enabled = false } +tasks.withType { options.compilerArgs.addAll(listOf("-Xmaxerrs", "500")) } + +dependencies { + implementation(projects.common) + implementation(projects.shared) + + implementation(fileTree("../common/libs") { include("*.jar") }) + + //Networking + implementation(libs.bundles.okhttp) + + //REST API handling + implementation(libs.retrofit) { exclude(module = libs.okhttp.asProvider().get().group) } + implementation(libs.retrofit.converter.gson) + + //Dependency Injection + implementation(libs.hilt.android) + ksp(libs.hilt.compiler) + compileOnly(libs.javax.annotation) + + //App Compatibility and Material Design + implementation(libs.bundles.design) + + //Desugaring + coreLibraryDesugaring(libs.desugar) + + implementation(libs.device.names) + + // IAP Handling / Verification + implementation(libs.billing) + implementation(libs.viewPagerIndicator) { exclude(group = "com.google.android") } + + implementation(libs.coil.compose) + + //Analytics + implementation(libs.amplitude.analytic) + + //Tests + testImplementation(libs.bundles.test.implementation) + + androidTestImplementation(libs.bundles.android.test.implementation) + androidTestImplementation(libs.kaspresso) { exclude(module = "protobuf-lite") } + + debugImplementation(libs.test.fragment) + debugImplementation(libs.test.monitor) + + androidTestUtil(libs.test.orchestrator) + + implementation(libs.shimmer) + + //Leak Detection + debugImplementation(libs.leakcanary) + + // Google Services + implementation(platform(libs.firebase.bom)) + implementation(libs.bundles.google.services) + + implementation(libs.flexbox) + + implementation(libs.core) + implementation(libs.core.ktx) + implementation(libs.lifecycle.viewmodel) + implementation(libs.lifecycle.livedata) + implementation(libs.lifecycle.common) + implementation(libs.navigation.fragment) + implementation(libs.navigation.ui) + implementation(libs.fragment.ktx) + implementation(libs.paging) + implementation(libs.paging.compose) + implementation(libs.kotlinx.coroutine) + implementation(libs.coroutine.android) + implementation(libs.material3) + implementation(libs.accompanist.sysmtemUi) + + implementation(libs.google.play.review) + implementation(libs.google.play.review.ktx) + + implementation(libs.activity.compose) + implementation(libs.runtime.livedata) + implementation(libs.compose.animation) + implementation(libs.text.google.fonts) + implementation(libs.ui.tooling) + implementation(libs.viewmodel.compose) + + implementation(libs.kotlin.jdk7) + + implementation(libs.toolargetool) +} \ No newline at end of file diff --git a/Habitica/habitica-flavor.json b/Habitica/habitica-flavor.json new file mode 100644 index 000000000..a0d99fee9 --- /dev/null +++ b/Habitica/habitica-flavor.json @@ -0,0 +1,36 @@ +{ + "dimension": "buildType", + "flavors": [ + { + "name": "dev" + }, + { + "name": "staff", + "testingLevel": "\"staff\"", + "appName": "Habitica Staff", + "versionCodeIncrement": 8 + }, + { + "name": "partners", + "testingLevel": "\"partners\"", + "appName": "Habitica", + "versionCodeIncrement": 6 + }, + { + "name": "alpha", + "testingLevel": "\"alpha\"", + "appName": "Habitica Alpha", + "versionCodeIncrement": 4 + }, + { + "name": "beta", + "testingLevel": "\"beta\"", + "versionCodeIncrement": 2 + }, + { + "name": "prod", + "testingLevel": "\"production\"", + "versionCodeIncrement": 0 + } + ] +} \ No newline at end of file diff --git a/build-logic/convention/.gitignore b/build-logic/convention/.gitignore new file mode 100644 index 000000000..42afabfd2 --- /dev/null +++ b/build-logic/convention/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/build-logic/convention/build.gradle.kts b/build-logic/convention/build.gradle.kts new file mode 100644 index 000000000..cef485cc6 --- /dev/null +++ b/build-logic/convention/build.gradle.kts @@ -0,0 +1,38 @@ +import org.gradle.api.JavaVersion.VERSION_11 +import org.jetbrains.kotlin.gradle.dsl.JvmTarget + +plugins { + `kotlin-dsl` +} + +group = "com.habitrpg.buildlogic" +version = "0.1.0" + +java { + sourceCompatibility = VERSION_11 + targetCompatibility = VERSION_11 +} + +kotlin.compilerOptions.jvmTarget = JvmTarget.JVM_11 + +dependencies { + implementation(libs.android.gradlePlugin) + implementation(libs.detekt.gradlePlugin) + implementation(libs.gson) + implementation(libs.ktlint.gradlePlugin) +} + +gradlePlugin { + plugins { + register("conventionPlugin") { + id = "com.habitrpg.buildlogic.convention" + version = project.version + implementationClass = "com.habitrpg.buildlogic.plugin.ConventionPlugin" + } + register("applicationPlugin") { + id = "com.habitrpg.buildlogic.application" + version = project.version + implementationClass = "com.habitrpg.buildlogic.plugin.ApplicationPlugin" + } + } +} \ No newline at end of file diff --git a/build-logic/convention/src/main/kotlin/com/habitrpg/buildlogic/model/Flavor.kt b/build-logic/convention/src/main/kotlin/com/habitrpg/buildlogic/model/Flavor.kt new file mode 100644 index 000000000..b0328169e --- /dev/null +++ b/build-logic/convention/src/main/kotlin/com/habitrpg/buildlogic/model/Flavor.kt @@ -0,0 +1,10 @@ +package com.habitrpg.buildlogic.model + +import com.google.gson.annotations.SerializedName + +data class Flavor( + @SerializedName("testingLevel") val testingLevel: String?, + @SerializedName("appName") val appName: String?, + @SerializedName("name") val name: String, + @SerializedName("versionCodeIncrement") val versionCodeIncrement: Int? +) diff --git a/build-logic/convention/src/main/kotlin/com/habitrpg/buildlogic/model/HabiticaFlavor.kt b/build-logic/convention/src/main/kotlin/com/habitrpg/buildlogic/model/HabiticaFlavor.kt new file mode 100644 index 000000000..0ea2be140 --- /dev/null +++ b/build-logic/convention/src/main/kotlin/com/habitrpg/buildlogic/model/HabiticaFlavor.kt @@ -0,0 +1,8 @@ +package com.habitrpg.buildlogic.model + +import com.google.gson.annotations.SerializedName + +data class HabiticaFlavor( + @SerializedName("dimension") val dimension: String, + @SerializedName("flavors") val flavors: List +) diff --git a/build-logic/convention/src/main/kotlin/com/habitrpg/buildlogic/plugin/ApplicationPlugin.kt b/build-logic/convention/src/main/kotlin/com/habitrpg/buildlogic/plugin/ApplicationPlugin.kt new file mode 100644 index 000000000..35d29aff3 --- /dev/null +++ b/build-logic/convention/src/main/kotlin/com/habitrpg/buildlogic/plugin/ApplicationPlugin.kt @@ -0,0 +1,68 @@ +package com.habitrpg.buildlogic.plugin + +import com.android.build.gradle.AppExtension +import com.google.gson.Gson +import com.habitrpg.buildlogic.model.HabiticaFlavor +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.kotlin.dsl.getByType +import java.io.File +import java.io.FileInputStream +import java.io.FileReader +import java.util.Properties + +class ApplicationPlugin : Plugin { + override fun apply(target: Project): Unit = with(target) { + pluginManager.withPlugin("com.android.application") { + val signingProps = try { + Properties().apply { load(FileInputStream(File("signingrelease.properties"))) } + } catch (t: Throwable) { + Properties() + } + val signingPropsAvailable = signingProps.containsKey("STORE_FILE") && signingProps.containsKey("STORE_PASSWORD") && + signingProps.containsKey("KEY_ALIAS") && signingProps.containsKey("KEY_PASSWORD") + + val versionProps = try { + Properties().apply { load(FileInputStream(File("version.properties"))) } + } catch (t: Throwable) { + Properties() + } + val versionPropsAvailable = versionProps.containsKey("NAME") && versionProps.containsKey("CODE") + val currentVersionCode = (versionProps["CODE"] ?: "0").toString().toInt() + + val habiticaFlavor = Gson().fromJson(FileReader(file("habitica-flavor.json")), HabiticaFlavor::class.java) + + extensions.getByType().apply { + defaultConfig { + versionName = versionProps["NAME"].toString() + versionCode = currentVersionCode + + val habiticaRes = Properties().apply { load(FileInputStream(File(projectDir.absolutePath + "/../habitica.resources"))) } + habiticaRes.forEach { key, value -> resValue("string", key.toString(), "\"${value}\"") } + val hrpgProps = Properties().apply { load(FileInputStream(File(projectDir.absolutePath + "/../habitica.properties"))) } + hrpgProps.forEach { key, value -> buildConfigField("String", key as String, "\"${value}\"") } + } + + if (signingPropsAvailable && versionPropsAvailable) signingConfigs.register("release") { + storeFile = file(signingProps["STORE_FILE"].toString()) + storePassword = signingProps["STORE_PASSWORD"].toString() + keyAlias = signingProps["KEY_ALIAS"].toString() + keyPassword = signingProps["KEY_PASSWORD"].toString() + } + + flavorDimensions(habiticaFlavor.dimension) + + productFlavors { + habiticaFlavor.flavors.forEach { flavor -> + register(flavor.name) { + dimension = habiticaFlavor.dimension + versionCode = currentVersionCode + (flavor.versionCodeIncrement ?: 0) + if (flavor.testingLevel != null) buildConfigField("String", "TESTING_LEVEL", flavor.testingLevel) + if (flavor.appName != null) resValue("string", "app_name", flavor.appName) + } + } + } + } + } + } +} \ No newline at end of file diff --git a/build-logic/convention/src/main/kotlin/com/habitrpg/buildlogic/plugin/ConventionPlugin.kt b/build-logic/convention/src/main/kotlin/com/habitrpg/buildlogic/plugin/ConventionPlugin.kt new file mode 100644 index 000000000..bee2f748d --- /dev/null +++ b/build-logic/convention/src/main/kotlin/com/habitrpg/buildlogic/plugin/ConventionPlugin.kt @@ -0,0 +1,77 @@ +package com.habitrpg.buildlogic.plugin + +import io.gitlab.arturbosch.detekt.Detekt +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.api.tasks.testing.Test +import org.gradle.api.tasks.testing.TestDescriptor +import org.gradle.api.tasks.testing.TestResult +import org.gradle.api.tasks.testing.logging.TestLogEvent.FAILED +import org.gradle.api.tasks.testing.logging.TestLogEvent.PASSED +import org.gradle.api.tasks.testing.logging.TestLogEvent.SKIPPED +import org.gradle.api.tasks.testing.logging.TestLogEvent.STANDARD_ERROR +import org.gradle.kotlin.dsl.KotlinClosure2 +import org.gradle.kotlin.dsl.assign +import org.gradle.kotlin.dsl.configure +import org.gradle.kotlin.dsl.withType +import org.jlleitschuh.gradle.ktlint.KtlintExtension + +class ConventionPlugin : Plugin { + override fun apply(target: Project): Unit = with(target) { + + with(pluginManager) { + apply("io.gitlab.arturbosch.detekt") + apply("org.jlleitschuh.gradle.ktlint") + } + + configure { + filter { + exclude { entry -> entry.file.toString().contains("generated") } + } + } + + tasks.withType { + source = fileTree("$projectDir/src/main/java") + config = files("${rootProject.rootDir}/detekt.yml") + baseline = file("${rootProject.projectDir}/detekt_baseline.xml") + reports { + xml.required.set(false) + html.required.set(true) + html.outputLocation.set(layout.buildDirectory.file("reports/detekt.html")) + txt.required.set(false) + sarif.required.set(true) + sarif.outputLocation.set(layout.buildDirectory.file("reports/detekt.sarif")) + } + } + + tasks.withType { + outputs.upToDateWhen { false } + testLogging { + showStandardStreams = true + events.addAll(listOf(PASSED, SKIPPED, FAILED, STANDARD_ERROR)) + } + afterSuite(KotlinClosure2({ desc, result -> + if (desc.parent == null) { // will match the outermost suite + val output = buildString { + append("Results: ${result.resultType} ") + append("(${result.testCount} tests, ") + append("${result.successfulTestCount} passed, ") + append("${result.failedTestCount} failed, ") + append("${result.skippedTestCount} skipped)") + } + val startItem = "| " + val endItem = " |" + val repeatLength = startItem.length + output.length + endItem.length + println(buildString { + append("\n") + repeat(repeatLength) { append("—") } + append("\n") + append(startItem + output + endItem) + append("\n") + repeat(repeatLength) { append("—") } + }) + } + })) + } + } +} \ No newline at end of file diff --git a/build-logic/gradle.properties b/build-logic/gradle.properties new file mode 100644 index 000000000..1c9073eb9 --- /dev/null +++ b/build-logic/gradle.properties @@ -0,0 +1,4 @@ +# Gradle properties are not passed to included builds https://github.com/gradle/gradle/issues/2534 +org.gradle.parallel=true +org.gradle.caching=true +org.gradle.configureondemand=true diff --git a/build-logic/settings.gradle.kts b/build-logic/settings.gradle.kts new file mode 100644 index 000000000..63b3f528b --- /dev/null +++ b/build-logic/settings.gradle.kts @@ -0,0 +1,19 @@ +dependencyResolutionManagement { + repositories { + gradlePluginPortal() + google { + content { + includeGroupByRegex("com\\.android.*") + includeGroupByRegex("com\\.google.*") + includeGroupByRegex("androidx.*") + } + } + mavenCentral() + maven("https://jitpack.io") + mavenLocal() + } + versionCatalogs.create("libs").from(files("../gradle/libs.versions.toml")) +} + +rootProject.name = "build-logic" +include(":convention") \ No newline at end of file diff --git a/build.gradle b/build.gradle deleted file mode 100644 index 3e9af528f..000000000 --- a/build.gradle +++ /dev/null @@ -1,138 +0,0 @@ -import org.jetbrains.kotlin.gradle.tasks.KotlinCompile - -// Top-level build file where you can add configuration options common to all sub-projects/modules. - -buildscript { - ext { - min_sdk = 21 - target_sdk = 34 - wearos_target_sdk = 33 - app_version_name = '' - app_version_code = 0 - - accompanist_version = '0.30.0' - amplitude_version = '1.6.1' - appcompat_version = '1.7.0' - coil_version = '2.4.0' - compose_version = '1.6.8' - compose_compiler = '1.5.14' - core_ktx_version = '1.13.1' - coroutines_version = '1.8.0' - daggerhilt_version = '2.51.1' - firebase_bom = '31.3.0' - kotest_version = '5.6.2' - kotlin_version = '2.0.20' - ktlint_version = '1.2.1' - lifecycle_version = '2.8.4' - markwon_version = '4.6.2' - mockk_version = '1.13.4' - moshi_version = '1.15.0' - navigation_version = '2.7.7' - okhttp_version = '4.12.0' - paging_version = '3.3.0' - play_wearables_version = '18.2.0' - play_auth_version = '21.2.0' - preferences_version = '1.2.1' - realm_version = '1.9.1' - retrofit_version = '2.9.0' - recyclerview_version = '1.3.2' - } - - repositories { - google() - maven { url "https://plugins.gradle.org/m2/" } - mavenCentral() - } - dependencies { - classpath 'com.android.tools.build:gradle:8.7.2' - classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' - classpath 'com.google.gms:google-services:4.4.2' - classpath 'com.google.firebase:firebase-crashlytics-gradle:3.0.2' - classpath "io.realm:realm-gradle-plugin:10.19.0" - classpath("io.realm.kotlin:gradle-plugin:$realm_version") - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - classpath "io.gitlab.arturbosch.detekt:detekt-gradle-plugin:1.19.0" - classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$navigation_version" - classpath 'com.google.firebase:perf-plugin:1.4.2' - classpath "com.google.dagger:hilt-android-gradle-plugin:$daggerhilt_version" - classpath "org.jlleitschuh.gradle:ktlint-gradle:11.3.1" - classpath "org.jetbrains.kotlin:compose-compiler-gradle-plugin:$kotlin_version" - } -} - -apply plugin: 'io.gitlab.arturbosch.detekt' - -allprojects { - apply plugin: "org.jlleitschuh.gradle.ktlint" - repositories { - google() - mavenCentral() - } - - tasks.withType(Test).configureEach { - testLogging { - events "passed", "skipped", "failed", "standardError" - outputs.upToDateWhen {false} - - afterSuite { desc, result -> - if (!desc.parent) { // will match the outermost suite - def output = "Results: ${result.resultType} (${result.testCount} tests, ${result.successfulTestCount} passed, ${result.failedTestCount} failed, ${result.skippedTestCount} skipped)" - def startItem = '| ', endItem = ' |' - def repeatLength = startItem.length() + output.length() + endItem.length() - println('\n' + ('-' * repeatLength) + '\n' + startItem + output + endItem + '\n' + ('-' * repeatLength)) - } - } - } - } -} - -Properties props = new Properties() -def propFile = new File('version.properties') -if (propFile.canRead()) { - props.load(new FileInputStream(propFile)) - - if (props != null && props.containsKey('NAME') && props.containsKey('CODE') ) { - ext.app_version_name = props['NAME'] - ext.app_version_code = props['CODE'] as Integer - } else { - println 'signing.properties found but some entries are missing' - android.buildTypes.release.signingConfig = null - } -} else { - println 'signing.properties not found' -} - -detekt { - source = files("Habitica/src/main/java") - config = files("detekt.yml") - baseline = file("${rootProject.projectDir}/detekt_baseline.xml") -} - -ktlint { - filter { - exclude { entry -> - entry.file.toString().contains("generated") - } - } -} - -tasks.named("detekt").configure { - reports { - xml.required.set(false) - html.required.set(true) - html.outputLocation.set(file("build/reports/detekt.html")) - txt.required.set(false) - sarif.required.set(true) - sarif.outputLocation.set(file("build/reports/detekt.sarif")) - } -} - -task allUnitTests(type: GradleBuild) { - tasks = [':Habitica:testProdDebugUnitTest', ':wearos:testProdDebugUnitTest', ':common:testProdDebugUnitTest'] -} - -subprojects { - tasks.withType(KotlinCompile).configureEach { - kotlinOptions.jvmTarget = "11" - } -} diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 000000000..9bb19fc05 --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,23 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. +plugins { + alias(libs.plugins.android.application) apply false + alias(libs.plugins.android.library) apply false + alias(libs.plugins.crashlytics) apply false + alias(libs.plugins.detekt) apply false + alias(libs.plugins.firebase.perf) apply false + alias(libs.plugins.google.service) apply false + alias(libs.plugins.hilt) apply false + alias(libs.plugins.kotest) apply false + alias(libs.plugins.kotlin.android) apply false + alias(libs.plugins.kotlin.compose) apply false + alias(libs.plugins.ksp) apply false + alias(libs.plugins.ktlint) apply false + alias(libs.plugins.navigation) apply false + alias(libs.plugins.realm) apply false + alias(libs.plugins.habitrpg.application) apply false + alias(libs.plugins.habitrpg.convention) apply false +} + +tasks.register("allUnitTests", DefaultTask::class) { + dependsOn(":Habitica:testProdDebugUnitTest", ":wearos:testProdDebugUnitTest", ":common:testProdDebugUnitTest") +} \ No newline at end of file diff --git a/common/build.gradle.kts b/common/build.gradle.kts index 7fc6589ab..ac07f72ad 100644 --- a/common/build.gradle.kts +++ b/common/build.gradle.kts @@ -1,30 +1,24 @@ -@file:Suppress("PropertyName") - import java.io.FileInputStream import java.util.Properties plugins { - id("com.android.library") - id("org.jetbrains.kotlin.android") - id("org.jetbrains.kotlin.plugin.compose") + alias(libs.plugins.kotlin.android) + alias(libs.plugins.habitrpg.convention) + alias(libs.plugins.android.library) + alias(libs.plugins.kotlin.compose) } -val rootExtra = rootProject.extra - android { - compileSdk = rootExtra.get("target_sdk") as Int + namespace = "com.habitrpg.common.habitica" + compileSdk = libs.versions.targetSdk.get().toInt() defaultConfig { - minSdk = rootExtra.get("min_sdk") as Int - + minSdk = libs.versions.minSdk.get().toInt() testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" consumerProguardFiles("consumer-rules.pro") - } - testOptions { - unitTests { - } - animationsDisabled = true + val hrpgProps = Properties().apply { load(FileInputStream(File(projectDir.absolutePath + "/../habitica.properties"))) } + hrpgProps.forEach { key, value -> buildConfigField("String", key as String, "\"${value}\"") } } buildTypes { @@ -44,8 +38,12 @@ android { buildConfig = true } - composeOptions { - kotlinCompilerExtensionVersion = rootProject.extra.get("compose_compiler") as String + testOptions { + unitTests { + isIncludeAndroidResources = true + all { it.useJUnitPlatform() } + } + animationsDisabled = true } compileOptions { @@ -53,13 +51,6 @@ android { targetCompatibility = JavaVersion.VERSION_11 } - kotlin { - jvmToolchain(11) - } - namespace = "com.habitrpg.common.habitica" - - flavorDimensions.add("buildType") - productFlavors { register("dev") { dimension = "buildType" @@ -90,85 +81,42 @@ android { buildConfigField("String", "TESTING_LEVEL", "\"production\"") } } -} -val core_ktx_version: String by rootExtra -val accompanist_version: String by rootExtra -val appcompat_version: String by rootExtra -val compose_version: String by rootExtra -val markwon_version: String by rootExtra -val coil_version: String by rootExtra -val mockk_version: String by rootExtra -val kotest_version: String by rootExtra -val kotlin_version: String by rootExtra -val navigation_version: String by rootExtra + kotlin.jvmToolchain(11) + composeOptions.kotlinCompilerExtensionVersion = libs.versions.compose.compiler.get() + kotlinOptions.jvmTarget = JavaVersion.VERSION_11.toString() + flavorDimensions.add("buildType") +} dependencies { + implementation(projects.shared) + implementation(fileTree(mapOf("include" to listOf("*.jar"), "dir" to "libs"))) - implementation("androidx.core:core-ktx:$core_ktx_version") - implementation("androidx.appcompat:appcompat:$appcompat_version") + implementation(libs.core) + implementation(libs.core.ktx) + implementation(libs.appcompat) // Markdown - implementation("io.noties.markwon:core:$markwon_version") - implementation("io.noties.markwon:ext-strikethrough:$markwon_version") - implementation("io.noties.markwon:image:$markwon_version") - implementation("io.noties.markwon:recycler:$markwon_version") - implementation("io.noties.markwon:linkify:$markwon_version") + implementation(libs.bundles.markwon) // Image Management Library - implementation("io.coil-kt:coil:$coil_version") - implementation("io.coil-kt:coil-gif:$coil_version") - implementation("androidx.recyclerview:recyclerview:1.3.2") - implementation("androidx.navigation:navigation-common-ktx:$navigation_version") - implementation("androidx.navigation:navigation-runtime-ktx:$navigation_version") - implementation("com.google.android.material:material:1.12.0") + implementation(libs.coil) + implementation(libs.coil.gif) - testImplementation("io.mockk:mockk:$mockk_version") - testImplementation("io.mockk:mockk-android:$mockk_version") - testImplementation("io.kotest:kotest-runner-junit5:$kotest_version") - testImplementation("io.kotest:kotest-assertions-core:$kotest_version") - testImplementation("io.kotest:kotest-framework-datatest:$kotest_version") - testImplementation("org.jetbrains.kotlin:kotlin-reflect:$kotlin_version") + implementation(libs.navigation.common) + implementation(libs.navigation.runtime) + implementation(libs.recyclerview) + implementation(libs.material) - androidTestImplementation("androidx.test.ext:junit:1.2.1") - androidTestImplementation("androidx.test.espresso:espresso-core:3.6.1") - androidTestImplementation("org.jetbrains.kotlin:kotlin-reflect:$kotlin_version") + testImplementation(libs.bundles.test.implementation) + androidTestImplementation(libs.bundles.android.test.implementation) - implementation("androidx.activity:activity-compose:1.9.1") - implementation("androidx.compose.runtime:runtime-livedata:$compose_version") - implementation("androidx.compose.animation:animation:$compose_version") - implementation("androidx.compose.ui:ui-text-google-fonts:$compose_version") - implementation("androidx.compose.ui:ui-tooling:$compose_version") - implementation("androidx.compose.material3:material3:1.2.1") - implementation("com.google.accompanist:accompanist-themeadapter-material3:$accompanist_version") - - implementation(project(":shared")) -} - -android.testOptions { - unitTests.all { - it.useJUnitPlatform() - } -} - -tasks.withType { - this.testLogging { - this.showStandardStreams = true - } -} - -// Add Habitica Properties to buildConfigField -val HRPG_PROPS_FILE = File(projectDir.absolutePath + "/../habitica.properties") -if (HRPG_PROPS_FILE.canRead()) { - val hrpgProps = Properties() - hrpgProps.load(FileInputStream(HRPG_PROPS_FILE)) - - android.buildTypes.configureEach { - hrpgProps.forEach { property -> - buildConfigField("String", property.key as String, "\"${property.value}\"") - } - } -} else { - throw MissingResourceException("habitica.properties not found") -} + implementation(libs.activity.compose) + implementation(libs.runtime.livedata) + implementation(libs.compose.animation) + implementation(libs.text.google.fonts) + implementation(libs.ui.tooling) + implementation(libs.material3) + implementation(libs.accompanist.theme) +} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 404e79491..3525d00e6 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,3 +10,5 @@ kotlin.mpp.androidSourceSetLayoutVersion=2 android.nonTransitiveRClass=false android.nonFinalResIds=false android.enableR8.fullMode=false +org.gradle.caching=true +org.gradle.parallel=true \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml new file mode 100644 index 000000000..e4b709262 --- /dev/null +++ b/gradle/libs.versions.toml @@ -0,0 +1,221 @@ +[versions] +accompanist = "0.30.0" +agp = "8.5.2" +amplitude = "1.6.1" +androidTest = "1.6.1" +androidTestRunner = "1.6.2" +annotationApi = "1.3.2" +appcompat = "1.7.0" +billing = "7.0.0" +coil = "2.4.0" +compose = "1.6.8" +composeActivity = "1.9.1" +compose_compiler = "1.5.14" +constraintlayout = "2.2.0" +converterMoshi = "2.9.0" +coordinatorlayout = "1.2.0" +coreSplashscreen = "1.1.0-rc01" +core_ktx = "1.13.0" +coroutines = "1.8.0" +crashlytics = "3.0.2" +daggerhilt = "2.51.1" +desuggar = "2.0.4" +detekt = "1.19.0" +deviceNames = "2.1.1" +firebase-perf = "1.4.2" +firebase_bom = "31.3.0" +flexbox = "3.0.0" +fragmentKtx = "1.8.2" +fragmentTesting = "1.8.2" +google-service = "4.4.2" +gson = "2.11.0" +habitRpgPlugin = "0.1.0" +inAppReview = "2.0.1" +junitKtx = "1.2.1" +kaspresso = "1.5.1" +kotest = "5.6.2" +kotlin = "2.0.20" +ksp = "2.0.20-1.0.25" +ktlint = "1.2.1" +ktlintPlugin = "11.3.1" +leakCanary = "2.10" +lifecycle = "2.8.4" +lifecycleRuntimeKtx = "2.8.4" +markwon = "4.6.2" +material = "1.12.0" +material3 = "1.2.1" +minSdk = "26" +mockk = "1.13.4" +moshi = "1.15.0" +moshiKotlin = "1.15.0" +navigation = "2.7.7" +okhttp = "4.12.0" +orchestrator = "1.5.0" +pagerIndicator = "2.4.1" +paging = "3.3.0" +play_auth = "21.2.0" +play_wearables = "18.2.0" +preferences = "1.2.1" +realm = "1.9.1" +realmPlugin = "10.19.0" +recyclerview = "1.3.2" +retrofit = "2.9.0" +shimmer = "0.5.0" +swipeRefresh = "1.1.0" +targetSdk = "34" +tooLargeTool = "0.3.0" +turbine = "0.12.1" +wear = "1.3.0" +wearInput = "1.1.0" +wearOsTargetSdk = "33" + +[libraries] +accompanist-sysmtemUi = { group = "com.google.accompanist", name = "accompanist-systemuicontroller", version.ref = "accompanist" } +accompanist-theme = { group = "com.google.accompanist", name = "accompanist-themeadapter-material3", version.ref = "accompanist" } +activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "composeActivity" } +amplitude-analytic = { group = "com.amplitude", name = "analytics-android", version.ref = "amplitude" } +appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" } +billing = { group = "com.android.billingclient", name = "billing-ktx", version.ref = "billing" } +coil = { group = "io.coil-kt", name = "coil", version.ref = "coil" } +coil-compose = { group = "io.coil-kt", name = "coil-compose", version.ref = "coil" } +coil-gif = { group = "io.coil-kt", name = "coil-gif", version.ref = "coil" } +compose-animation = { group = "androidx.compose.animation", name = "animation", version.ref = "compose" } +constraintlayout = { module = "androidx.constraintlayout:constraintlayout", version.ref = "constraintlayout" } +coordinatorlayout = { module = "androidx.coordinatorlayout:coordinatorlayout", version.ref = "coordinatorlayout" } +core = { group = "androidx.core", name = "core", version.ref = "core_ktx" } +core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "core_ktx" } +core-splashscreen = { module = "androidx.core:core-splashscreen", version.ref = "coreSplashscreen" } +coroutine-android = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-android", version.ref = "coroutines" } +desugar = { group = "com.android.tools", name = "desugar_jdk_libs", version.ref = "desuggar" } +device-names = { group = "com.jaredrummler", name = "android-device-names", version.ref = "deviceNames" } +firebase-analytic = { group = "com.google.firebase", name = "firebase-analytics-ktx" } +firebase-bom = { group = "com.google.firebase", name = "firebase-bom", version.ref = "firebase_bom" } +firebase-config = { group = "com.google.firebase", name = "firebase-config-ktx" } +firebase-crashlytics = { group = "com.google.firebase", name = "firebase-crashlytics-ktx" } +firebase-messaging = { group = "com.google.firebase", name = "firebase-messaging-ktx" } +firebase-perf = { group = "com.google.firebase", name = "firebase-perf-ktx" } +flexbox = { group = "com.google.android.flexbox", name = "flexbox", version.ref = "flexbox" } +fragment-ktx = { group = "androidx.fragment", name = "fragment-ktx", version.ref = "fragmentKtx" } +google-play-auth = { group = "com.google.android.gms", name = "play-services-auth", version.ref = "play_auth" } +google-play-review = { group = "com.google.android.play", name = "review", version.ref = "inAppReview" } +google-play-review-ktx = { group = "com.google.android.play", name = "review-ktx", version.ref = "inAppReview" } +google-play-wearable = { group = "com.google.android.gms", name = "play-services-wearable", version.ref = "play_wearables" } +hilt-android = { group = "com.google.dagger", name = "hilt-android", version.ref = "daggerhilt" } +hilt-compiler = { group = "com.google.dagger", name = "hilt-compiler", version.ref = "daggerhilt" } +javax-annotation = { group = "javax.annotation", name = "javax.annotation-api", version.ref = "annotationApi" } +kaspresso = { group = "com.kaspersky.android-components", name = "kaspresso", version.ref = "kaspresso" } +kaspresso-compose = { group = "com.kaspersky.android-components", name = "kaspresso-compose-support", version.ref = "kaspresso" } +kotest-assertions = { group = "io.kotest", name = "kotest-assertions-core", version.ref = "kotest" } +kotest-framework = { group = "io.kotest", name = "kotest-framework-datatest", version.ref = "kotest" } +kotest-runner = { group = "io.kotest", name = "kotest-runner-junit5", version.ref = "kotest" } +kotlin-jdk7 = { group = "org.jetbrains.kotlin", name = "kotlin-stdlib-jdk7", version.ref = "kotlin" } +kotlin-reflect = { group = "org.jetbrains.kotlin", name = "kotlin-reflect", version.ref = "kotlin" } +kotlinx-coroutine = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-core", version.ref = "coroutines" } +leakcanary = { group = "com.squareup.leakcanary", name = "leakcanary-android", version.ref = "leakCanary" } +lifecycle-common = { group = "androidx.lifecycle", name = "lifecycle-common-java8", version.ref = "lifecycle" } +lifecycle-livedata = { group = "androidx.lifecycle", name = "lifecycle-livedata-ktx", version.ref = "lifecycle" } +lifecycle-runtime-ktx = { module = "androidx.lifecycle:lifecycle-runtime-ktx", version.ref = "lifecycleRuntimeKtx" } +lifecycle-viewmodel = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-ktx", version.ref = "lifecycle" } +markwon-core = { group = "io.noties.markwon", name = "core", version.ref = "markwon" } +markwon-ext = { group = "io.noties.markwon", name = "ext-strikethrough", version.ref = "markwon" } +markwon-image = { group = "io.noties.markwon", name = "image", version.ref = "markwon" } +markwon-linkify = { group = "io.noties.markwon", name = "linkify", version.ref = "markwon" } +markwon-recycler = { group = "io.noties.markwon", name = "recycler", version.ref = "markwon" } +material = { group = "com.google.android.material", name = "material", version.ref = "material" } +material3 = { group = "androidx.compose.material3", name = "material3", version.ref = "material3" } +mockk = { group = "io.mockk", name = "mockk", version.ref = "mockk" } +mockk-agent = { group = "io.mockk", name = "mockk-agent", version.ref = "mockk" } +mockk-android = { group = "io.mockk", name = "mockk-android", version.ref = "mockk" } +moshi-kotlin = { module = "com.squareup.moshi:moshi-kotlin", version.ref = "moshiKotlin" } +moshi-kotlin-codegen = { module = "com.squareup.moshi:moshi-kotlin-codegen", version.ref = "moshiKotlin" } +navigation-common = { group = "androidx.navigation", name = "navigation-common-ktx", version.ref = "navigation" } +navigation-fragment = { group = "androidx.navigation", name = "navigation-fragment-ktx", version.ref = "navigation" } +navigation-runtime = { group = "androidx.navigation", name = "navigation-runtime-ktx", version.ref = "navigation" } +navigation-ui = { group = "androidx.navigation", name = "navigation-ui-ktx", version.ref = "navigation" } +okhttp = { group = "com.squareup.okhttp3", name = "okhttp", version.ref = "okhttp" } +okhttp-logging = { group = "com.squareup.okhttp3", name = "logging-interceptor", version.ref = "okhttp" } +paging = { group = "androidx.paging", name = "paging-runtime-ktx", version.ref = "paging" } +paging-compose = { group = "androidx.paging", name = "paging-compose", version.ref = "paging" } +preference = { group = "androidx.preference", name = "preference-ktx", version.ref = "preferences" } +recyclerview = { group = "androidx.recyclerview", name = "recyclerview", version.ref = "recyclerview" } +retrofit = { group = "com.squareup.retrofit2", name = "retrofit", version.ref = "retrofit" } +retrofit-converter-gson = { group = "com.squareup.retrofit2", name = "converter-gson", version.ref = "retrofit" } +retrofit2-converter-moshi = { module = "com.squareup.retrofit2:converter-moshi", version.ref = "converterMoshi" } +runtime-livedata = { group = "androidx.compose.runtime", name = "runtime-livedata", version.ref = "compose" } +shimmer = { group = "com.facebook.shimmer", name = "shimmer", version.ref = "shimmer" } +swipeRefreshLayout = { group = "androidx.swiperefreshlayout", name = "swiperefreshlayout", version.ref = "swipeRefresh" } +test-core = { group = "androidx.test", name = "core", version.ref = "androidTest" } +test-core-ktx = { group = "androidx.test", name = "core-ktx", version.ref = "androidTest" } +test-fragment = { group = "androidx.fragment", name = "fragment-testing", version.ref = "fragmentTesting" } +test-junit = { group = "androidx.test.ext", name = "junit-ktx", version.ref = "junitKtx" } +test-monitor = { group = "androidx.test", name = "monitor", version.ref = "androidTest" } +test-orchestrator = { group = "androidx.test", name = "orchestrator", version.ref = "orchestrator" } +test-rules = { group = "androidx.test", name = "rules", version.ref = "androidTest" } +test-runner = { group = "androidx.test", name = "runner", version.ref = "androidTestRunner" } +text-google-fonts = { group = "androidx.compose.ui", name = "ui-text-google-fonts", version.ref = "compose" } +toolargetool = { group = "com.gu.android", name = "toolargetool", version.ref = "tooLargeTool" } +turbine = { module = "app.cash.turbine:turbine", version.ref = "turbine" } +ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling", version.ref = "compose" } +viewPagerIndicator = { group = "fr.avianey.com.viewpagerindicator", name = "library", version.ref = "pagerIndicator" } +viewmodel-compose = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-compose", version.ref = "lifecycle" } +wear = { module = "androidx.wear:wear", version.ref = "wear" } +wear-input = { module = "androidx.wear:wear-input", version.ref = "wearInput" } + +## Dependencies of included build-logic +android-gradlePlugin = { group = "com.android.tools.build", name = "gradle", version.ref = "agp" } +detekt-gradlePlugin = { group = "io.gitlab.arturbosch.detekt", name = "detekt-gradle-plugin", version.ref = "detekt" } +gson = { group = "com.google.code.gson", name = "gson", version.ref = "gson" } +ktlint-gradlePlugin = { group = "org.jlleitschuh.gradle", name = "ktlint-gradle", version.ref = "ktlintPlugin" } + +[bundles] +okhttp = ["okhttp", "okhttp-logging"] +markwon = ["markwon-core", "markwon-ext", "markwon-image", "markwon-linkify", "markwon-recycler"] +design = ["appcompat", "material", "recyclerview", "preference", "swipeRefreshLayout"] +google-services = [ + "firebase-analytic", + "firebase-crashlytics", + "firebase-messaging", + "firebase-config", + "firebase-perf", + "google-play-auth", + "google-play-wearable" +] +test-implementation = [ + "test-core", + "mockk", + "mockk-android", + "kotest-runner", + "kotest-assertions", + "kotest-framework" +] +android-test-implementation = [ + "test-runner", + "test-rules", + "test-core-ktx", + "test-junit", + "mockk-android", + "mockk-agent", + "kotest-assertions", + "kotlin-reflect", + "kaspresso-compose" +] + +[plugins] +android-application = { id = "com.android.application", version.ref = "agp" } +android-library = { id = "com.android.library", version.ref = "agp" } +crashlytics = { id = "com.google.firebase.crashlytics", version.ref = "crashlytics" } +detekt = { id = "io.gitlab.arturbosch.detekt", version.ref = "detekt" } +firebase-perf = { id = "com.google.firebase.firebase-perf", version.ref = "firebase-perf" } +google-service = { id = "com.google.gms.google-services", version.ref = "google-service" } +hilt = { id = "com.google.dagger.hilt.android", version.ref = "daggerhilt" } +kotest = { id = "io.kotest.multiplatform", version.ref = "kotest" } +kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } +kotlin-compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } +ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" } +ktlint = { id = "org.jlleitschuh.gradle.ktlint", version.ref = "ktlintPlugin" } +navigation = { id = "androidx.navigation.safeargs", version.ref = "navigation" } +realm = { id = "realm-android", version.ref = "realmPlugin" } + +## Plugins defined by build-logic +habitrpg-application = { id = "com.habitrpg.buildlogic.application", version.ref = "habitRpgPlugin" } +habitrpg-convention = { id = "com.habitrpg.buildlogic.convention", version.ref = "habitRpgPlugin" } \ No newline at end of file diff --git a/settings.gradle b/settings.gradle deleted file mode 100644 index 248391423..000000000 --- a/settings.gradle +++ /dev/null @@ -1,8 +0,0 @@ -plugins { - id 'org.gradle.toolchains.foojay-resolver-convention' version '0.6.0' -} - -include 'Habitica', ':Habitica' -include ':wearos' -include ':common' -include ':shared' diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 000000000..b5ba85062 --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1,48 @@ +@file:Suppress("UnstableApiUsage") + +enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") + +pluginManagement { + includeBuild("build-logic") + repositories { + gradlePluginPortal() + google { + content { + includeGroupByRegex("com\\.android.*") + includeGroupByRegex("com\\.google.*") + includeGroupByRegex("androidx.*") + } + } + mavenCentral() + maven("https://jitpack.io") + mavenLocal() + } + resolutionStrategy.eachPlugin { + if (requested.id.id == "realm-android") useModule( + "io.realm:realm-gradle-plugin:${requested.version}" + ) + } +} + +dependencyResolutionManagement { + repositories { + google { + content { + includeGroupByRegex("com\\.android.*") + includeGroupByRegex("com\\.google.*") + includeGroupByRegex("androidx.*") + } + } + mavenCentral() + maven("https://jitpack.io") + maven("https://plugins.gradle.org/m2/") + mavenLocal() + } +} + +plugins { + id("org.gradle.toolchains.foojay-resolver-convention") version "0.6.0" +} + +rootProject.name = "habitica-android" +include(":Habitica", ":wearos", ":common", ":shared") \ No newline at end of file diff --git a/shared/build.gradle.kts b/shared/build.gradle.kts index b3435c1c5..c4cdcbeca 100644 --- a/shared/build.gradle.kts +++ b/shared/build.gradle.kts @@ -1,20 +1,17 @@ +import org.jetbrains.kotlin.gradle.dsl.JvmTarget +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + plugins { kotlin("multiplatform") - id("com.android.library") + alias(libs.plugins.android.library) id("kotlin-parcelize") - id("kotlin-kapt") - id("io.kotest.multiplatform") version "5.6.2" -} - -allprojects { - repositories { - mavenCentral() - mavenLocal() - } + alias(libs.plugins.ksp) + alias(libs.plugins.habitrpg.convention) + alias(libs.plugins.kotest) } kotlin { - android() + androidTarget() iosX64() iosArm64() iosSimulatorArm64() @@ -27,7 +24,7 @@ kotlin { sourceSets { commonMain { dependencies { - implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:${rootProject.extra.get("coroutines_version")}") + implementation(libs.kotlinx.coroutine) } } commonTest { @@ -39,15 +36,12 @@ kotlin { } android { - compileSdk = rootProject.extra.get("target_sdk") as Int + compileSdk = libs.versions.targetSdk.get().toInt() + namespace = "com.habitrpg.shared.habitica" sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml") - defaultConfig { - minSdk = 21 - } + defaultConfig.minSdk = 21 buildTypes { - release { - } create("debugIAP") { initWith(buildTypes["debug"]) isMinifyEnabled = false @@ -60,6 +54,8 @@ android { sourceCompatibility = JavaVersion.VERSION_11 targetCompatibility = JavaVersion.VERSION_11 } - - namespace = "com.habitrpg.shared.habitica" } + +tasks.withType { + compilerOptions.jvmTarget.set(JvmTarget.JVM_11) +} \ No newline at end of file diff --git a/wearos/build.gradle b/wearos/build.gradle deleted file mode 100644 index 2cf494d1f..000000000 --- a/wearos/build.gradle +++ /dev/null @@ -1,224 +0,0 @@ -plugins { - id 'com.android.application' - id 'org.jetbrains.kotlin.android' - id 'kotlin-kapt' - id 'dagger.hilt.android.plugin' - id 'com.google.gms.google-services' - id 'com.google.firebase.crashlytics' -} -apply plugin: 'kotlin-android' - -android { - compileSdk target_sdk - - testOptions { - unitTests { - includeAndroidResources = true - } - animationsDisabled = true - } - - defaultConfig { - applicationId "com.habitrpg.android.habitica" - minSdk 26 - targetSdk wearos_target_sdk - compileSdk target_sdk - versionCode app_version_code + 1 - versionName "${app_version_name}w" - buildConfigField "String", "TESTING_LEVEL", "\"production\"" - - def formattedDate = new Date().format('yyMMdd') - archivesBaseName = "Habitica-WearOS-${formattedDate}${versionCode}" - } - - signingConfigs { - release - } - - compileOptions { - sourceCompatibility JavaVersion.VERSION_11 - targetCompatibility JavaVersion.VERSION_11 - } - - kotlinOptions { - jvmTarget = JavaVersion.VERSION_11.toString() - } - - buildTypes { - debug { - minifyEnabled false - debuggable true - ext.enableCrashlytics = false - ext.alwaysUpdateBuildId = false - resValue "string", "app_name", "Habitica Debug" - } - release { - signingConfig signingConfigs.release - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' - resValue "string", "app_name", "Habitica" - } - } - - bundle { - language { - // Specifies that the app bundle should not support - // configuration APKs for language resources. These - // resources are instead packaged with each base and - // dynamic feature APK. - enableSplit = false - } - } - - flavorDimensions.add("buildType") - - productFlavors { - dev { - dimension "buildType" - } - - staff { - dimension "buildType" - buildConfigField "String", "TESTING_LEVEL", "\"staff\"" - resValue "string", "app_name", "Habitica Staff" - versionCode app_version_code + 9 - } - - partners { - dimension "buildType" - buildConfigField "String", "TESTING_LEVEL", "\"partners\"" - resValue "string", "app_name", "Habitica" - versionCode app_version_code + 7 - } - - alpha { - dimension "buildType" - buildConfigField "String", "TESTING_LEVEL", "\"alpha\"" - resValue "string", "app_name", "Habitica Alpha" - versionCode app_version_code + 5 - } - - beta { - buildConfigField "String", "TESTING_LEVEL", "\"beta\"" - dimension "buildType" - versionCode app_version_code + 3 - } - - prod { - buildConfigField "String", "TESTING_LEVEL", "\"production\"" - dimension "buildType" - versionCode app_version_code + 1 - } - } - - buildFeatures { - viewBinding true - buildConfig true - } - namespace 'com.habitrpg.android.habitica' -} - -dependencies { - implementation fileTree(include: ['*.jar'], dir: '../common/libs') - - implementation "androidx.core:core-ktx:$core_ktx_version" - implementation "com.google.android.gms:play-services-wearable:$play_wearables_version" - implementation "androidx.recyclerview:recyclerview:$recyclerview_version" - implementation 'androidx.wear:wear:1.3.0' - implementation "androidx.wear:wear-input:1.1.0" - - //Networking - implementation "com.squareup.okhttp3:okhttp:$okhttp_version" - implementation "com.squareup.okhttp3:logging-interceptor:$okhttp_version" - - //REST API handling - implementation("com.squareup.retrofit2:retrofit:$retrofit_version") { - exclude module: 'okhttp' - } - implementation("com.squareup.retrofit2:converter-moshi:$retrofit_version") - implementation("com.squareup.moshi:moshi-kotlin:$moshi_version") - implementation 'androidx.coordinatorlayout:coordinatorlayout:1.2.0' - implementation 'androidx.constraintlayout:constraintlayout:2.1.4' - kapt("com.squareup.moshi:moshi-kotlin-codegen:$moshi_version") - - implementation platform("com.google.firebase:firebase-bom:$firebase_bom") - implementation 'com.google.firebase:firebase-crashlytics-ktx' - implementation 'com.google.firebase:firebase-analytics-ktx' - - implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version" - implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version" - implementation "androidx.lifecycle:lifecycle-runtime-ktx:$lifecycle_version" - implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version" - implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version" - implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version" - implementation "androidx.preference:preference-ktx:$preferences_version" - implementation "androidx.navigation:navigation-fragment-ktx:2.7.7" - - implementation "com.google.android.gms:play-services-auth:$play_auth_version" - - implementation project(':common') - implementation project(':shared') - implementation "androidx.appcompat:appcompat:$appcompat_version" - - implementation "com.google.dagger:hilt-android:$daggerhilt_version" - kapt "com.google.dagger:hilt-compiler:$daggerhilt_version" - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" - implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version" - - implementation "androidx.core:core-splashscreen:1.1.0-rc01" - - testImplementation "io.mockk:mockk:$mockk_version" - testImplementation "io.mockk:mockk-android:$mockk_version" - testImplementation "io.kotest:kotest-runner-junit5:$kotest_version" - testImplementation "io.kotest:kotest-assertions-core:$kotest_version" - testImplementation "io.kotest:kotest-framework-datatest:$kotest_version" - testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutines_version" - testImplementation 'app.cash.turbine:turbine:0.12.1' -} -repositories { - mavenCentral() -} - -android.testOptions { - unitTests.all { - it.useJUnitPlatform() - } -} - -final File HRPG_PROPS_FILE = new File(projectDir.absolutePath + '/../habitica.properties') -if (HRPG_PROPS_FILE.canRead()) { - Properties HRPG_PROPS = new Properties() - HRPG_PROPS.load(new FileInputStream(HRPG_PROPS_FILE)) - - if (HRPG_PROPS != null) { - android.buildTypes.configureEach { buildType -> - HRPG_PROPS.any { property -> - buildType.buildConfigField "String", property.key, "\"${property.value}\"" - } - } - } else { - throw new MissingResourceException('habitica.properties found but some entries are missing') - } -} else { - throw new MissingResourceException('habitica.properties not found') -} - -Properties props = new Properties() -def propFile = new File('signingrelease.properties') -if (propFile.canRead()) { - props.load(new FileInputStream(propFile)) - - if (props != null && props.containsKey('STORE_FILE') && props.containsKey('STORE_PASSWORD') && - props.containsKey('KEY_ALIAS') && props.containsKey('KEY_PASSWORD')) { - android.signingConfigs.release.storeFile = file(props['STORE_FILE']) - android.signingConfigs.release.storePassword = props['STORE_PASSWORD'] - android.signingConfigs.release.keyAlias = props['KEY_ALIAS'] - android.signingConfigs.release.keyPassword = props['KEY_PASSWORD'] - } else { - println 'signing.properties found but some entries are missing' - android.buildTypes.release.signingConfig = null - } -} else { - println 'signing.properties not found' - android.buildTypes.release.signingConfig = null -} diff --git a/wearos/build.gradle.kts b/wearos/build.gradle.kts new file mode 100644 index 000000000..346a2be9c --- /dev/null +++ b/wearos/build.gradle.kts @@ -0,0 +1,113 @@ +plugins { + alias(libs.plugins.android.application) + alias(libs.plugins.kotlin.android) + alias(libs.plugins.ksp) + alias(libs.plugins.hilt) + alias(libs.plugins.habitrpg.convention) + alias(libs.plugins.habitrpg.application) + alias(libs.plugins.crashlytics) + alias(libs.plugins.google.service) +} + +android { + namespace = "com.habitrpg.android.habitica" + compileSdk = libs.versions.targetSdk.get().toInt() + + defaultConfig { + applicationId = "com.habitrpg.android.habitica" + minSdk = libs.versions.minSdk.get().toInt() + targetSdk = libs.versions.wearOsTargetSdk.get().toInt() + compileSdk = libs.versions.targetSdk.get().toInt() + + buildConfigField("String", "TESTING_LEVEL", "\"production\"") + } + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + } + + buildTypes { + debug { + isMinifyEnabled = false + isDebuggable = true + ext["enableCrashlytics"] = false + ext["alwaysUpdateBuildId"] = false + resValue("string", "app_name", "Habitica Debug") + } + release { + signingConfigs.asMap["release"]?.let { releaseSigning -> signingConfig = releaseSigning } + isMinifyEnabled = false + proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") + resValue("string", "app_name", "Habitica") + } + } + + buildFeatures { + viewBinding = true + buildConfig = true + } + + testOptions { + unitTests { + isIncludeAndroidResources = true + all { it.useJUnitPlatform() } + } + animationsDisabled = true + } + + bundle.language.enableSplit = false + kotlinOptions.jvmTarget = JavaVersion.VERSION_11.toString() +} + +dependencies { + implementation(projects.shared) + implementation(projects.common) + + implementation(fileTree("../common/libs") { include("*.jar") }) + + implementation(libs.core) + implementation(libs.core.ktx) + implementation(libs.google.play.wearable) + implementation(libs.recyclerview) + implementation(libs.wear) + implementation(libs.wear.input) + + //Networking + implementation(libs.bundles.okhttp) + + //REST API handling + implementation(libs.retrofit) { exclude(module = libs.okhttp.asProvider().get().name) } + implementation(libs.retrofit2.converter.moshi) + implementation(libs.moshi.kotlin) + implementation(libs.coordinatorlayout) + implementation(libs.constraintlayout) + ksp(libs.moshi.kotlin.codegen) + + implementation(platform(libs.firebase.bom)) + implementation(libs.bundles.google.services) + + implementation(libs.lifecycle.viewmodel) + implementation(libs.lifecycle.livedata) + implementation(libs.lifecycle.runtime.ktx) + implementation(libs.lifecycle.common) + implementation(libs.kotlinx.coroutine) + implementation(libs.coroutine.android) + implementation(libs.preference) + implementation(libs.navigation.fragment) + + implementation(libs.google.play.auth) + + implementation(libs.appcompat) + + implementation(libs.hilt.android) + ksp(libs.hilt.compiler) + implementation(libs.kotlin.jdk7) + implementation(libs.kotlin.reflect) + + implementation(libs.core.splashscreen) { exclude(module = libs.core.ktx.get().name) } + + testImplementation(libs.bundles.test.implementation) + testImplementation(libs.mockk.android) + testImplementation(libs.turbine) +} diff --git a/wearos/habitica-flavor.json b/wearos/habitica-flavor.json new file mode 100644 index 000000000..53a64759f --- /dev/null +++ b/wearos/habitica-flavor.json @@ -0,0 +1,36 @@ +{ + "dimension": "buildType", + "flavors": [ + { + "name": "dev" + }, + { + "name": "staff", + "testingLevel": "\"staff\"", + "appName": "Habitica Staff", + "versionCodeIncrement": 9 + }, + { + "name": "partners", + "testingLevel": "\"partners\"", + "appName": "Habitica", + "versionCodeIncrement": 7 + }, + { + "name": "alpha", + "testingLevel": "\"alpha\"", + "appName": "Habitica Alpha", + "versionCodeIncrement": 5 + }, + { + "name": "beta", + "testingLevel": "\"beta\"", + "versionCodeIncrement": 3 + }, + { + "name": "prod", + "testingLevel": "\"production\"", + "versionCodeIncrement": 1 + } + ] +} \ No newline at end of file diff --git a/wearos/proguard-rules.pro b/wearos/proguard-rules.pro index 4cc78faa5..1f15f54f7 100644 --- a/wearos/proguard-rules.pro +++ b/wearos/proguard-rules.pro @@ -1,6 +1,6 @@ # Add project specific ProGuard rules here. # You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. +# proguardFiles setting in build.gradle.kts. # # For more details, see # http://developer.android.com/guide/developing/tools/proguard.html