diff --git a/app/build.gradle.kts b/app/build.gradle.kts index a54a7261..5a6eeb89 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -7,9 +7,9 @@ plugins { kotlin("android") kotlin("kapt") id("kotlin-parcelize") - id("io.gitlab.arturbosch.detekt") version Dependencies.Versions.detekt - id("de.mannodermaus.android-junit5") - id("com.github.ben-manes.versions") version Dependencies.Versions.dependencyUpdates + id(Plugins.detekt) version Plugins.Versions.detekt + id(Plugins.androidJunit5) + id(Plugins.dependencyUpdates) version Plugins.Versions.dependencyUpdates } detekt { @@ -103,82 +103,66 @@ android { dependencies { - // Add implementation functions for build flavors - val libreImplementation by configurations val proprietaryImplementation by configurations // Kotlin - implementation(Dependencies.Kotlin.coroutinesCore) - implementation(Dependencies.Kotlin.coroutinesAndroid) + implementation(libs.bundles.coroutines) // Core - implementation(Dependencies.Core.koinAndroid) - implementation(Dependencies.Core.appCompat) - implementation(Dependencies.Core.androidx) - implementation(Dependencies.Core.activity) - implementation(Dependencies.Core.fragment) - implementation(Dependencies.Core.exoPlayer) + implementation(libs.koin) + implementation(libs.androidx.core) + implementation(libs.androidx.appcompat) + implementation(libs.androidx.activity) + implementation(libs.androidx.fragment) + coreLibraryDesugaring(libs.androiddesugarlibs) // Lifecycle - implementation(Dependencies.Lifecycle.viewModel) - implementation(Dependencies.Lifecycle.liveData) - implementation(Dependencies.Lifecycle.runtime) - implementation(Dependencies.Lifecycle.common) - implementation(Dependencies.Lifecycle.process) + implementation(libs.bundles.androidx.lifecycle) // UI - implementation(Dependencies.UI.constraintLayout) - implementation(Dependencies.UI.material) - implementation(Dependencies.UI.webkitX) - implementation(Dependencies.UI.exoPlayer) - implementation(Dependencies.UI.modernAndroidPreferences) - - // Room - implementation(Dependencies.Room.runtime) - kapt(Dependencies.Room.compiler) + implementation(libs.google.material) + implementation(libs.androidx.constraintlayout) + implementation(libs.androidx.webkit) + implementation(libs.modernandroidpreferences) // Network val sdkVersion = findProperty("sdk.version")?.toString() - implementation(Dependencies.Network.jellyfinSdk) { + implementation(libs.jellyfin.sdk) { // Change version if desired when (sdkVersion) { - "local" -> version { strictly(Dependencies.Versions.jellyfinSdkLocal) } - "snapshot" -> version { strictly(Dependencies.Versions.jellyfinSdkSnapshot) } - "unstable-snapshot" -> version { strictly(Dependencies.Versions.jellyfinSdkSnapshotUnstable) } + "local" -> version { strictly(JellyfinSdk.LOCAL) } + "snapshot" -> version { strictly(JellyfinSdk.SNAPSHOT) } + "unstable-snapshot" -> version { strictly(JellyfinSdk.SNAPSHOT_UNSTABLE) } } } - implementation(Dependencies.Network.okHttp) - implementation(Dependencies.Network.coil) - implementation(Dependencies.Network.exoPlayerHLS) - - // Cast - implementation(Dependencies.Cast.mediaRouter) - proprietaryImplementation(Dependencies.Cast.exoPlayerCastExtension) - proprietaryImplementation(Dependencies.Cast.playServicesCast) - proprietaryImplementation(Dependencies.Cast.playServicesCastFramework) + implementation(libs.okhttp) + implementation(libs.coil) // Media - implementation(Dependencies.Media.media) - implementation(Dependencies.Media.exoPlayerMediaSession) + implementation(libs.androidx.media) + implementation(libs.androidx.mediarouter) + implementation(libs.bundles.exoplayer) + @Suppress("UnstableApiUsage") + proprietaryImplementation(libs.exoplayer.cast) + @Suppress("UnstableApiUsage") + proprietaryImplementation(libs.bundles.playservices) - // Health - implementation(Dependencies.Health.timber) - debugImplementation(Dependencies.Health.leakCanary) - debugImplementation(Dependencies.Health.redScreenOfDeath) - releaseImplementation(Dependencies.Health.redScreenOfDeathNoOp) + // Room + implementation(libs.bundles.androidx.room) + kapt(libs.androidx.room.compiler) + + // Monitoring + implementation(libs.timber) + debugImplementation(libs.leakcanary) + debugImplementation(libs.redscreenofdeath.impl) + releaseImplementation(libs.redscreenofdeath.noop) // Testing - testImplementation(Dependencies.Health.junit) - testRuntimeOnly(Dependencies.Health.junitEngine) - testImplementation(Dependencies.Health.kotestAssertions) - testImplementation(Dependencies.Health.kotestProperty) - testImplementation(Dependencies.Health.kotestRunner) - testImplementation(Dependencies.Health.mockk) - androidTestImplementation(Dependencies.Health.androidXRunner) - androidTestImplementation(Dependencies.Health.androidXEspresso) - - // Desugaring - coreLibraryDesugaring(Dependencies.Health.androidDesugarLibs) + testImplementation(libs.junit.api) + testRuntimeOnly(libs.junit.engine) + testImplementation(libs.bundles.kotest) + testImplementation(libs.mockk) + androidTestImplementation(libs.bundles.androidx.test) } tasks { diff --git a/build.gradle.kts b/build.gradle.kts index 49b5fba5..d9d27c52 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -19,13 +19,13 @@ allprojects { google() mavenLocal { content { - includeVersionByRegex(Dependencies.Groups.jellyfin, ".*", Dependencies.Versions.jellyfinSdkLocal) + includeVersionByRegex(JellyfinSdk.GROUP, ".*", JellyfinSdk.LOCAL) } } maven("https://s01.oss.sonatype.org/content/repositories/snapshots/") { content { - includeVersionByRegex(Dependencies.Groups.jellyfin, ".*", Dependencies.Versions.jellyfinSdkSnapshot) - includeVersionByRegex(Dependencies.Groups.jellyfin, ".*", Dependencies.Versions.jellyfinSdkSnapshotUnstable) + includeVersionByRegex(JellyfinSdk.GROUP, ".*", JellyfinSdk.SNAPSHOT) + includeVersionByRegex(JellyfinSdk.GROUP, ".*", JellyfinSdk.SNAPSHOT_UNSTABLE) } } } diff --git a/buildSrc/src/main/kotlin/Dependencies.kt b/buildSrc/src/main/kotlin/Dependencies.kt deleted file mode 100644 index 1f80fd69..00000000 --- a/buildSrc/src/main/kotlin/Dependencies.kt +++ /dev/null @@ -1,141 +0,0 @@ -object Dependencies { - object Versions { - // Gradle plugins - const val dependencyUpdates = "0.39.0" - const val detekt = "1.17.1" - - // KotlinX - const val coroutines = "1.5.1" - - // Core - const val koin = "3.1.2" - const val appCompat = "1.3.1" - const val androidxCore = "1.6.0" - const val activity = "1.3.0" - const val fragment = "1.3.6" - const val exoPlayer = "2.14.2" - - // Lifecycle - const val lifecycleExtensions = "2.3.1" - - // UI - const val constraintLayout = "2.1.0" - const val material = "1.4.0" - const val webkitX = "1.4.0" - const val modernAndroidPreferences = "2.1.0" - - // Room - const val room = "2.3.0" - - // Network - const val jellyfinSdk = "1.0.1" - const val jellyfinSdkLocal = "latest-SNAPSHOT" - const val jellyfinSdkSnapshot = "master-SNAPSHOT" - const val jellyfinSdkSnapshotUnstable = "openapi-unstable-SNAPSHOT" - const val okHttp = "4.9.1" - const val coil = "1.3.1" - - // Cast - const val mediaRouter = "1.2.4" - const val playServicesCast = "20.0.0" - - // Media - const val media = "1.4.0" - - // Health - const val timber = "4.7.1" - const val leakCanary = "2.7" - const val redScreenOfDeath = "0.1.3" - const val junit = "5.7.2" - const val kotest = "4.6.1" - const val mockk = "1.12.0" - const val androidXRunner = "1.4.0" - const val androidXEspresso = "3.4.0" - const val androidDesugarLibs = "1.1.5" - } - - object Groups { - const val jellyfin = "org.jellyfin.sdk" - } - - object Kotlin { - val coroutinesCore = kotlinx("coroutines-core", Versions.coroutines) - val coroutinesAndroid = kotlinx("coroutines-android", Versions.coroutines) - } - - object Core { - const val koinAndroid = "io.insert-koin:koin-android:${Versions.koin}" - val appCompat = androidx("appcompat", Versions.appCompat) - val androidx = androidxKtx("core", Versions.androidxCore) - val activity = androidxKtx("activity", Versions.activity) - val fragment = androidxKtx("fragment", Versions.fragment) - val exoPlayer = exoPlayer("core") - } - - object Lifecycle { - val viewModel = lifecycle("viewmodel-ktx") - val liveData = lifecycle("livedata-ktx") - val runtime = lifecycle("runtime-ktx") - val common = lifecycle("common-java8") - val process = lifecycle("process") - } - - object UI { - val constraintLayout = androidx("constraintlayout", Versions.constraintLayout) - const val material = "com.google.android.material:material:${Versions.material}" - val webkitX = androidx("webkit", Versions.webkitX) - val exoPlayer = exoPlayer("ui") - const val modernAndroidPreferences = "de.maxr1998:modernandroidpreferences:${Versions.modernAndroidPreferences}" - } - - object Room { - val runtime = room("runtime") - val compiler = room("compiler") - } - - object Network { - const val jellyfinSdk = "${Groups.jellyfin}:jellyfin-platform-android:${Versions.jellyfinSdk}" - const val okHttp = "com.squareup.okhttp3:okhttp:${Versions.okHttp}" - const val coil = "io.coil-kt:coil-base:${Versions.coil}" - val exoPlayerHLS = exoPlayer("hls") - } - - object Cast { - val mediaRouter = androidx("mediarouter", Versions.mediaRouter) - const val exoPlayerCastExtension = "com.google.android.exoplayer:extension-cast:${Versions.exoPlayer}" - const val playServicesCast = "com.google.android.gms:play-services-cast:${Versions.playServicesCast}" - const val playServicesCastFramework = "com.google.android.gms:play-services-cast-framework:${Versions.playServicesCast}" - } - - object Media { - val media = androidx("media", Versions.media) - var exoPlayerMediaSession = "com.google.android.exoplayer:extension-mediasession:${Versions.exoPlayer}" - } - - /** - * Includes logging, debugging, testing and desugaring - */ - object Health { - const val timber = "com.jakewharton.timber:timber:${Versions.timber}" - const val leakCanary = "com.squareup.leakcanary:leakcanary-android:${Versions.leakCanary}" - const val redScreenOfDeath = "com.mlegy.redscreenofdeath:red-screen-of-death:${Versions.redScreenOfDeath}" - const val redScreenOfDeathNoOp = "com.mlegy.redscreenofdeath:red-screen-of-death-no-op:${Versions.redScreenOfDeath}" - const val junit = "org.junit.jupiter:junit-jupiter-api:${Versions.junit}" - const val junitEngine = "org.junit.jupiter:junit-jupiter-engine:${Versions.junit}" - const val kotestAssertions = "io.kotest:kotest-assertions-core-jvm:${Versions.kotest}" - const val kotestProperty = "io.kotest:kotest-property-jvm:${Versions.kotest}" - const val kotestRunner = "io.kotest:kotest-runner-junit5-jvm:${Versions.kotest}" - const val mockk = "io.mockk:mockk:${Versions.mockk}" - const val androidXRunner = "androidx.test:runner:${Versions.androidXRunner}" - const val androidXEspresso = "androidx.test.espresso:espresso-core:${Versions.androidXEspresso}" - const val androidDesugarLibs = "com.android.tools:desugar_jdk_libs:${Versions.androidDesugarLibs}" - } - - // Helpers - private fun androidx(module: String, version: String) = "androidx.$module:$module:$version" - private fun androidxKtx(module: String, version: String) = "androidx.$module:$module-ktx:$version" - private fun kotlinx(module: String, version: String) = "org.jetbrains.kotlinx:kotlinx-$module:$version" - private fun lifecycle(module: String) = "androidx.lifecycle:lifecycle-$module:${Versions.lifecycleExtensions}" - private fun room(module: String) = "androidx.room:room-$module:${Versions.room}" - private fun exoPlayer(module: String) = "com.google.android.exoplayer:exoplayer-$module:${Versions.exoPlayer}" -} diff --git a/buildSrc/src/main/kotlin/JellyfinSdk.kt b/buildSrc/src/main/kotlin/JellyfinSdk.kt new file mode 100644 index 00000000..e4118ea4 --- /dev/null +++ b/buildSrc/src/main/kotlin/JellyfinSdk.kt @@ -0,0 +1,7 @@ +object JellyfinSdk { + const val GROUP = "org.jellyfin.sdk" + + const val LOCAL = "latest-SNAPSHOT" + const val SNAPSHOT = "master-SNAPSHOT" + const val SNAPSHOT_UNSTABLE = "openapi-unstable-SNAPSHOT" +} diff --git a/buildSrc/src/main/kotlin/Plugins.kt b/buildSrc/src/main/kotlin/Plugins.kt new file mode 100644 index 00000000..a28f3ace --- /dev/null +++ b/buildSrc/src/main/kotlin/Plugins.kt @@ -0,0 +1,10 @@ +object Plugins { + object Versions { + const val dependencyUpdates = "0.39.0" + const val detekt = "1.17.1" + } + + const val detekt = "io.gitlab.arturbosch.detekt" + const val androidJunit5 = "de.mannodermaus.android-junit5" + const val dependencyUpdates = "com.github.ben-manes.versions" +} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml new file mode 100644 index 00000000..e4cd287e --- /dev/null +++ b/gradle/libs.versions.toml @@ -0,0 +1,132 @@ +[versions] +# KotlinX +coroutines = "1.5.1" + +# Core +koin = "3.1.2" +androidx-core = "1.6.0" +androidx-appcompat = "1.3.1" +androidx-activity = "1.3.0" +androidx-fragment = "1.3.6" +androiddesugarlibs = "1.1.5" + +# Lifecycle extensions +androidx-lifecycle = "2.3.1" + +# UI +androidx-constraintlayout = "2.1.0" +google-material = "1.4.0" +androidx-webkit = "1.4.0" +modernandroidpreferences = "2.1.0" + +# Network +jellyfin-sdk = "1.0.1" +okhttp = "4.9.1" +coil = "1.3.1" + +# Media +androidx-media = "1.4.0" +androidx-mediarouter = "1.2.4" +exoplayer = "2.14.2" +playservices = "20.0.0" + +# Room +androidx-room = "2.3.0" + +# Monitoring +timber = "4.7.1" +leakcanary = "2.7" +redscreenofdeath = "0.1.3" + +# Testing +junit = "5.7.2" +kotest = "4.6.1" +mockk = "1.12.0" +androidx-test-runner = "1.4.0" +androidx-test-espresso = "3.4.0" + +[libraries] +# KotlinX +coroutines-core = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-core", version.ref = "coroutines" } +coroutines-android = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-android", version.ref = "coroutines" } + +# Core +koin = { group = "io.insert-koin", name = "koin-android", version.ref = "koin" } +androidx-core = { group = "androidx.core", name = "core-ktx", version.ref = "androidx-core" } +androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "androidx-appcompat" } +androidx-activity = { group = "androidx.activity", name = "activity-ktx", version.ref = "androidx-activity" } +androidx-fragment = { group = "androidx.fragment", name = "fragment-ktx", version.ref = "androidx-fragment" } +androiddesugarlibs = { group = "com.android.tools", name = "desugar_jdk_libs", version.ref = "androiddesugarlibs" } + +# Lifecycle Extensions +androidx-lifecycle-viewmodel = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-ktx", version.ref = "androidx-lifecycle" } +androidx-lifecycle-livedata = { group = "androidx.lifecycle", name = "lifecycle-livedata-ktx", version.ref = "androidx-lifecycle" } +androidx-lifecycle-runtime = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version.ref = "androidx-lifecycle" } +androidx-lifecycle-common = { group = "androidx.lifecycle", name = "lifecycle-common-java8", version.ref = "androidx-lifecycle" } +androidx-lifecycle-process = { group = "androidx.lifecycle", name = "lifecycle-process", version.ref = "androidx-lifecycle" } + +# UI +google-material = { group = "com.google.android.material", name = "material", version.ref = "google-material" } +androidx-constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "androidx-constraintlayout" } +androidx-webkit = { group = "androidx.webkit", name = "webkit", version.ref = "androidx-webkit" } +modernandroidpreferences = { group = "de.maxr1998", name = "modernandroidpreferences", version.ref = "modernandroidpreferences" } + +# Network +jellyfin-sdk = { group = "org.jellyfin.sdk", name = "jellyfin-platform-android", version.ref = "jellyfin-sdk" } +okhttp = { group = "com.squareup.okhttp3", name = "okhttp", version.ref = "okhttp" } +coil = { group = "io.coil-kt", name = "coil-base", version.ref = "coil" } + +# Media +androidx-media = { group = "androidx.media", name = "media", version.ref = "androidx-media" } +androidx-mediarouter = { group = "androidx.mediarouter", name = "mediarouter", version.ref = "androidx-mediarouter" } +exoplayer-core = { group = "com.google.android.exoplayer", name = "exoplayer-core", version.ref = "exoplayer" } +exoplayer-ui = { group = "com.google.android.exoplayer", name = "exoplayer-ui", version.ref = "exoplayer" } +exoplayer-mediaSession = { group = "com.google.android.exoplayer", name = "extension-mediasession", version.ref = "exoplayer" } +exoplayer-hls = { group = "com.google.android.exoplayer", name = "exoplayer-hls", version.ref = "exoplayer" } +exoplayer-cast = { group = "com.google.android.exoplayer", name = "extension-cast", version.ref = "exoplayer" } +playservices-cast = { group = "com.google.android.gms", name = "play-services-cast", version.ref = "playservices" } +playservices-castframework = { group = "com.google.android.gms", name = "play-services-cast-framework", version.ref = "playservices" } + +# Room +androidx-room-runtime = { group = "androidx.room", name = "room-runtime", version.ref = "androidx-room" } +androidx-room-ktx = { group = "androidx.room", name = "room-ktx", version.ref = "androidx-room" } +androidx-room-compiler = { group = "androidx.room", name = "room-compiler", version.ref = "androidx-room" } + +# Monitoring +timber = { group = "com.jakewharton.timber", name = "timber", version.ref = "timber" } +leakcanary = { group = "com.squareup.leakcanary", name = "leakcanary-android", version.ref = "leakcanary" } +redscreenofdeath-impl = { group = "com.mlegy.redscreenofdeath", name = "red-screen-of-death", version.ref = "redscreenofdeath" } +redscreenofdeath-noop = { group = "com.mlegy.redscreenofdeath", name = "red-screen-of-death-no-op", version.ref = "redscreenofdeath" } + +# Testing +junit-api = { group = "org.junit.jupiter", name = "junit-jupiter-api", version.ref = "junit" } +junit-engine = { group = "org.junit.jupiter", name = "junit-jupiter-engine", version.ref = "junit" } +kotest-runner = { group = "io.kotest", name = "kotest-runner-junit5-jvm", version.ref = "kotest" } +kotest-assertions = { group = "io.kotest", name = "kotest-assertions-core-jvm", version.ref = "kotest" } +kotest-property = { group = "io.kotest", name = "kotest-property-jvm", version.ref = "kotest" } +mockk = { group = "io.mockk", name = "mockk", version.ref = "mockk" } +androidx-test-runner = { group = "androidx.test", name = "runner", version.ref = "androidx-test-runner" } +androidx-test-espresso = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "androidx-test-espresso" } + +[bundles] +coroutines = ["coroutines-core", "coroutines-android"] +androidx-lifecycle = [ + "androidx-lifecycle-viewmodel", + "androidx-lifecycle-livedata", + "androidx-lifecycle-runtime", + "androidx-lifecycle-common", + "androidx-lifecycle-process", +] +exoplayer = [ + "exoplayer-core", + "exoplayer-ui", + "exoplayer-mediaSession", + "exoplayer-hls", +] +playservices = [ + "playservices-cast", + "playservices-castframework", +] +androidx-room = ["androidx-room-runtime", "androidx-room-ktx"] +kotest = ["kotest-runner", "kotest-assertions", "kotest-property"] +androidx-test = ["androidx-test-runner", "androidx-test-espresso"] diff --git a/settings.gradle.kts b/settings.gradle.kts index 8129c838..d2e82e23 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,3 +1,5 @@ +enableFeaturePreview("VERSION_CATALOGS") + include(":app") pluginManagement {