From e0d44f2f1c69b6a17b8b3cc7bfd6beba3a22107f Mon Sep 17 00:00:00 2001 From: darken Date: Sat, 27 Aug 2022 22:34:28 +0200 Subject: [PATCH] Use Kotlin for Gradle DSL --- app-common/build.gradle | 120 ------- app-common/build.gradle.kts | 90 ++++++ .../eu/darken/capod/common/BuildConfigWrap.kt | 2 +- app-wear/build.gradle | 303 ------------------ app-wear/build.gradle.kts | 171 ++++++++++ .../eu/darken/capod/wear/ui/MainActivity.kt | 1 - .../src/main/res/layout/activity_main.xml | 3 +- app/build.gradle | 296 ----------------- app/build.gradle.kts | 175 ++++++++++ .../preferences/PercentSliderPreference.kt | 6 +- .../capod/common/uix/PreferenceFragment2.kt | 2 +- .../main/ui/settings/SettingsFragment.kt | 4 +- build.gradle | 54 ---- build.gradle.kts | 24 ++ buildSrc/.gitignore | 2 + buildSrc/build.gradle.kts | 14 + buildSrc/src/main/java/Dependencies.kt | 131 ++++++++ buildSrc/src/main/java/ProjectConfig.kt | 122 +++++++ buildSrc/src/main/java/Versions.kt | 52 +++ gradle/wrapper/gradle-wrapper.properties | 4 +- 20 files changed, 792 insertions(+), 784 deletions(-) delete mode 100644 app-common/build.gradle create mode 100644 app-common/build.gradle.kts delete mode 100644 app-wear/build.gradle create mode 100644 app-wear/build.gradle.kts delete mode 100644 app/build.gradle create mode 100644 app/build.gradle.kts delete mode 100644 build.gradle create mode 100644 build.gradle.kts create mode 100644 buildSrc/.gitignore create mode 100644 buildSrc/build.gradle.kts create mode 100644 buildSrc/src/main/java/Dependencies.kt create mode 100644 buildSrc/src/main/java/ProjectConfig.kt create mode 100644 buildSrc/src/main/java/Versions.kt diff --git a/app-common/build.gradle b/app-common/build.gradle deleted file mode 100644 index 537b6da2..00000000 --- a/app-common/build.gradle +++ /dev/null @@ -1,120 +0,0 @@ -plugins { - id 'com.android.library' - id 'kotlin-android' - id 'kotlin-kapt' - id 'kotlin-parcelize' - id 'androidx.navigation.safeargs.kotlin' - id 'com.bugsnag.android.gradle' - id 'dagger.hilt.android.plugin' -} - - -def gitSha = 'git rev-parse --short HEAD'.execute([], project.rootDir).text.trim() -def buildTime = new Date().format("yyyy-MM-dd'T'HH:mm:ss'Z'", TimeZone.getTimeZone("GMT+1")) - -android { - compileSdkVersion buildConfig.compileSdk - - defaultConfig { - - minSdkVersion buildConfig.minSdk - targetSdkVersion buildConfig.targetSdk - - versionCode buildConfig.version.code - versionName buildConfig.version.name - - buildConfigField "long", "VERSION_CODE", "${buildConfig.version.code}" - buildConfigField "String", "VERSION_NAME", "\"${buildConfig.version.name}\"" - - buildConfigField "String", "GITSHA", "\"${gitSha}\"" - buildConfigField "String", "BUILDTIME", "\"${buildTime}\"" - } - - flavorDimensions "version" - productFlavors { - foss { - - } - gplay { - - } - } - - buildTypes { - def proguardRulesRelease = fileTree(dir: "../proguard", include: ["*.pro"]).asList().toArray() - debug { - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt') - proguardFiles proguardRulesRelease - proguardFiles 'proguard-rules-debug.pro' - } - beta { - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt') - proguardFiles proguardRulesRelease - } - release { - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt') - proguardFiles proguardRulesRelease - } - } - - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } - - kotlinOptions { - jvmTarget = '1.8' - } - - buildFeatures { - viewBinding true - } - - tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all { - kotlinOptions { - jvmTarget = "1.8" - - freeCompilerArgs += [ - "-Xuse-experimental=kotlinx.coroutines.ExperimentalCoroutinesApi", - "-Xuse-experimental=kotlinx.coroutines.FlowPreview", - "-Xuse-experimental=kotlin.time.ExperimentalTime", - "-Xuse-experimental=kotlin.ExperimentalUnsignedTypes", - "-Xuse-experimental=kotlin.contracts.ExperimentalContracts", - "-Xopt-in=kotlin.RequiresOptIn" - ] - } - } -} - -dependencies { - - implementation("com.squareup.moshi:moshi:1.13.0") - kapt("com.squareup.moshi:moshi-kotlin-codegen:1.13.0") - - // Debugging - implementation('com.bugsnag:bugsnag-android:5.9.2') - implementation 'com.getkeepsafe.relinker:relinker:1.4.3' - - implementation 'androidx.preference:preference-ktx:1.1.1' - - // DI - implementation "com.google.dagger:dagger:${versions.dagger.core}" - implementation "com.google.dagger:dagger-android:${versions.dagger.core}" - - kapt "com.google.dagger:dagger-compiler:${versions.dagger.core}" - kapt "com.google.dagger:dagger-android-processor:${versions.dagger.core}" - - implementation "com.google.dagger:hilt-android:${versions.dagger.core}" - kapt "com.google.dagger:hilt-android-compiler:${versions.dagger.core}" - - testImplementation "com.google.dagger:hilt-android-testing:${versions.dagger.core}" - kaptTest "com.google.dagger:hilt-android-compiler:${versions.dagger.core}" - - androidTestImplementation "com.google.dagger:hilt-android-testing:${versions.dagger.core}" - kaptAndroidTest "com.google.dagger:hilt-android-compiler:${versions.dagger.core}" - - kapt "androidx.hilt:hilt-compiler:1.0.0" - implementation 'androidx.hilt:hilt-common:1.0.0' - kaptTest "androidx.hilt:hilt-compiler:1.0.0" - testImplementation 'androidx.hilt:hilt-common:1.0.0' -} \ No newline at end of file diff --git a/app-common/build.gradle.kts b/app-common/build.gradle.kts new file mode 100644 index 00000000..a0c12557 --- /dev/null +++ b/app-common/build.gradle.kts @@ -0,0 +1,90 @@ +plugins { + id("com.android.library") + id("org.jetbrains.kotlin.android") + id("kotlin-kapt") + id("kotlin-parcelize") +} +apply(plugin = "dagger.hilt.android.plugin") + +android { + compileSdk = ProjectConfig.compileSdk + + defaultConfig { + minSdk = ProjectConfig.minSdk + targetSdk = ProjectConfig.targetSdk + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + consumerProguardFiles("consumer-rules.pro") + + buildConfigField("Long", "VERSION_CODE", "${ProjectConfig.Version.code}L") + buildConfigField("String", "VERSION_NAME", "\"${ProjectConfig.Version.name}\"") + buildConfigField("String", "APPLICATION_ID", "\"${ProjectConfig.packageName}\"") + buildConfigField("String", "GITSHA", "\"${lastCommitHash()}\"") + buildConfigField("String", "BUILDTIME", "\"${buildTime()}\"") + } + + compileOptions { + isCoreLibraryDesugaringEnabled = true + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } + + kotlinOptions { + jvmTarget = "1.8" + freeCompilerArgs = freeCompilerArgs + listOf( + "-Xopt-in=kotlin.ExperimentalStdlibApi", + "-Xuse-experimental=kotlinx.coroutines.ExperimentalCoroutinesApi", + "-Xuse-experimental=kotlin.time.ExperimentalTime", + "-Xuse-experimental=kotlin.ExperimentalUnsignedTypes", + ) + } + + flavorDimensions.add("version") + productFlavors { + create("foss") { + dimension = "version" + } + create("gplay") { + dimension = "version" + } + } + + buildTypes { + val customProguardRules = fileTree(File("../proguard")) { + include("*.pro") + } + debug { + proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt")) + proguardFiles(*customProguardRules.toList().toTypedArray()) + proguardFiles("proguard-rules-debug.pro") + } + create("beta") { + proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt")) + proguardFiles(*customProguardRules.toList().toTypedArray()) + } + release { + proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt")) + proguardFiles(*customProguardRules.toList().toTypedArray()) + } + } + + testOptions { + unitTests { + isIncludeAndroidResources = true + } + tasks.withType { + useJUnitPlatform() + } + } +} + +dependencies { + coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:1.1.5") + + addBaseAndroid() + addBaseKotlin() + addDagger() + addMoshi() + + implementation("com.bugsnag:bugsnag-android:5.9.2") +} \ No newline at end of file diff --git a/app-common/src/main/java/eu/darken/capod/common/BuildConfigWrap.kt b/app-common/src/main/java/eu/darken/capod/common/BuildConfigWrap.kt index fbccbf37..35d2a414 100644 --- a/app-common/src/main/java/eu/darken/capod/common/BuildConfigWrap.kt +++ b/app-common/src/main/java/eu/darken/capod/common/BuildConfigWrap.kt @@ -34,7 +34,7 @@ object BuildConfigWrap { ; } - val APPLICATION_ID: String = TODO()//BuildConfig.APPLICATION_ID + val APPLICATION_ID: String = BuildConfig.APPLICATION_ID val VERSION_CODE: Long = BuildConfig.VERSION_CODE.toLong() val VERSION_NAME: String = BuildConfig.VERSION_NAME diff --git a/app-wear/build.gradle b/app-wear/build.gradle deleted file mode 100644 index c981106c..00000000 --- a/app-wear/build.gradle +++ /dev/null @@ -1,303 +0,0 @@ -plugins { - id 'com.android.application' - id 'kotlin-android' - id 'kotlin-kapt' - id 'kotlin-parcelize' - id 'androidx.navigation.safeargs.kotlin' - id 'com.bugsnag.android.gradle' - id 'dagger.hilt.android.plugin' -} - -def gitSha = 'git rev-parse --short HEAD'.execute([], project.rootDir).text.trim() -def buildTime = new Date().format("yyyy-MM-dd'T'HH:mm:ss'Z'", TimeZone.getTimeZone("GMT+1")) - -android { - def packageName = "eu.darken.capod" - - compileSdkVersion buildConfig.compileSdk - - defaultConfig { - applicationId "${packageName}" - - minSdkVersion buildConfig.minSdk - targetSdkVersion buildConfig.targetSdk - - versionCode buildConfig.version.code - versionName buildConfig.version.name - - testInstrumentationRunner "eu.darken.capod.HiltTestRunner" - - buildConfigField "String", "GITSHA", "\"${gitSha}\"" - buildConfigField "String", "BUILDTIME", "\"${buildTime}\"" - - manifestPlaceholders = [bugsnagApiKey: "fake"] - } - - signingConfigs { - releaseFoss {} - releaseGplay {} - } - - signingConfigs { - releaseFoss { - def signingFossPropFile = new File(System.properties['user.home'], ".appconfig/${packageName}/signing-foss.properties") - Properties signingPropsFoss = new Properties() - if (signingFossPropFile.canRead()) signingPropsFoss.load(new FileInputStream(signingFossPropFile)) - String keyStorePathFoss = System.getenv("STORE_PATH") ?: signingPropsFoss["release.storePath"] - File keyStoreFoss = keyStorePathFoss ? new File(keyStorePathFoss) : null - if (keyStoreFoss?.canRead()) { - storeFile keyStoreFoss - storePassword System.getenv("STORE_PASSWORD") ?: signingPropsFoss['release.storePassword'] - keyAlias System.getenv("KEY_ALIAS") ?: signingPropsFoss['release.keyAlias'] - keyPassword System.getenv("KEY_PASSWORD") ?: signingPropsFoss['release.keyPassword'] - } - } - - releaseGplay { - def signingGplayPropFile = new File(System.properties['user.home'], ".appconfig/${packageName}/signing-gplay.properties") - Properties signingPropsGplay = new Properties() - if (signingGplayPropFile.canRead()) signingPropsGplay.load(new FileInputStream(signingGplayPropFile)) - String keyStorePathGplay = System.getenv("STORE_PATH") ?: signingPropsGplay["release.storePath"] - File keyStoreGplay = keyStorePathGplay ? new File(keyStorePathGplay) : null - if (keyStoreGplay?.canRead()) { - storeFile keyStoreGplay - storePassword System.getenv("STORE_PASSWORD") ?: signingPropsGplay['release.storePassword'] - keyAlias System.getenv("KEY_ALIAS") ?: signingPropsGplay['release.keyAlias'] - keyPassword System.getenv("KEY_PASSWORD") ?: signingPropsGplay['release.keyPassword'] - } - } - } - - flavorDimensions "version" - productFlavors { - foss { - signingConfig signingConfigs.releaseFoss - } - gplay { - signingConfig signingConfigs.releaseGplay - } - } - - Properties bugsnagProps = new Properties() - def bugsnagPropsFile = new File(System.properties['user.home'], ".appconfig/${packageName}/bugsnag.properties") - if (bugsnagPropsFile.canRead()) bugsnagProps.load(new FileInputStream(bugsnagPropsFile)) - String bugSnagApiKey = System.getenv("BUGSNAG_API_KEY") ?: bugsnagProps.getProperty("bugsnag.apikey", "") - - buildTypes { - def proguardRulesRelease = fileTree(dir: "../proguard", include: ["*.pro"]).asList().toArray() - debug { - minifyEnabled false - shrinkResources false - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt') - proguardFiles proguardRulesRelease - proguardFiles 'proguard-rules-debug.pro' - manifestPlaceholders = [bugsnagApiKey: bugSnagApiKey] - } - beta { - lintOptions { - abortOnError true - fatal 'StopShip' - } - minifyEnabled true - shrinkResources true - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt') - proguardFiles proguardRulesRelease - manifestPlaceholders = [bugsnagApiKey: bugSnagApiKey] - } - release { - lintOptions { - abortOnError true - fatal 'StopShip' - } - minifyEnabled true - shrinkResources true - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt') - proguardFiles proguardRulesRelease - manifestPlaceholders = [bugsnagApiKey: bugSnagApiKey] - } - } - - applicationVariants.all { variant -> - def flavor = variant.productFlavors[0].name.toUpperCase() - def buildType = variant.buildType.name.toUpperCase() - def versionCode = defaultConfig.versionCode - def versionName = defaultConfig.versionName - - if (variant.buildType.name == "debug") { - variant.mergedFlavor.resourceConfigurations.clear() - variant.mergedFlavor.resourceConfigurations.add("en") - variant.mergedFlavor.resourceConfigurations.add("de") - } else if (variant.buildType.name != "debug") { - variant.outputs.each { output -> - output.outputFileName = "${packageName}-v${versionName}(${versionCode})-${gitSha}-${flavor}-${buildType}.apk" - } - } - } - - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } - - kotlinOptions { - jvmTarget = '1.8' - } - - buildFeatures { - viewBinding true - } - - tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all { - kotlinOptions { - jvmTarget = "1.8" - - freeCompilerArgs += [ - "-Xuse-experimental=kotlinx.coroutines.ExperimentalCoroutinesApi", - "-Xuse-experimental=kotlinx.coroutines.FlowPreview", - "-Xuse-experimental=kotlin.time.ExperimentalTime", - "-Xuse-experimental=kotlin.ExperimentalUnsignedTypes", - "-Xuse-experimental=kotlin.contracts.ExperimentalContracts", - "-Xopt-in=kotlin.RequiresOptIn" - ] - } - } - - testOptions { - unitTests.all { - useJUnitPlatform() - } - unitTests { - includeAndroidResources = true - } - } - - sourceSets { - test { - java.srcDirs += "$projectDir/src/testShared/java" - } - androidTest { - java.srcDirs += "$projectDir/src/testShared/java" - androidTest.assets.srcDirs += files("$projectDir/schemas".toString()) - } - } -} - -dependencies { - implementation(project(":app-common")) - - // Kotlin - implementation "org.jetbrains.kotlin:kotlin-stdlib:${versions.kotlin.core}" - implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:${versions.kotlin.coroutines}" - implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:${versions.kotlin.coroutines}" - - testImplementation "org.jetbrains.kotlin:kotlin-reflect:${versions.kotlin.core}" - testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:${versions.kotlin.coroutines}" - androidTestImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:${versions.kotlin.coroutines}") { - // conflicts with mockito due to direct inclusion of byte buddy - exclude group: "org.jetbrains.kotlinx", module: "kotlinx-coroutines-debug" - } - - implementation ("androidx.wear:wear:1.2.0") - implementation ("androidx.wear.tiles:tiles-material:1.1.0") - implementation ("com.google.android.horologist:horologist-tiles:0.1.5") - implementation 'com.google.android.gms:play-services-wearable:17.1.0' - - // Debugging - implementation('com.bugsnag:bugsnag-android:5.9.2') - implementation 'com.getkeepsafe.relinker:relinker:1.4.3' - - implementation("com.squareup.moshi:moshi:1.13.0") - kapt("com.squareup.moshi:moshi-kotlin-codegen:1.13.0") - - // DI - implementation "com.google.dagger:dagger:${versions.dagger.core}" - implementation "com.google.dagger:dagger-android:${versions.dagger.core}" - - kapt "com.google.dagger:dagger-compiler:${versions.dagger.core}" - kapt "com.google.dagger:dagger-android-processor:${versions.dagger.core}" - - implementation "com.google.dagger:hilt-android:${versions.dagger.core}" - kapt "com.google.dagger:hilt-android-compiler:${versions.dagger.core}" - - testImplementation "com.google.dagger:hilt-android-testing:${versions.dagger.core}" - kaptTest "com.google.dagger:hilt-android-compiler:${versions.dagger.core}" - - androidTestImplementation "com.google.dagger:hilt-android-testing:${versions.dagger.core}" - kaptAndroidTest "com.google.dagger:hilt-android-compiler:${versions.dagger.core}" - - kapt "androidx.hilt:hilt-compiler:1.0.0" - implementation 'androidx.hilt:hilt-common:1.0.0' - kaptTest "androidx.hilt:hilt-compiler:1.0.0" - testImplementation 'androidx.hilt:hilt-common:1.0.0' - - // Support libs - implementation 'androidx.core:core-ktx:1.7.0' - implementation 'androidx.appcompat:appcompat:1.4.0' - implementation 'androidx.annotation:annotation:1.3.0' - - implementation 'androidx.activity:activity-ktx:1.4.0' - implementation 'androidx.fragment:fragment-ktx:1.4.0' - - implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0' - implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.0' - implementation 'androidx.lifecycle:lifecycle-viewmodel-savedstate:2.4.0' - implementation 'androidx.lifecycle:lifecycle-common-java8:2.4.0' - implementation 'androidx.lifecycle:lifecycle-process:2.4.0' - implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.4.0' - - implementation "androidx.navigation:navigation-fragment-ktx:2.3.5" - implementation "androidx.navigation:navigation-ui-ktx:2.3.5" - - implementation 'androidx.preference:preference-ktx:1.1.1' - - implementation 'androidx.core:core-splashscreen:1.0.0-alpha02' - - - def work_version = "2.7.1" - implementation "androidx.work:work-runtime:${work_version}" - testImplementation "androidx.work:work-testing:${work_version}" - implementation "androidx.work:work-runtime-ktx:${work_version}" - implementation 'androidx.hilt:hilt-work:1.0.0' - - // IAP - gplayImplementation 'com.android.billingclient:billing:4.0.0' - - // UI - implementation 'androidx.constraintlayout:constraintlayout:2.1.2' - implementation 'com.google.android.material:material:1.6.0-alpha01' - - - // Testing - testImplementation 'junit:junit:4.13.2' - testImplementation "org.junit.vintage:junit-vintage-engine:5.7.1" - testImplementation "androidx.test:core-ktx:1.4.0" - - testImplementation "io.mockk:mockk:1.12.1" - androidTestImplementation "io.mockk:mockk-android:1.11.0" - - testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:5.7.1" - testImplementation "org.junit.jupiter:junit-jupiter-api:5.7.1" - testImplementation "org.junit.jupiter:junit-jupiter-params:5.7.1" - - androidTestImplementation "androidx.navigation:navigation-testing:2.3.5" - - testImplementation "io.kotest:kotest-runner-junit5:4.6.2" - testImplementation "io.kotest:kotest-assertions-core-jvm:4.6.2" - testImplementation "io.kotest:kotest-property-jvm:4.6.2" - androidTestImplementation "io.kotest:kotest-assertions-core-jvm:4.6.2" - androidTestImplementation "io.kotest:kotest-property-jvm:4.6.2" - - testImplementation 'android.arch.core:core-testing:1.1.1' - androidTestImplementation 'android.arch.core:core-testing:1.1.1' - debugImplementation 'androidx.test:core-ktx:1.4.0' - - androidTestImplementation 'androidx.test.ext:junit:1.1.3' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' - - androidTestImplementation 'androidx.test:runner:1.4.0' - androidTestImplementation 'androidx.test:rules:1.4.0' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' - androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.4.0' - androidTestImplementation 'androidx.test.espresso:espresso-intents:3.4.0' - androidTestImplementation 'androidx.test.espresso.idling:idling-concurrent:3.4.0' -} \ No newline at end of file diff --git a/app-wear/build.gradle.kts b/app-wear/build.gradle.kts new file mode 100644 index 00000000..498e4459 --- /dev/null +++ b/app-wear/build.gradle.kts @@ -0,0 +1,171 @@ +plugins { + id("com.android.application") + id("kotlin-android") + id("kotlin-kapt") + id("kotlin-parcelize") +} +apply(plugin = "dagger.hilt.android.plugin") +apply(plugin = "androidx.navigation.safeargs.kotlin") +apply(plugin = "com.bugsnag.android.gradle") + +android { + val packageName = "eu.darken.androidstarter" + + compileSdk = ProjectConfig.compileSdk + + defaultConfig { + applicationId = packageName + + minSdk = ProjectConfig.minSdk + targetSdk = ProjectConfig.targetSdk + + versionCode = ProjectConfig.Version.code + versionName = ProjectConfig.Version.name + + testInstrumentationRunner = "eu.darken.androidstarter.HiltTestRunner" + + buildConfigField("String", "GITSHA", "\"${lastCommitHash()}\"") + buildConfigField("String", "BUILDTIME", "\"${buildTime()}\"") + + manifestPlaceholders["bugsnagApiKey"] = getBugSnagApiKey( + File(System.getProperty("user.home"), ".appconfig/${packageName}/bugsnag.properties") + ) ?: "fake" + } + + signingConfigs { + val basePath = File(System.getProperty("user.home"), ".appconfig/${packageName}") + create("releaseFoss") { + setupCredentials(File(basePath, "signing-foss.properties")) + } + create("releaseGplay") { + setupCredentials(File(basePath, "signing-gplay-upload.properties")) + } + } + + flavorDimensions.add("version") + productFlavors { + create("foss") { + dimension = "version" + signingConfig = signingConfigs["releaseFoss"] + } + create("gplay") { + dimension = "version" + signingConfig = signingConfigs["releaseGplay"] + } + } + + buildTypes { + val customProguardRules = fileTree(File("../proguard")) { + include("*.pro") + } + debug { + isMinifyEnabled = false + isShrinkResources = false + proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt")) + proguardFiles(*customProguardRules.toList().toTypedArray()) + proguardFiles("proguard-rules-debug.pro") + } + create("beta") { + lint { + abortOnError = true + fatal.add("StopShip") + } + isMinifyEnabled = true + isShrinkResources = true + proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt")) + proguardFiles(*customProguardRules.toList().toTypedArray()) + } + release { + lint { + abortOnError = true + fatal.add("StopShip") + } + isMinifyEnabled = true + isShrinkResources = true + proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt")) + proguardFiles(*customProguardRules.toList().toTypedArray()) + } + } + + buildOutputs.all { + val variantOutputImpl = this as com.android.build.gradle.internal.api.BaseVariantOutputImpl + val variantName: String = variantOutputImpl.name + + if (listOf("release", "beta").any { variantName.toLowerCase().contains(it) }) { + val outputFileName = packageName + + "-v${defaultConfig.versionName}-${defaultConfig.versionCode}" + + "-${variantName.toUpperCase()}-${lastCommitHash()}.apk" + + variantOutputImpl.outputFileName = outputFileName + } + } + + buildFeatures { + viewBinding = true + } + + compileOptions { + isCoreLibraryDesugaringEnabled = true + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } + + kotlinOptions { + jvmTarget = "1.8" + freeCompilerArgs = freeCompilerArgs + listOf( + "-Xopt-in=kotlin.ExperimentalStdlibApi", + "-Xopt-in=kotlinx.coroutines.ExperimentalCoroutinesApi", + "-Xopt-in=kotlinx.coroutines.FlowPreview", + "-Xopt-in=kotlin.time.ExperimentalTime", + "-Xopt-in=kotlin.RequiresOptIn" + ) + } + + testOptions { + unitTests { + isIncludeAndroidResources = true + } + tasks.withType { + useJUnitPlatform() + } + } + + sourceSets { + getByName("test") { + java.srcDir("$projectDir/src/testShared/java") + } + getByName("androidTest") { + java.srcDir("$projectDir/src/testShared/java") + assets.srcDirs(files("$projectDir/schemas")) + } + } +} + +dependencies { + implementation(project(":app-common")) + + implementation("androidx.wear:wear:1.2.0") + implementation("androidx.wear.tiles:tiles-material:1.1.0") + implementation("com.google.android.horologist:horologist-tiles:0.1.5") + implementation("com.google.android.gms:play-services-wearable:17.1.0") + + coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:1.1.5") + + addBaseKotlin() + + addDagger() + + // Debugging + implementation("com.bugsnag:bugsnag-android:5.9.2") + implementation("com.getkeepsafe.relinker:relinker:1.4.3") + + implementation("androidx.core:core-splashscreen:1.0.0-alpha02") + + addBaseWorkManager() + + addBaseAndroid() + addBaseAndroidUi() + implementation("com.google.android.material:material:1.5.0-rc01") + + addTesting() +} \ No newline at end of file diff --git a/app-wear/src/main/java/eu/darken/capod/wear/ui/MainActivity.kt b/app-wear/src/main/java/eu/darken/capod/wear/ui/MainActivity.kt index 4047e97b..24a9759f 100644 --- a/app-wear/src/main/java/eu/darken/capod/wear/ui/MainActivity.kt +++ b/app-wear/src/main/java/eu/darken/capod/wear/ui/MainActivity.kt @@ -13,6 +13,5 @@ class MainActivity : Activity() { binding = ActivityMainBinding.inflate(layoutInflater) setContentView(binding.root) - } } \ No newline at end of file diff --git a/app-wear/src/main/res/layout/activity_main.xml b/app-wear/src/main/res/layout/activity_main.xml index 86325ecb..32d061d2 100644 --- a/app-wear/src/main/res/layout/activity_main.xml +++ b/app-wear/src/main/res/layout/activity_main.xml @@ -14,8 +14,9 @@ android:padding="@dimen/inner_frame_layout_padding" app:layout_boxedEdges="all"> - diff --git a/app/build.gradle b/app/build.gradle deleted file mode 100644 index 22a3de6f..00000000 --- a/app/build.gradle +++ /dev/null @@ -1,296 +0,0 @@ -plugins { - id 'com.android.application' - id 'kotlin-android' - id 'kotlin-kapt' - id 'kotlin-parcelize' - id 'androidx.navigation.safeargs.kotlin' - id 'com.bugsnag.android.gradle' - id 'dagger.hilt.android.plugin' -} - -def gitSha = 'git rev-parse --short HEAD'.execute([], project.rootDir).text.trim() -def buildTime = new Date().format("yyyy-MM-dd'T'HH:mm:ss'Z'", TimeZone.getTimeZone("GMT+1")) - -android { - def packageName = "eu.darken.capod" - - compileSdkVersion buildConfig.compileSdk - - defaultConfig { - applicationId "${packageName}" - - minSdkVersion buildConfig.minSdk - targetSdkVersion buildConfig.targetSdk - - versionCode buildConfig.version.code - versionName buildConfig.version.name - - testInstrumentationRunner "eu.darken.capod.HiltTestRunner" - - buildConfigField "String", "GITSHA", "\"${gitSha}\"" - buildConfigField "String", "BUILDTIME", "\"${buildTime}\"" - - manifestPlaceholders = [bugsnagApiKey: "fake"] - } - - signingConfigs { - releaseFoss {} - releaseGplay {} - } - - signingConfigs { - releaseFoss { - def signingFossPropFile = new File(System.properties['user.home'], ".appconfig/${packageName}/signing-foss.properties") - Properties signingPropsFoss = new Properties() - if (signingFossPropFile.canRead()) signingPropsFoss.load(new FileInputStream(signingFossPropFile)) - String keyStorePathFoss = System.getenv("STORE_PATH") ?: signingPropsFoss["release.storePath"] - File keyStoreFoss = keyStorePathFoss ? new File(keyStorePathFoss) : null - if (keyStoreFoss?.canRead()) { - storeFile keyStoreFoss - storePassword System.getenv("STORE_PASSWORD") ?: signingPropsFoss['release.storePassword'] - keyAlias System.getenv("KEY_ALIAS") ?: signingPropsFoss['release.keyAlias'] - keyPassword System.getenv("KEY_PASSWORD") ?: signingPropsFoss['release.keyPassword'] - } - } - - releaseGplay { - def signingGplayPropFile = new File(System.properties['user.home'], ".appconfig/${packageName}/signing-gplay.properties") - Properties signingPropsGplay = new Properties() - if (signingGplayPropFile.canRead()) signingPropsGplay.load(new FileInputStream(signingGplayPropFile)) - String keyStorePathGplay = System.getenv("STORE_PATH") ?: signingPropsGplay["release.storePath"] - File keyStoreGplay = keyStorePathGplay ? new File(keyStorePathGplay) : null - if (keyStoreGplay?.canRead()) { - storeFile keyStoreGplay - storePassword System.getenv("STORE_PASSWORD") ?: signingPropsGplay['release.storePassword'] - keyAlias System.getenv("KEY_ALIAS") ?: signingPropsGplay['release.keyAlias'] - keyPassword System.getenv("KEY_PASSWORD") ?: signingPropsGplay['release.keyPassword'] - } - } - } - - flavorDimensions "version" - productFlavors { - foss { - signingConfig signingConfigs.releaseFoss - } - gplay { - signingConfig signingConfigs.releaseGplay - } - } - - Properties bugsnagProps = new Properties() - def bugsnagPropsFile = new File(System.properties['user.home'], ".appconfig/${packageName}/bugsnag.properties") - if (bugsnagPropsFile.canRead()) bugsnagProps.load(new FileInputStream(bugsnagPropsFile)) - String bugSnagApiKey = System.getenv("BUGSNAG_API_KEY") ?: bugsnagProps.getProperty("bugsnag.apikey", "") - - buildTypes { - def proguardRulesRelease = fileTree(dir: "../proguard", include: ["*.pro"]).asList().toArray() - debug { - minifyEnabled false - shrinkResources false - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt') - proguardFiles proguardRulesRelease - proguardFiles 'proguard-rules-debug.pro' - manifestPlaceholders = [bugsnagApiKey: bugSnagApiKey] - } - beta { - lintOptions { - abortOnError true - fatal 'StopShip' - } - minifyEnabled true - shrinkResources true - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt') - proguardFiles proguardRulesRelease - manifestPlaceholders = [bugsnagApiKey: bugSnagApiKey] - } - release { - lintOptions { - abortOnError true - fatal 'StopShip' - } - minifyEnabled true - shrinkResources true - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt') - proguardFiles proguardRulesRelease - manifestPlaceholders = [bugsnagApiKey: bugSnagApiKey] - } - } - - applicationVariants.all { variant -> - def flavor = variant.productFlavors[0].name.toUpperCase() - def buildType = variant.buildType.name.toUpperCase() - def versionCode = defaultConfig.versionCode - def versionName = defaultConfig.versionName - - if (variant.buildType.name == "debug") { - variant.mergedFlavor.resourceConfigurations.clear() - variant.mergedFlavor.resourceConfigurations.add("en") - variant.mergedFlavor.resourceConfigurations.add("de") - } else if (variant.buildType.name != "debug") { - variant.outputs.each { output -> - output.outputFileName = "${packageName}-v${versionName}(${versionCode})-${gitSha}-${flavor}-${buildType}.apk" - } - } - } - - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } - - kotlinOptions { - jvmTarget = '1.8' - } - - buildFeatures { - viewBinding true - } - - tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all { - kotlinOptions { - jvmTarget = "1.8" - - freeCompilerArgs += [ - "-Xopt-in=kotlinx.coroutines.ExperimentalCoroutinesApi", - "-Xopt-in=kotlinx.coroutines.FlowPreview", - "-Xopt-in=kotlin.time.ExperimentalTime", - "-Xopt-in=kotlin.ExperimentalUnsignedTypes", - "-Xopt-in=kotlin.contracts.ExperimentalContracts", - "-Xopt-in=kotlin.RequiresOptIn" - ] - } - } - - testOptions { - unitTests.all { - useJUnitPlatform() - } - unitTests { - includeAndroidResources = true - } - } - - sourceSets { - test { - java.srcDirs += "$projectDir/src/testShared/java" - } - androidTest { - java.srcDirs += "$projectDir/src/testShared/java" - androidTest.assets.srcDirs += files("$projectDir/schemas".toString()) - } - } -} - -dependencies { - implementation(project(":app-common")) - // Kotlin - implementation "org.jetbrains.kotlin:kotlin-stdlib:${versions.kotlin.core}" - implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:${versions.kotlin.coroutines}" - implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:${versions.kotlin.coroutines}" - - testImplementation "org.jetbrains.kotlin:kotlin-reflect:${versions.kotlin.core}" - testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:${versions.kotlin.coroutines}" - androidTestImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:${versions.kotlin.coroutines}") { - // conflicts with mockito due to direct inclusion of byte buddy - exclude group: "org.jetbrains.kotlinx", module: "kotlinx-coroutines-debug" - } - - // Debugging - implementation('com.bugsnag:bugsnag-android:5.9.2') - implementation 'com.getkeepsafe.relinker:relinker:1.4.3' - - implementation("com.squareup.moshi:moshi:1.13.0") - kapt("com.squareup.moshi:moshi-kotlin-codegen:1.13.0") - - // DI - implementation "com.google.dagger:dagger:${versions.dagger.core}" - implementation "com.google.dagger:dagger-android:${versions.dagger.core}" - - kapt "com.google.dagger:dagger-compiler:${versions.dagger.core}" - kapt "com.google.dagger:dagger-android-processor:${versions.dagger.core}" - - implementation "com.google.dagger:hilt-android:${versions.dagger.core}" - kapt "com.google.dagger:hilt-android-compiler:${versions.dagger.core}" - - testImplementation "com.google.dagger:hilt-android-testing:${versions.dagger.core}" - kaptTest "com.google.dagger:hilt-android-compiler:${versions.dagger.core}" - - androidTestImplementation "com.google.dagger:hilt-android-testing:${versions.dagger.core}" - kaptAndroidTest "com.google.dagger:hilt-android-compiler:${versions.dagger.core}" - - kapt "androidx.hilt:hilt-compiler:1.0.0" - implementation 'androidx.hilt:hilt-common:1.0.0' - kaptTest "androidx.hilt:hilt-compiler:1.0.0" - testImplementation 'androidx.hilt:hilt-common:1.0.0' - - // Support libs - implementation 'androidx.core:core-ktx:1.7.0' - implementation 'androidx.appcompat:appcompat:1.4.0' - implementation 'androidx.annotation:annotation:1.3.0' - - implementation 'androidx.activity:activity-ktx:1.5.1' - implementation 'androidx.fragment:fragment-ktx:1.5.2' - - implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0' - implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.0' - implementation 'androidx.lifecycle:lifecycle-viewmodel-savedstate:2.4.0' - implementation 'androidx.lifecycle:lifecycle-common-java8:2.4.0' - implementation 'androidx.lifecycle:lifecycle-process:2.4.0' - implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.4.0' - - implementation "androidx.navigation:navigation-fragment-ktx:2.5.1" - implementation "androidx.navigation:navigation-ui-ktx:2.5.1" - - implementation 'androidx.preference:preference-ktx:1.1.1' - - implementation 'androidx.core:core-splashscreen:1.0.0' - - - def work_version = "2.7.1" - implementation "androidx.work:work-runtime:${work_version}" - testImplementation "androidx.work:work-testing:${work_version}" - implementation "androidx.work:work-runtime-ktx:${work_version}" - implementation 'androidx.hilt:hilt-work:1.0.0' - - // IAP - gplayImplementation 'com.android.billingclient:billing:4.0.0' - - // UI - implementation 'androidx.constraintlayout:constraintlayout:2.1.2' - implementation 'com.google.android.material:material:1.6.0-alpha01' - - // Testing - testImplementation 'junit:junit:4.13.2' - testImplementation "org.junit.vintage:junit-vintage-engine:5.7.1" - testImplementation "androidx.test:core-ktx:1.4.0" - - testImplementation "io.mockk:mockk:1.12.1" - androidTestImplementation "io.mockk:mockk-android:1.11.0" - - testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:5.7.1" - testImplementation "org.junit.jupiter:junit-jupiter-api:5.7.1" - testImplementation "org.junit.jupiter:junit-jupiter-params:5.7.1" - - androidTestImplementation "androidx.navigation:navigation-testing:2.3.5" - - testImplementation "io.kotest:kotest-runner-junit5:4.6.2" - testImplementation "io.kotest:kotest-assertions-core-jvm:4.6.2" - testImplementation "io.kotest:kotest-property-jvm:4.6.2" - androidTestImplementation "io.kotest:kotest-assertions-core-jvm:4.6.2" - androidTestImplementation "io.kotest:kotest-property-jvm:4.6.2" - - testImplementation 'android.arch.core:core-testing:1.1.1' - androidTestImplementation 'android.arch.core:core-testing:1.1.1' - debugImplementation 'androidx.test:core-ktx:1.4.0' - - androidTestImplementation 'androidx.test.ext:junit:1.1.3' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' - - androidTestImplementation 'androidx.test:runner:1.4.0' - androidTestImplementation 'androidx.test:rules:1.4.0' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' - androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.4.0' - androidTestImplementation 'androidx.test.espresso:espresso-intents:3.4.0' - androidTestImplementation 'androidx.test.espresso.idling:idling-concurrent:3.4.0' -} \ No newline at end of file diff --git a/app/build.gradle.kts b/app/build.gradle.kts new file mode 100644 index 00000000..a0a4ecfd --- /dev/null +++ b/app/build.gradle.kts @@ -0,0 +1,175 @@ +plugins { + id("com.android.application") + id("kotlin-android") + id("kotlin-kapt") + id("kotlin-parcelize") +} +apply(plugin = "dagger.hilt.android.plugin") +apply(plugin = "androidx.navigation.safeargs.kotlin") +apply(plugin = "com.bugsnag.android.gradle") + +android { + + compileSdk = ProjectConfig.compileSdk + + defaultConfig { + applicationId = ProjectConfig.packageName + + minSdk = ProjectConfig.minSdk + targetSdk = ProjectConfig.targetSdk + + versionCode = ProjectConfig.Version.code + versionName = ProjectConfig.Version.name + + testInstrumentationRunner = "eu.darken.androidstarter.HiltTestRunner" + + manifestPlaceholders["bugsnagApiKey"] = getBugSnagApiKey( + File(System.getProperty("user.home"), ".appconfig/${ProjectConfig.packageName}/bugsnag.properties") + ) ?: "fake" + } + + signingConfigs { + val basePath = File(System.getProperty("user.home"), ".appconfig/${ProjectConfig.packageName}") + create("releaseFoss") { + setupCredentials(File(basePath, "signing-foss.properties")) + } + create("releaseGplay") { + setupCredentials(File(basePath, "signing-gplay-upload.properties")) + } + } + + flavorDimensions.add("version") + productFlavors { + create("foss") { + dimension = "version" + signingConfig = signingConfigs["releaseFoss"] + } + create("gplay") { + dimension = "version" + signingConfig = signingConfigs["releaseGplay"] + } + } + + buildTypes { + val customProguardRules = fileTree(File("../proguard")) { + include("*.pro") + } + debug { + isMinifyEnabled = false + isShrinkResources = false + proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt")) + proguardFiles(*customProguardRules.toList().toTypedArray()) + proguardFiles("proguard-rules-debug.pro") + } + create("beta") { + lint { + abortOnError = true + fatal.add("StopShip") + } + isMinifyEnabled = true + isShrinkResources = true + proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt")) + proguardFiles(*customProguardRules.toList().toTypedArray()) + } + release { + lint { + abortOnError = true + fatal.add("StopShip") + } + isMinifyEnabled = true + isShrinkResources = true + proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt")) + proguardFiles(*customProguardRules.toList().toTypedArray()) + } + } + + buildOutputs.all { + val variantOutputImpl = this as com.android.build.gradle.internal.api.BaseVariantOutputImpl + val variantName: String = variantOutputImpl.name + + if (listOf("release", "beta").any { variantName.toLowerCase().contains(it) }) { + val outputFileName = ProjectConfig.packageName + + "-v${defaultConfig.versionName}-${defaultConfig.versionCode}" + + "-${variantName.toUpperCase()}-${lastCommitHash()}.apk" + + variantOutputImpl.outputFileName = outputFileName + } + } + + buildFeatures { + viewBinding = true + } + + compileOptions { + isCoreLibraryDesugaringEnabled = true + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } + + kotlinOptions { + jvmTarget = "1.8" + freeCompilerArgs = freeCompilerArgs + listOf( + "-Xopt-in=kotlin.ExperimentalStdlibApi", + "-Xuse-experimental=kotlinx.coroutines.ExperimentalCoroutinesApi", + "-Xuse-experimental=kotlinx.coroutines.FlowPreview", + "-Xuse-experimental=kotlin.time.ExperimentalTime", + "-Xopt-in=kotlin.RequiresOptIn" + ) + } + + testOptions { + unitTests { + isIncludeAndroidResources = true + } + tasks.withType { + useJUnitPlatform() + } + } + + sourceSets { + getByName("test") { + java.srcDir("$projectDir/src/testShared/java") + } + getByName("androidTest") { + java.srcDir("$projectDir/src/testShared/java") + assets.srcDirs(files("$projectDir/schemas")) + } + } +} + +dependencies { + implementation(project(":app-common")) + + coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:1.1.5") + + addBaseKotlin() + + addDagger() + + addMoshi() + + addOkio() + + addBaseAndroid() + addBaseAndroidUi() + + addNavigation() + + implementation("androidx.navigation:navigation-fragment-ktx:2.5.0") + implementation("androidx.navigation:navigation-ui-ktx:2.5.0") + + + addBaseWorkManager() + + // UI + implementation("com.google.android.material:material:1.5.0-rc01") + implementation("androidx.core:core-splashscreen:1.0.0-alpha02") + + // Debugging + implementation("com.bugsnag:bugsnag-android:5.9.2") + implementation("com.getkeepsafe.relinker:relinker:1.4.3") + + addTesting() + + "gplayImplementation"("com.android.billingclient:billing:4.0.0") +} \ No newline at end of file diff --git a/app/src/main/java/eu/darken/capod/common/preferences/PercentSliderPreference.kt b/app/src/main/java/eu/darken/capod/common/preferences/PercentSliderPreference.kt index d438e91c..a103796a 100644 --- a/app/src/main/java/eu/darken/capod/common/preferences/PercentSliderPreference.kt +++ b/app/src/main/java/eu/darken/capod/common/preferences/PercentSliderPreference.kt @@ -12,7 +12,7 @@ import eu.darken.capod.R import eu.darken.capod.common.preferences.PercentSliderPreferenceDialogFragment.Companion.newInstance import kotlinx.parcelize.Parcelize -class PercentSliderPreference(context: Context?, attrs: AttributeSet?) : DialogPreference(context, attrs) { +class PercentSliderPreference(context: Context, attrs: AttributeSet?) : DialogPreference(context, attrs) { @get:PluralsRes val sliderTextPluralsResource: Int val min: Float @@ -51,7 +51,7 @@ class PercentSliderPreference(context: Context?, attrs: AttributeSet?) : DialogP value = if (restoreValue) getPersistedFloat(internalValue) else defaultValue as Float } - override fun onSaveInstanceState(): Parcelable { + override fun onSaveInstanceState(): Parcelable? { val superState = super.onSaveInstanceState() // No need to save instance state since it's persistent if (isPersistent) return superState @@ -73,7 +73,7 @@ class PercentSliderPreference(context: Context?, attrs: AttributeSet?) : DialogP @Parcelize data class SavedState( val value: Float, - val superState: Parcelable, + val superState: Parcelable?, ) : Parcelable companion object { diff --git a/app/src/main/java/eu/darken/capod/common/uix/PreferenceFragment2.kt b/app/src/main/java/eu/darken/capod/common/uix/PreferenceFragment2.kt index f566dd60..98f23401 100644 --- a/app/src/main/java/eu/darken/capod/common/uix/PreferenceFragment2.kt +++ b/app/src/main/java/eu/darken/capod/common/uix/PreferenceFragment2.kt @@ -27,7 +27,7 @@ abstract class PreferenceFragment2 val toolbar: Toolbar get() = (parentFragment as SettingsFragment).toolbar - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { toolbar.menu.clear() return super.onCreateView(inflater, container, savedInstanceState) } diff --git a/app/src/main/java/eu/darken/capod/main/ui/settings/SettingsFragment.kt b/app/src/main/java/eu/darken/capod/main/ui/settings/SettingsFragment.kt index 790beb80..b4361f55 100644 --- a/app/src/main/java/eu/darken/capod/main/ui/settings/SettingsFragment.kt +++ b/app/src/main/java/eu/darken/capod/main/ui/settings/SettingsFragment.kt @@ -83,7 +83,7 @@ class SettingsFragment : Fragment2(R.layout.settings_fragment), override fun onPreferenceStartFragment(caller: PreferenceFragmentCompat, pref: Preference): Boolean { val screenInfo = Screen( - fragmentClass = pref.fragment, + fragmentClass = pref.fragment!!, screenTitle = pref.title?.toString() ) @@ -93,7 +93,7 @@ class SettingsFragment : Fragment2(R.layout.settings_fragment), } val fragment = childFragmentManager.fragmentFactory - .instantiate(this::class.java.classLoader!!, pref.fragment) + .instantiate(this::class.java.classLoader!!, pref.fragment!!) .apply { arguments = args setTargetFragment(caller, 0) diff --git a/build.gradle b/build.gradle deleted file mode 100644 index 7d7add33..00000000 --- a/build.gradle +++ /dev/null @@ -1,54 +0,0 @@ -// Top-level build file where you can add configuration options common to all sub-projects/modules. -buildscript { - ext.buildConfig = [ - 'minSdk' : 26, - 'compileSdk': 33, - 'targetSdk' : 33, - - 'version' : [ - 'major': 2, - 'minor': 0, - 'patch': 0, - 'build': 0, - ], - ] - - ext.buildConfig.version['name'] = "${buildConfig.version.major}.${buildConfig.version.minor}.${buildConfig.version.patch}-rc${buildConfig.version.build}" - ext.buildConfig.version['code'] = buildConfig.version.major * 1000000 + buildConfig.version.minor * 10000 + buildConfig.version.patch * 100 + buildConfig.version.build - - ext.versions = [ - 'kotlin' : [ - 'core' : '1.6.10', - 'coroutines': '1.5.1' - ], - 'dagger' : [ - 'core': '2.43.2' - ], - 'androidx' : [ - 'navigation': '2.3.5' - ], - ] - - repositories { - google() - mavenCentral() - } - dependencies { - classpath 'com.android.tools.build:gradle:7.0.4' - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.7.10" - classpath "com.google.dagger:hilt-android-gradle-plugin:${versions.dagger.core}" - classpath "androidx.navigation:navigation-safe-args-gradle-plugin:${versions.androidx.navigation}" - classpath 'com.bugsnag:bugsnag-android-gradle-plugin:7.0.0' - } -} - -allprojects { - repositories { - google() - mavenCentral() - } -} - -task clean(type: Delete) { - delete rootProject.buildDir -} \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 00000000..dfe7f0f2 --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,24 @@ +buildscript { + repositories { + google() + mavenCentral() + } + dependencies { + classpath("com.android.tools.build:gradle:${Versions.Gradle.buildTools}") + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${Versions.Kotlin.core}") + classpath("com.google.dagger:hilt-android-gradle-plugin:${Versions.Dagger.core}") + classpath("androidx.navigation:navigation-safe-args-gradle-plugin:${Versions.AndroidX.Navigation.core}") + classpath("com.bugsnag:bugsnag-android-gradle-plugin:7.2.1") + } +} + +allprojects { + repositories { + google() + mavenCentral() + } +} + +tasks.register("clean").configure { + delete("build") +} \ No newline at end of file diff --git a/buildSrc/.gitignore b/buildSrc/.gitignore new file mode 100644 index 00000000..192221b4 --- /dev/null +++ b/buildSrc/.gitignore @@ -0,0 +1,2 @@ +.gradle/ +build/ \ No newline at end of file diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts new file mode 100644 index 00000000..264a8689 --- /dev/null +++ b/buildSrc/build.gradle.kts @@ -0,0 +1,14 @@ +plugins { + `kotlin-dsl` + `java-library` +} + +repositories { + google() + mavenCentral() +} +dependencies { + implementation("com.android.tools.build:gradle:7.2.1") + implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.10") + implementation("com.squareup:javapoet:1.13.0") +} \ No newline at end of file diff --git a/buildSrc/src/main/java/Dependencies.kt b/buildSrc/src/main/java/Dependencies.kt new file mode 100644 index 00000000..4e86be5e --- /dev/null +++ b/buildSrc/src/main/java/Dependencies.kt @@ -0,0 +1,131 @@ +import org.gradle.api.artifacts.Dependency +import org.gradle.api.artifacts.dsl.DependencyHandler +import org.gradle.kotlin.dsl.DependencyHandlerScope + +private fun DependencyHandler.implementation(dependencyNotation: Any): Dependency? = + add("implementation", dependencyNotation) + +private fun DependencyHandler.testImplementation(dependencyNotation: Any): Dependency? = + add("testImplementation", dependencyNotation) + +private fun DependencyHandler.kapt(dependencyNotation: Any): Dependency? = + add("kapt", dependencyNotation) + +private fun DependencyHandler.kaptTest(dependencyNotation: Any): Dependency? = + add("kaptTest", dependencyNotation) + +private fun DependencyHandler.androidTestImplementation(dependencyNotation: Any): Dependency? = + add("androidTestImplementation", dependencyNotation) + +private fun DependencyHandler.kaptAndroidTest(dependencyNotation: Any): Dependency? = + add("kaptAndroidTest", dependencyNotation) + +private fun DependencyHandler.`testRuntimeOnly`(dependencyNotation: Any): Dependency? = + add("testRuntimeOnly", dependencyNotation) + +private fun DependencyHandler.`debugImplementation`(dependencyNotation: Any): Dependency? = + add("debugImplementation", dependencyNotation) + +fun DependencyHandlerScope.addBaseKotlin() { + implementation("org.jetbrains.kotlin:kotlin-stdlib:${Versions.Kotlin.core}") + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:${Versions.Kotlin.coroutines}") + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:${Versions.Kotlin.coroutines}") + + testImplementation("org.jetbrains.kotlin:kotlin-reflect:${Versions.Kotlin.core}") + testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:${Versions.Kotlin.coroutines}") + + androidTestImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:${Versions.Kotlin.coroutines}") +// { +// // conflicts with mockito due to direct inclusion of byte buddy +// exclude("org.jetbrains.kotlinx", "kotlinx-coroutines-debug") +// } +} + +fun DependencyHandlerScope.addDagger() { + implementation("com.google.dagger:dagger:${Versions.Dagger.core}") + implementation("com.google.dagger:dagger-android:${Versions.Dagger.core}") + implementation("androidx.hilt:hilt-common:1.0.0") + + kapt("com.google.dagger:dagger-compiler:${Versions.Dagger.core}") + kapt("com.google.dagger:dagger-android-processor:${Versions.Dagger.core}") + + implementation("com.google.dagger:hilt-android:${Versions.Dagger.core}") + kapt("com.google.dagger:hilt-android-compiler:${Versions.Dagger.core}") + + testImplementation("com.google.dagger:hilt-android-testing:${Versions.Dagger.core}") + kaptTest("com.google.dagger:hilt-android-compiler:${Versions.Dagger.core}") + + androidTestImplementation("com.google.dagger:hilt-android-testing:${Versions.Dagger.core}") + kaptAndroidTest("com.google.dagger:hilt-android-compiler:${Versions.Dagger.core}") +} + +fun DependencyHandlerScope.addMoshi() { + implementation("com.squareup.moshi:moshi:${Versions.Moshi.core}") + implementation("com.squareup.moshi:moshi-adapters:${Versions.Moshi.core}") + kapt("com.squareup.moshi:moshi-kotlin-codegen:${Versions.Moshi.core}") +} + +fun DependencyHandlerScope.addOkio() { + implementation("com.squareup.okio:okio:3.1.0") +} + +fun DependencyHandlerScope.addNavigation() { + implementation("androidx.navigation:navigation-fragment-ktx:${Versions.AndroidX.Navigation.core}") + implementation("androidx.navigation:navigation-ui-ktx:${Versions.AndroidX.Navigation.core}") + androidTestImplementation("androidx.navigation:navigation-testing:${Versions.AndroidX.Navigation.core}") +} + +fun DependencyHandlerScope.addBaseWorkManager() { + implementation("androidx.work:work-runtime:${Versions.AndroidX.WorkManager.core}") + testImplementation("androidx.work:work-testing:${Versions.AndroidX.WorkManager.core}") + implementation("androidx.work:work-runtime-ktx:${Versions.AndroidX.WorkManager.core}") + implementation("androidx.hilt:hilt-work:1.0.0") +} + +fun DependencyHandlerScope.addBaseAndroid() { + implementation("androidx.core:core-ktx:1.8.0") + implementation("androidx.annotation:annotation:1.4.0") + implementation("androidx.collection:collection-ktx:1.2.0") + implementation("androidx.preference:preference-ktx:1.2.0") +} + +fun DependencyHandlerScope.addBaseAndroidUi() { + implementation("androidx.appcompat:appcompat:1.6.0-alpha04") + implementation("androidx.constraintlayout:constraintlayout:2.1.3") + implementation("androidx.fragment:fragment-ktx:1.4.1") + + implementation("androidx.activity:activity-ktx:1.5.0") + implementation("androidx.fragment:fragment-ktx:1.5.0") + + val lifecycleVers = "2.5.0" + implementation("androidx.lifecycle:lifecycle-extensions:2.2.0") + implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycleVers") + implementation("androidx.lifecycle:lifecycle-viewmodel-savedstate:$lifecycleVers") + implementation("androidx.lifecycle:lifecycle-common-java8:$lifecycleVers") + implementation("androidx.lifecycle:lifecycle-process:$lifecycleVers") + implementation("androidx.lifecycle:lifecycle-livedata-ktx:$lifecycleVers") +} + +fun DependencyHandlerScope.addTesting(junit: Boolean = true, instrumentation: Boolean = true) { + testImplementation("junit:junit:${Versions.Junit.legacy}") + + testImplementation("org.junit.vintage:junit-vintage-engine:${Versions.Junit.jupiter}") + testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:${Versions.Junit.jupiter}") + testImplementation("org.junit.jupiter:junit-jupiter-api:${Versions.Junit.jupiter}") + testImplementation("org.junit.jupiter:junit-jupiter-params:${Versions.Junit.jupiter}") + + testImplementation("androidx.test:core-ktx:${Versions.AndroidX.Testing.coreKtx}") + androidTestImplementation("androidx.test.ext:junit:1.1.3") + androidTestImplementation("androidx.test.espresso:espresso-core:3.4.0") + + testImplementation("io.mockk:mockk:${Versions.Mockk.core}") + androidTestImplementation("io.mockk:mockk-android:${Versions.Mockk.android}") + + testImplementation("io.kotest:kotest-runner-junit5:${Versions.Kotest.core}") + testImplementation("io.kotest:kotest-assertions-core-jvm:${Versions.Kotest.core}") + testImplementation("io.kotest:kotest-property-jvm:${Versions.Kotest.core}") + androidTestImplementation("io.kotest:kotest-assertions-core-jvm:${Versions.Kotest.core}") + androidTestImplementation("io.kotest:kotest-property-jvm:${Versions.Kotest.core}") + + debugImplementation("androidx.fragment:fragment-testing:1.4.1") +} \ No newline at end of file diff --git a/buildSrc/src/main/java/ProjectConfig.kt b/buildSrc/src/main/java/ProjectConfig.kt new file mode 100644 index 00000000..71184bce --- /dev/null +++ b/buildSrc/src/main/java/ProjectConfig.kt @@ -0,0 +1,122 @@ +import com.android.build.gradle.LibraryExtension +import org.gradle.api.Action +import org.gradle.api.JavaVersion +import java.io.File +import java.io.FileInputStream +import java.time.Instant +import java.util.* + +object ProjectConfig { + const val packageName = "eu.darken.capod" + + const val minSdk = 26 + const val compileSdk = 33 + const val targetSdk = 33 + + object Version { + const val major = 2 + const val minor = 0 + const val patch = 0 + const val build = 0 + + const val name = "${major}.${minor}.${patch}-rc${build}" + const val code = major * 1000000 + minor * 10000 + patch * 100 + build + } +} + +fun lastCommitHash(): String = Runtime.getRuntime().exec("git rev-parse --short HEAD").let { process -> + process.waitFor() + val output = process.inputStream.use { input -> + input.bufferedReader().use { + it.readText() + } + } + process.destroy() + output.trim() +} + +fun buildTime(): Instant = Instant.now() + +/** + * Configures the [kotlinOptions][org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptions] extension. + */ +private fun LibraryExtension.kotlinOptions(configure: Action): Unit = + (this as org.gradle.api.plugins.ExtensionAware).extensions.configure("kotlinOptions", configure) + +fun LibraryExtension.setupLibraryDefaults() { + compileSdk = ProjectConfig.compileSdk + + defaultConfig { + minSdk = ProjectConfig.minSdk + targetSdk = ProjectConfig.targetSdk + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + consumerProguardFiles("consumer-rules.pro") + } + + buildTypes { + release { + isMinifyEnabled = false + proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") + } + } + + compileOptions { + isCoreLibraryDesugaringEnabled = true + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } + + kotlinOptions { + jvmTarget = "1.8" + freeCompilerArgs = freeCompilerArgs + listOf( + "-Xopt-in=kotlinx.coroutines.ExperimentalCoroutinesApi", + "-Xopt-in=kotlinx.coroutines.FlowPreview", + "-Xopt-in=kotlin.time.ExperimentalTime", + "-Xopt-in=kotlin.RequiresOptIn" + ) + } + + packagingOptions { + resources.excludes += "DebugProbesKt.bin" + } +} + +fun com.android.build.api.dsl.SigningConfig.setupCredentials( + signingPropsPath: File? = null +) { + + val keyStoreFromEnv = System.getenv("STORE_PATH")?.let { File(it) } + + if (keyStoreFromEnv?.exists() == true) { + println("Using signing data from environment variables.") + storeFile = keyStoreFromEnv + storePassword = System.getenv("STORE_PASSWORD") + keyAlias = System.getenv("KEY_ALIAS") + keyPassword = System.getenv("KEY_PASSWORD") + } else { + println("Using signing data from properties file.") + val props = Properties().apply { + signingPropsPath?.takeIf { it.canRead() }?.let { load(FileInputStream(it)) } + } + + val keyStorePath = props.getProperty("release.storePath")?.let { File(it) } + + if (keyStorePath?.exists() == true) { + storeFile = keyStorePath + storePassword = props.getProperty("release.storePassword") + keyAlias = props.getProperty("release.keyAlias") + keyPassword = props.getProperty("release.keyPassword") + } + } +} + +fun getBugSnagApiKey( + propertiesPath: File? +): String? { + val bugsnagProps = Properties().apply { + propertiesPath?.takeIf { it.canRead() }?.let { load(FileInputStream(it)) } + } + + return System.getenv("BUGSNAG_API_KEY") ?: bugsnagProps.getProperty("bugsnag.apikey") +} \ No newline at end of file diff --git a/buildSrc/src/main/java/Versions.kt b/buildSrc/src/main/java/Versions.kt new file mode 100644 index 00000000..2c54f814 --- /dev/null +++ b/buildSrc/src/main/java/Versions.kt @@ -0,0 +1,52 @@ +object Versions { + object Gradle { + const val buildTools = "7.1.2" + } + + object Kotlin { + const val core = "1.7.0" + const val coroutines = "1.6.2" + } + + object Dokka { + const val core = "1.6.21" + } + + object Dagger { + const val core = "2.42" + } + + object Moshi { + const val core = "1.13.0" + } + + object AndroidX { + const val core = "" + + object Navigation { + const val core = "2.5.0" + } + + object Testing { + const val coreKtx = "1.4.0" + } + + object WorkManager { + const val core = "2.7.1" + } + } + + object Junit { + const val legacy = "4.13.2" + const val jupiter = "5.7.1" + } + + object Mockk { + const val core = "1.12.4" + const val android = "1.12.4" + } + + object Kotest { + const val core = "4.6.4" + } +} diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 516b361d..c2314a5a 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Thu May 13 21:51:43 CEST 2021 +#Sat Aug 27 21:32:28 CEST 2022 distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip distributionPath=wrapper/dists zipStorePath=wrapper/dists zipStoreBase=GRADLE_USER_HOME