diff --git a/.idea/compiler.xml b/.idea/compiler.xml index b589d56e9..b86273d94 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml index e805548aa..bb4493707 100644 --- a/.idea/kotlinc.xml +++ b/.idea/kotlinc.xml @@ -1,6 +1,6 @@ - \ No newline at end of file diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts index 06cb3a205..3c014cc40 100644 --- a/android/app/build.gradle.kts +++ b/android/app/build.gradle.kts @@ -11,12 +11,12 @@ plugins { android { - compileSdk = 34 + compileSdk = 35 defaultConfig { applicationId = "com.simplecityapps.shuttle" minSdk = 21 - targetSdk = 34 + targetSdk = 35 versionName = versionName() versionCode = versionCode() vectorDrawables.useSupportLibrary = true @@ -95,7 +95,7 @@ android { implementation(project(":android:networking")) // TagLib - implementation("com.github.timusus:ktaglib:1.4.1") + implementation(libs.timusus.ktaglib) // Shuttle implementation(project(":android:data")) @@ -121,126 +121,126 @@ android { implementation(project(":android:trial")) // RecyclerView FastScroll - implementation("com.github.timusus:RecyclerView-FastScroll:dev-SNAPSHOT") + implementation(libs.timusus.recyclerViewFastScroll) // AppCompat - implementation("androidx.appcompat:appcompat:1.6.1") + implementation(libs.androidx.appcompat) // Material - implementation("com.google.android.material:material:1.10.0") + implementation(libs.google.material) // Constraint Layout - implementation("androidx.constraintlayout:constraintlayout:2.1.4") + implementation(libs.androidx.constraintlayout) // Android Arch - implementation("androidx.lifecycle:lifecycle-extensions:2.2.0") + implementation(libs.androidx.lifecycle.extensions) // AndroidX Navigation - implementation("androidx.navigation:navigation-fragment-ktx:2.7.5") - implementation("androidx.navigation:navigation-ui-ktx:2.7.5") + implementation(libs.androidx.navigation.fragment.ktx) + implementation(libs.androidx.navigation.ui.ktx) // Hilt - implementation("com.google.dagger:hilt-android:2.48.1") - ksp("com.google.dagger:hilt-compiler:2.48.1") + implementation(libs.hilt) + ksp(libs.hilt.compiler) - androidTestImplementation("com.google.dagger:hilt-android-testing:2.48.1") - kspAndroidTest("com.google.dagger:hilt-android-compiler:2.48.1") + androidTestImplementation(libs.hilt.android.testing) + kspAndroidTest(libs.hilt.compiler) // Leak Canary - debugImplementation("com.squareup.leakcanary:leakcanary-android:2.10") + debugImplementation(libs.leakcanary.android) // ViewPager 2 - implementation("androidx.viewpager2:viewpager2:1.1.0-beta02") + implementation(libs.androidx.viewpager2) // ViewPager Circle Indicator - implementation("me.relex:circleindicator:2.1.4") + implementation(libs.relex.circleindicator) // AndroidX Media - implementation("androidx.media:media:1.6.0") + implementation(libs.androidx.media) // AndroidX Preference - implementation("androidx.preference:preference-ktx:1.2.1") + implementation(libs.androidx.preference.ktx) // ChromeCast - implementation("com.google.android.gms:play-services-cast-framework:21.3.0") + implementation(libs.google.play.services.cast.framework) // NanoHttp - implementation("org.nanohttpd:nanohttpd-webserver:2.3.1") + implementation(libs.nanohttpd.webserver) // Moshi - ksp("com.squareup.moshi:moshi-kotlin-codegen:1.15.0") + ksp(libs.moshi.kotlinCodegen) // AndroidX Lifecycle - implementation("androidx.lifecycle:lifecycle-common-java8:2.6.2") + implementation(libs.androidx.lifecycle.common.java8) // Noise - implementation("com.github.paramsen:noise:2.0.0") + implementation(libs.paramsen.noise) // MpAndroidChart - implementation("com.github.PhilJay:MPAndroidChart:3.1.0") + implementation(libs.philjay.mpAndroidChart) // AndroidX Lifecycle - implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.2") + implementation(libs.androidx.lifecycle.runtime.ktx) // ExoPlayer - implementation("com.github.timusus.exoplayer:exoplayer-core:2.14.2-shuttle") - implementation("com.github.timusus.exoplayer:exoplayer-hls:2.14.2-shuttle") + implementation(libs.exoplayer.core) + implementation(libs.exoplayer.hls) - implementation("androidx.drawerlayout:drawerlayout:1.2.0") + implementation(libs.androidx.drawerlayout) // New fragment manager - implementation("androidx.fragment:fragment-ktx:1.6.2") + implementation(libs.androidx.fragment.ktx) // Glide - implementation("com.github.bumptech.glide:glide:4.16.0") - implementation("com.github.bumptech.glide:okhttp3-integration:4.16.0") + implementation(libs.glide) + implementation(libs.glide.okhttp3Integration) implementation("com.github.bumptech.glide:recyclerview-integration:4.14.2") { // Excludes the support library because it's already included by Glide. isTransitive = false } // About Libraries - implementation("com.mikepenz:aboutlibraries-core:10.9.2") + implementation(libs.mikepenz.aboutlibrariesCore) // Billing - implementation("com.android.billingclient:billing-ktx:6.1.0") + implementation(libs.billingclient.billingKtx) // Play Core (review api) - implementation("com.google.android.play:core:1.10.3") - implementation("com.google.android.play:core-ktx:1.8.1") + implementation(libs.google.review) + implementation(libs.google.review.ktx) // Semantic versioning - implementation("com.vdurmont:semver4j:3.1.0") + implementation(libs.vdurmont.semver4j) - implementation("com.microsoft.design:fluent-system-icons:1.1.137@aar") + implementation(libs.design.fluentSystemIcons) // KotlinX DateTime - implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.4.1") + implementation(libs.kotlinx.datetime) // Core Library Desugaring - Required for KotlinX DateTime on API < 27 - coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.0.4") + coreLibraryDesugaring(libs.tools.desugar.jdk.libs) // Firebase - implementation(platform("com.google.firebase:firebase-bom:32.6.0")) - implementation("com.google.firebase:firebase-crashlytics") + implementation(platform(libs.firebase.bom)) + implementation(libs.firebase.crashlytics) // Testing - androidTestImplementation("androidx.test:runner:1.5.2") - androidTestImplementation("androidx.test:rules:1.5.0") - androidTestImplementation("androidx.test:core-ktx:1.5.0") - androidTestImplementation("org.hamcrest:hamcrest-library:1.3") + androidTestImplementation(libs.androidx.runner) + androidTestImplementation(libs.androidx.rules) + androidTestImplementation(libs.androidx.core.ktx) + androidTestImplementation(libs.hamcrest.library) // Remote config implementation(project(":android:remote-config")) - testImplementation("junit:junit:4.13.2") + testImplementation(libs.junit) // WorkManager - implementation("androidx.work:work-runtime-ktx:2.9.0-rc01") - implementation("androidx.hilt:hilt-work:1.1.0") - ksp("androidx.hilt:hilt-compiler:1.1.0") + implementation(libs.androidx.work.runtime.ktx) + implementation(libs.androidx.hilt.work) + ksp(libs.androidx.hilt.compiler) } buildFeatures.buildConfig = true diff --git a/android/app/src/main/java/com/simplecityapps/shuttle/ui/screens/library/albumartists/AlbumArtistBinder.kt b/android/app/src/main/java/com/simplecityapps/shuttle/ui/screens/library/albumartists/AlbumArtistBinder.kt index b8b7017d3..e4b981088 100644 --- a/android/app/src/main/java/com/simplecityapps/shuttle/ui/screens/library/albumartists/AlbumArtistBinder.kt +++ b/android/app/src/main/java/com/simplecityapps/shuttle/ui/screens/library/albumartists/AlbumArtistBinder.kt @@ -35,7 +35,7 @@ abstract class AlbumArtistBinder( } override fun getSectionName(): String? { - return albumArtist.groupKey.key?.firstOrNull()?.toUpperCase()?.toString() + return albumArtist.groupKey.key?.firstOrNull()?.uppercaseChar()?.toString() } override fun equals(other: Any?): Boolean { diff --git a/android/app/src/main/java/com/simplecityapps/shuttle/ui/screens/library/albumartists/detail/ExpandableAlbumBinder.kt b/android/app/src/main/java/com/simplecityapps/shuttle/ui/screens/library/albumartists/detail/ExpandableAlbumBinder.kt index 9a1a92e69..20b290af7 100644 --- a/android/app/src/main/java/com/simplecityapps/shuttle/ui/screens/library/albumartists/detail/ExpandableAlbumBinder.kt +++ b/android/app/src/main/java/com/simplecityapps/shuttle/ui/screens/library/albumartists/detail/ExpandableAlbumBinder.kt @@ -70,7 +70,7 @@ class ExpandableAlbumBinder( } override fun getSectionName(): String? { - return album.groupKey?.key?.firstOrNull()?.toString()?.toUpperCase(Locale.getDefault()) + return album.groupKey?.key?.firstOrNull()?.toString()?.uppercase(Locale.getDefault()) } override fun equals(other: Any?): Boolean { diff --git a/android/app/src/main/java/com/simplecityapps/shuttle/ui/screens/library/albums/AlbumBinder.kt b/android/app/src/main/java/com/simplecityapps/shuttle/ui/screens/library/albums/AlbumBinder.kt index 13da75edf..edc60d761 100644 --- a/android/app/src/main/java/com/simplecityapps/shuttle/ui/screens/library/albums/AlbumBinder.kt +++ b/android/app/src/main/java/com/simplecityapps/shuttle/ui/screens/library/albums/AlbumBinder.kt @@ -9,7 +9,7 @@ import com.simplecityapps.shuttle.ui.common.recyclerview.SectionViewBinder import java.util.* abstract class AlbumBinder( - val album: com.simplecityapps.shuttle.model.Album, + val album: Album, val imageLoader: ArtworkImageLoader, val listener: Listener? = null ) : ViewBinder, @@ -18,25 +18,25 @@ abstract class AlbumBinder( interface Listener { fun onAlbumClicked( - album: com.simplecityapps.shuttle.model.Album, + album: Album, viewHolder: ViewHolder ) fun onAlbumLongClicked( - album: com.simplecityapps.shuttle.model.Album, + album: Album, viewHolder: ViewHolder ) fun onOverflowClicked( view: View, - album: com.simplecityapps.shuttle.model.Album + album: Album ) {} fun onViewHolderCreated(holder: ViewHolder) {} } override fun getSectionName(): String? { - return album.groupKey?.key?.firstOrNull()?.toString()?.toUpperCase(Locale.getDefault()) + return album.groupKey?.key?.firstOrNull()?.toString()?.uppercase(Locale.getDefault()) } override fun equals(other: Any?): Boolean { diff --git a/android/app/src/main/java/com/simplecityapps/shuttle/ui/screens/library/albums/AlbumListPresenter.kt b/android/app/src/main/java/com/simplecityapps/shuttle/ui/screens/library/albums/AlbumListPresenter.kt index 812c283c9..74d2589a3 100644 --- a/android/app/src/main/java/com/simplecityapps/shuttle/ui/screens/library/albums/AlbumListPresenter.kt +++ b/android/app/src/main/java/com/simplecityapps/shuttle/ui/screens/library/albums/AlbumListPresenter.kt @@ -275,8 +275,8 @@ constructor( override fun getFastscrollPrefix(album: Album): String? { return when (sortPreferenceManager.sortOrderAlbumList) { - AlbumSortOrder.AlbumName -> album.groupKey?.key?.firstOrNull()?.toString()?.toUpperCase(Locale.getDefault()) - AlbumSortOrder.ArtistGroupKey -> album.groupKey?.albumArtistGroupKey?.key?.firstOrNull()?.toString()?.toUpperCase(Locale.getDefault()) + AlbumSortOrder.AlbumName -> album.groupKey?.key?.firstOrNull()?.toString()?.uppercase(Locale.getDefault()) + AlbumSortOrder.ArtistGroupKey -> album.groupKey?.albumArtistGroupKey?.key?.firstOrNull()?.toString()?.uppercase(Locale.getDefault()) AlbumSortOrder.Year -> album.year.toString() else -> null } diff --git a/android/app/src/main/java/com/simplecityapps/shuttle/ui/screens/library/songs/SongListPresenter.kt b/android/app/src/main/java/com/simplecityapps/shuttle/ui/screens/library/songs/SongListPresenter.kt index 289471167..2e1633456 100644 --- a/android/app/src/main/java/com/simplecityapps/shuttle/ui/screens/library/songs/SongListPresenter.kt +++ b/android/app/src/main/java/com/simplecityapps/shuttle/ui/screens/library/songs/SongListPresenter.kt @@ -219,8 +219,8 @@ constructor( override fun getFastscrollPrefix(song: Song): String? { return when (sortPreferenceManager.sortOrderSongList) { SongSortOrder.SongName -> song.name?.firstOrNull()?.toString() - SongSortOrder.ArtistGroupKey -> song.albumArtistGroupKey.key?.firstOrNull()?.toString()?.toUpperCase(Locale.getDefault()) - SongSortOrder.AlbumGroupKey -> song.albumGroupKey.key?.firstOrNull()?.toString()?.toUpperCase(Locale.getDefault()) + SongSortOrder.ArtistGroupKey -> song.albumArtistGroupKey.key?.firstOrNull()?.toString()?.uppercase(Locale.getDefault()) + SongSortOrder.AlbumGroupKey -> song.albumGroupKey.key?.firstOrNull()?.toString()?.uppercase(Locale.getDefault()) SongSortOrder.Year -> song.date?.year?.toString() else -> null } diff --git a/android/core/build.gradle b/android/core/build.gradle index 976b08979..b70d539e9 100644 --- a/android/core/build.gradle +++ b/android/core/build.gradle @@ -3,11 +3,11 @@ apply plugin: 'kotlin-android' apply plugin: 'com.google.devtools.ksp' android { - compileSdk 34 + compileSdk 35 defaultConfig { minSdkVersion 21 - targetSdkVersion 34 + targetSdkVersion 35 buildConfigField("String", "PROXY_ADDR", "\"192.168.0.14\"") buildConfigField("Integer", "PROXY_PORT", "8888") } @@ -40,52 +40,48 @@ dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) // AndroidX Preferences - implementation "androidx.preference:preference-ktx:1.2.1" + implementation libs.androidx.preference.ktx // OkHttp Logging Interceptor - api 'com.squareup.okhttp3:logging-interceptor:4.12.0' + api libs.okhttp3.loggingInterceptor // Kotlin Standard Library - api 'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.20' + api libs.kotlin.stdlib // Kotlin Extensions - api 'androidx.core:core-ktx:1.12.0' + api libs.androidx.core.ktx // AndroidX Annotations - api "androidx.annotation:annotation:1.7.0" + api libs.androidx.annotation // Hilt core - implementation 'com.google.dagger:hilt-android:2.48.1' - ksp 'com.google.dagger:hilt-compiler:2.48.1' + implementation libs.hilt + ksp libs.hilt.compiler // Timber - api 'com.jakewharton.timber:timber:4.7.1' + api libs.timber // Coroutines - api("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3") - api("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3") + api(libs.kotlinx.coroutinesCore) + api(libs.kotlinx.coroutinesAndroid) // OKHttp - implementation 'com.squareup.okhttp3:okhttp:4.12.0' + implementation libs.okhttp3.okhttp // Retrofit - implementation 'com.squareup.retrofit2:converter-moshi:2.10.0-SNAPSHOT' + implementation libs.retrofit2.converterMoshi // Moshi - implementation 'com.squareup.moshi:moshi:1.15.0' - implementation 'com.squareup.moshi:moshi-kotlin:1.15.0' - implementation 'com.squareup.moshi:moshi-adapters:1.15.0' + implementation libs.moshi + implementation libs.moshi.kotlin + implementation libs.moshi.adapters // Encrypted Shared Preferences - api 'androidx.security:security-crypto:1.1.0-alpha06' + api libs.androidx.security.crypto // Material Design Components - implementation 'com.google.android.material:material:1.10.0' + implementation libs.google.material // Phrase string formatting helper - api 'com.github.square:phrase:master-SNAPSHOT' + api libs.square.phrase } - -repositories { - mavenCentral() -} \ No newline at end of file diff --git a/android/data/build.gradle.kts b/android/data/build.gradle.kts index 8222cc0bf..7701c614a 100644 --- a/android/data/build.gradle.kts +++ b/android/data/build.gradle.kts @@ -5,7 +5,7 @@ plugins { } android { - compileSdk = 34 + compileSdk = 35 defaultConfig { minSdk = 21 @@ -22,6 +22,6 @@ android { } dependencies { - implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.4.1") + implementation(libs.kotlinx.datetime) } } diff --git a/android/data/src/main/kotlin/com/simplecityapps/shuttle/model/Album.kt b/android/data/src/main/kotlin/com/simplecityapps/shuttle/model/Album.kt index 9b250fc4b..dfc26871c 100644 --- a/android/data/src/main/kotlin/com/simplecityapps/shuttle/model/Album.kt +++ b/android/data/src/main/kotlin/com/simplecityapps/shuttle/model/Album.kt @@ -3,6 +3,7 @@ package com.simplecityapps.shuttle.model import android.os.Parcelable import com.simplecityapps.shuttle.parcel.InstantParceler import kotlinx.datetime.Instant +import kotlinx.parcelize.IgnoredOnParcel import kotlinx.parcelize.Parcelize import kotlinx.parcelize.TypeParceler @@ -21,17 +22,20 @@ data class Album( val groupKey: AlbumGroupKey?, val mediaProviders: List ) : Parcelable { - val friendlyArtistName: String? = - if (artists.isNotEmpty()) { - if (artists.size == 1) { - artists.first() + @IgnoredOnParcel + val friendlyArtistName: String? + by lazy { + if (artists.isNotEmpty()) { + if (artists.size == 1) { + artists.first() + } else { + artists.groupBy { it.lowercase().removeArticles() } + .map { map -> map.value.maxByOrNull { it.length } } + .joinToString(", ") + .ifEmpty { null } + } } else { - artists.groupBy { it.lowercase().removeArticles() } - .map { map -> map.value.maxByOrNull { it.length } } - .joinToString(", ") - .ifEmpty { null } + null } - } else { - null } } diff --git a/android/data/src/main/kotlin/com/simplecityapps/shuttle/model/AlbumArtist.kt b/android/data/src/main/kotlin/com/simplecityapps/shuttle/model/AlbumArtist.kt index 7d76675fc..98b28fe47 100644 --- a/android/data/src/main/kotlin/com/simplecityapps/shuttle/model/AlbumArtist.kt +++ b/android/data/src/main/kotlin/com/simplecityapps/shuttle/model/AlbumArtist.kt @@ -1,6 +1,7 @@ package com.simplecityapps.shuttle.model import android.os.Parcelable +import kotlinx.parcelize.IgnoredOnParcel import kotlinx.parcelize.Parcelize @Parcelize @@ -13,7 +14,8 @@ data class AlbumArtist( val groupKey: AlbumArtistGroupKey, val mediaProviders: List ) : Parcelable { - val friendlyArtistName: String? = + @IgnoredOnParcel + val friendlyArtistName: String? by lazy { if (artists.isNotEmpty()) { if (artists.size == 1) { artists.first() @@ -26,4 +28,5 @@ data class AlbumArtist( } else { null } + } } diff --git a/android/data/src/main/kotlin/com/simplecityapps/shuttle/model/Song.kt b/android/data/src/main/kotlin/com/simplecityapps/shuttle/model/Song.kt index a16e15292..c5b14c2f5 100644 --- a/android/data/src/main/kotlin/com/simplecityapps/shuttle/model/Song.kt +++ b/android/data/src/main/kotlin/com/simplecityapps/shuttle/model/Song.kt @@ -5,6 +5,7 @@ import com.simplecityapps.shuttle.parcel.InstantParceler import com.simplecityapps.shuttle.parcel.LocalDateParceler import kotlinx.datetime.Instant import kotlinx.datetime.LocalDate +import kotlinx.parcelize.IgnoredOnParcel import kotlinx.parcelize.Parcelize import kotlinx.parcelize.TypeParceler @@ -51,13 +52,16 @@ data class Song( } } - val albumArtistGroupKey: AlbumArtistGroupKey = + @IgnoredOnParcel + val albumArtistGroupKey: AlbumArtistGroupKey by lazy { AlbumArtistGroupKey( albumArtist?.lowercase()?.removeArticles() ?: artists.joinToString(", ") { it.lowercase().removeArticles() }.ifEmpty { null } ) + } - val albumGroupKey = AlbumGroupKey(album?.lowercase()?.removeArticles(), albumArtistGroupKey) + @IgnoredOnParcel + val albumGroupKey by lazy { AlbumGroupKey(album?.lowercase()?.removeArticles(), albumArtistGroupKey) } enum class Type { Audio, @@ -65,7 +69,8 @@ data class Song( Podcast } - val friendlyArtistName: String? = + @IgnoredOnParcel + val friendlyArtistName: String? by lazy { if (artists.isNotEmpty()) { if (artists.size == 1) { artists.first() @@ -78,4 +83,5 @@ data class Song( } else { null } + } } diff --git a/android/imageloader/build.gradle b/android/imageloader/build.gradle index efab39a1b..f924ac68a 100644 --- a/android/imageloader/build.gradle +++ b/android/imageloader/build.gradle @@ -5,11 +5,11 @@ apply plugin: 'com.google.devtools.ksp' apply plugin: 'com.google.devtools.ksp' android { - compileSdk 34 + compileSdk 35 defaultConfig { minSdkVersion 21 - targetSdkVersion 34 + targetSdkVersion 35 } buildTypes { @@ -47,23 +47,23 @@ dependencies { implementation project(':android:mediaprovider:jellyfin') // TagLib - implementation("com.github.timusus:ktaglib:1.4.1") + implementation(libs.timusus.ktaglib) // Hilt - implementation 'com.google.dagger:hilt-android:2.48.1' - ksp 'com.google.dagger:hilt-compiler:2.48.1' + implementation libs.hilt + ksp libs.hilt.compiler // Palette - implementation 'androidx.palette:palette-ktx:1.0.0' + implementation libs.androidx.palette.ktx // Coroutines - implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3' + implementation libs.kotlinx.coroutinesCore // Glide - implementation 'com.github.bumptech.glide:glide:4.16.0' - ksp 'com.github.bumptech.glide:ksp:4.14.2' - implementation 'com.github.bumptech.glide:okhttp3-integration:4.16.0' - implementation 'com.github.bumptech.glide:annotations:4.16.0' + implementation libs.glide + ksp libs.glide.ksp + implementation libs.glide.okhttp3Integration + implementation libs.glide.annotations implementation project(':android:data') } \ No newline at end of file diff --git a/android/mediaprovider/core/build.gradle b/android/mediaprovider/core/build.gradle index e8f88e77d..2417dc7ba 100644 --- a/android/mediaprovider/core/build.gradle +++ b/android/mediaprovider/core/build.gradle @@ -5,11 +5,11 @@ apply plugin: 'dagger.hilt.android.plugin' apply plugin: 'com.google.devtools.ksp' android { - compileSdk 34 + compileSdk 35 defaultConfig { minSdkVersion 21 - targetSdkVersion 34 + targetSdkVersion 35 testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" vectorDrawables.useSupportLibrary true @@ -41,32 +41,32 @@ dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) // Kotlin Standard Library - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.20" + implementation libs.kotlin.stdlib // Timber - implementation 'com.jakewharton.timber:timber:4.7.1' + implementation libs.timber implementation project(':android:data') // Shuttle Core implementation(project(":android:core")) - implementation 'org.jetbrains.kotlinx:kotlinx-datetime:0.4.1' + implementation libs.kotlinx.datetime // Kotlin Coroutines - api 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3' + api libs.kotlinx.coroutinesCore // AndroidX Annotations - api "androidx.annotation:annotation:1.7.0" + api libs.androidx.annotation // Phrase string formatting helper - api 'com.github.square:phrase:master-SNAPSHOT' + api libs.square.phrase // WorkManager - implementation("androidx.work:work-runtime-ktx:2.9.0-rc01") - implementation("androidx.hilt:hilt-work:1.1.0") - implementation("com.google.dagger:hilt-android:2.48.1") - ksp("com.google.dagger:hilt-compiler:2.48.1") - ksp("androidx.hilt:hilt-compiler:1.1.0") + implementation(libs.androidx.work.runtime.ktx) + implementation(libs.androidx.hilt.work) + implementation(libs.hilt) + ksp(libs.hilt.compiler) + ksp(libs.androidx.hilt.compiler) } \ No newline at end of file diff --git a/android/mediaprovider/core/src/main/java/com/simplecityapps/mediaprovider/StringComparison.kt b/android/mediaprovider/core/src/main/java/com/simplecityapps/mediaprovider/StringComparison.kt index 062ec1343..e2d1e11b5 100644 --- a/android/mediaprovider/core/src/main/java/com/simplecityapps/mediaprovider/StringComparison.kt +++ b/android/mediaprovider/core/src/main/java/com/simplecityapps/mediaprovider/StringComparison.kt @@ -103,8 +103,8 @@ object StringComparison { a: String, b: String ): JaroSimilarity { - val a = Normalizer.normalize(a.toLowerCase(), Normalizer.Form.NFD) - val b = Normalizer.normalize(b.toLowerCase(), Normalizer.Form.NFD) + val a = Normalizer.normalize(a.lowercase(), Normalizer.Form.NFD) + val b = Normalizer.normalize(b.lowercase(), Normalizer.Form.NFD) val jaroSimilarity = jaroDistance(a, b) val prefixScale = 0.1 diff --git a/android/mediaprovider/emby/build.gradle b/android/mediaprovider/emby/build.gradle index a258be316..f546e64f9 100644 --- a/android/mediaprovider/emby/build.gradle +++ b/android/mediaprovider/emby/build.gradle @@ -5,11 +5,11 @@ plugins { } android { - compileSdk 34 + compileSdk 35 defaultConfig { minSdkVersion 21 - targetSdkVersion 34 + targetSdkVersion 35 testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" consumerProguardFiles "consumer-rules.pro" @@ -27,7 +27,6 @@ android { } kotlinOptions { jvmTarget = JavaVersion.VERSION_11.toString() - freeCompilerArgs = freeCompilerArgs + "-Xallow-result-return-type" } namespace 'com.simplecityapps.provider.emby' @@ -36,21 +35,21 @@ android { dependencies { - implementation 'androidx.appcompat:appcompat:1.6.1' - implementation 'com.google.android.material:material:1.10.0' + implementation libs.androidx.appcompat + implementation libs.google.material implementation(project(":android:mediaprovider:core")) implementation(project(":android:core")) implementation(project(":android:networking")) - ksp 'com.squareup.moshi:moshi-kotlin-codegen:1.15.0' + ksp libs.moshi.kotlinCodegen - implementation 'com.jaredrummler:android-device-names:2.0.0' + implementation libs.jaredrummler.androidDeviceNames - implementation 'com.google.dagger:hilt-android:2.48.1' - ksp 'com.google.dagger:hilt-compiler:2.48.1' + implementation libs.hilt + ksp libs.hilt.compiler implementation project(':android:data') - implementation 'org.jetbrains.kotlinx:kotlinx-datetime:0.4.1' + implementation libs.kotlinx.datetime } \ No newline at end of file diff --git a/android/mediaprovider/emby/src/main/java/com/simplecityapps/provider/emby/EmbyMediaProvider.kt b/android/mediaprovider/emby/src/main/java/com/simplecityapps/provider/emby/EmbyMediaProvider.kt index 8ed8666ee..b2c2a92b7 100644 --- a/android/mediaprovider/emby/src/main/java/com/simplecityapps/provider/emby/EmbyMediaProvider.kt +++ b/android/mediaprovider/emby/src/main/java/com/simplecityapps/provider/emby/EmbyMediaProvider.kt @@ -20,6 +20,7 @@ import com.simplecityapps.shuttle.model.MediaProviderType import com.simplecityapps.shuttle.model.Playlist import com.simplecityapps.shuttle.model.Song import kotlin.math.min +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.asFlow import kotlinx.coroutines.flow.collectIndexed @@ -172,6 +173,7 @@ class EmbyMediaProvider( } } + @OptIn(ExperimentalCoroutinesApi::class) private fun findSongsForPlaylists( address: String, credentials: AuthenticatedCredentials, diff --git a/android/mediaprovider/jellyfin/build.gradle b/android/mediaprovider/jellyfin/build.gradle index 8dabcc75c..64d0b35fb 100644 --- a/android/mediaprovider/jellyfin/build.gradle +++ b/android/mediaprovider/jellyfin/build.gradle @@ -5,11 +5,11 @@ plugins { } android { - compileSdk 34 + compileSdk 35 defaultConfig { minSdkVersion 21 - targetSdkVersion 34 + targetSdkVersion 35 testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" consumerProguardFiles "consumer-rules.pro" @@ -27,7 +27,6 @@ android { } kotlinOptions { jvmTarget = JavaVersion.VERSION_11.toString() - freeCompilerArgs = freeCompilerArgs + "-Xallow-result-return-type" } namespace 'com.simplecityapps.provider.jellyfin' @@ -36,21 +35,21 @@ android { dependencies { - implementation 'androidx.appcompat:appcompat:1.6.1' - implementation 'com.google.android.material:material:1.10.0' + implementation libs.androidx.appcompat + implementation libs.google.material implementation(project(":android:mediaprovider:core")) implementation(project(":android:core")) implementation(project(":android:networking")) - ksp("com.squareup.moshi:moshi-kotlin-codegen:1.15.0") + ksp(libs.moshi.kotlinCodegen) - implementation 'com.jaredrummler:android-device-names:2.0.0' + implementation libs.jaredrummler.androidDeviceNames - implementation 'com.google.dagger:hilt-android:2.48.1' - ksp 'com.google.dagger:hilt-compiler:2.48.1' + implementation libs.hilt + ksp libs.hilt.compiler implementation project(':android:data') - implementation 'org.jetbrains.kotlinx:kotlinx-datetime:0.4.1' + implementation libs.kotlinx.datetime } \ No newline at end of file diff --git a/android/mediaprovider/jellyfin/src/main/java/com/simplecityapps/provider/jellyfin/JellyfinMediaProvider.kt b/android/mediaprovider/jellyfin/src/main/java/com/simplecityapps/provider/jellyfin/JellyfinMediaProvider.kt index f72102bb0..9e9ba944b 100644 --- a/android/mediaprovider/jellyfin/src/main/java/com/simplecityapps/provider/jellyfin/JellyfinMediaProvider.kt +++ b/android/mediaprovider/jellyfin/src/main/java/com/simplecityapps/provider/jellyfin/JellyfinMediaProvider.kt @@ -20,6 +20,7 @@ import com.simplecityapps.shuttle.model.MediaProviderType import com.simplecityapps.shuttle.model.Playlist import com.simplecityapps.shuttle.model.Song import kotlin.math.min +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.asFlow import kotlinx.coroutines.flow.collectIndexed @@ -172,6 +173,7 @@ class JellyfinMediaProvider( } } + @OptIn(ExperimentalCoroutinesApi::class) private fun findSongsForPlaylists( address: String, credentials: AuthenticatedCredentials, diff --git a/android/mediaprovider/local/build.gradle b/android/mediaprovider/local/build.gradle index 332d1e861..fd34d02c9 100644 --- a/android/mediaprovider/local/build.gradle +++ b/android/mediaprovider/local/build.gradle @@ -3,11 +3,11 @@ apply plugin: 'kotlin-android' apply plugin: 'com.google.devtools.ksp' android { - compileSdk 34 + compileSdk 35 defaultConfig { minSdkVersion 21 - targetSdkVersion 34 + targetSdkVersion 35 testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" @@ -52,27 +52,27 @@ dependencies { implementation project(path: ':android:mediaprovider:core') // TagLib - implementation("com.github.timusus:ktaglib:1.4.1") + implementation(libs.timusus.ktaglib) // Storage Access Framework implementation project(path: ':android:saf') // Room - ksp 'androidx.room:room-compiler:2.6.0' - api 'androidx.room:room-runtime:2.6.0' - api 'androidx.room:room-ktx:2.6.0' + ksp libs.androidx.room.compiler + api libs.androidx.room.runtime + api libs.androidx.room.ktx // Testing - testImplementation 'junit:junit:4.13.2' - androidTestImplementation 'androidx.test:runner:1.5.2' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' + testImplementation libs.junit + androidTestImplementation libs.androidx.runner + androidTestImplementation libs.androidx.espresso.core // Moshi - ksp("com.squareup.moshi:moshi-kotlin-codegen:1.15.0") + ksp(libs.moshi.kotlinCodegen) // Hilt - implementation 'com.google.dagger:hilt-android:2.48.1' - ksp 'com.google.dagger:hilt-compiler:2.48.1' + implementation libs.hilt + ksp libs.hilt.compiler - implementation 'org.jetbrains.kotlinx:kotlinx-datetime:0.4.1' + implementation libs.kotlinx.datetime } \ No newline at end of file diff --git a/android/mediaprovider/plex/build.gradle b/android/mediaprovider/plex/build.gradle index 88ae9ade8..e9558459e 100644 --- a/android/mediaprovider/plex/build.gradle +++ b/android/mediaprovider/plex/build.gradle @@ -5,11 +5,11 @@ plugins { } android { - compileSdk 34 + compileSdk 35 defaultConfig { minSdkVersion 21 - targetSdkVersion 34 + targetSdkVersion 35 testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" consumerProguardFiles "consumer-rules.pro" @@ -27,27 +27,26 @@ android { } kotlinOptions { jvmTarget = JavaVersion.VERSION_11.toString() - freeCompilerArgs = freeCompilerArgs + "-Xallow-result-return-type" } namespace 'com.simplecityapps.provider.plex' } dependencies { - implementation 'androidx.appcompat:appcompat:1.6.1' - implementation 'com.google.android.material:material:1.10.0' + implementation libs.androidx.appcompat + implementation libs.google.material implementation(project(":android:data")) implementation(project(":android:mediaprovider:core")) implementation(project(":android:core")) implementation(project(":android:networking")) - ksp 'com.squareup.moshi:moshi-kotlin-codegen:1.15.0' + ksp libs.moshi.kotlinCodegen - implementation 'com.jaredrummler:android-device-names:2.0.0' + implementation libs.jaredrummler.androidDeviceNames - implementation 'com.google.dagger:hilt-android:2.48.1' - ksp 'com.google.dagger:hilt-compiler:2.48.1' + implementation libs.hilt + ksp libs.hilt.compiler - implementation 'org.jetbrains.kotlinx:kotlinx-datetime:0.4.1' + implementation libs.kotlinx.datetime } \ No newline at end of file diff --git a/android/networking/build.gradle b/android/networking/build.gradle index 4c6676723..2adb61c75 100644 --- a/android/networking/build.gradle +++ b/android/networking/build.gradle @@ -5,11 +5,11 @@ plugins { } android { - compileSdk 34 + compileSdk 35 defaultConfig { minSdkVersion 21 - targetSdkVersion 34 + targetSdkVersion 35 testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" consumerProguardFiles "consumer-rules.pro" @@ -34,21 +34,21 @@ android { dependencies { // Kotlin std lib - implementation "org.jetbrains.kotlin:kotlin-stdlib:1.9.20" + implementation libs.kotlin.stdlib // OkHttp - implementation 'com.squareup.okhttp3:okhttp:4.12.0' + implementation libs.okhttp3.okhttp // Moshi - implementation 'com.squareup.moshi:moshi:1.15.0' - api 'com.squareup.moshi:moshi-kotlin:1.15.0' - implementation 'com.squareup.moshi:moshi-adapters:1.15.0' - ksp("com.squareup.moshi:moshi-kotlin-codegen:1.15.0") + implementation libs.moshi + api libs.moshi.kotlin + implementation libs.moshi.adapters + ksp(libs.moshi.kotlinCodegen) // Retrofit - api 'com.squareup.retrofit2:retrofit:2.10.0-SNAPSHOT' - api 'com.squareup.retrofit2:converter-moshi:2.10.0-SNAPSHOT' + api libs.retrofit2.retrofit + api libs.retrofit2.converterMoshi // Timber - implementation 'com.jakewharton.timber:timber:4.7.1' + implementation libs.timber } \ No newline at end of file diff --git a/android/playback/build.gradle b/android/playback/build.gradle index f8c8a49ac..965a82748 100644 --- a/android/playback/build.gradle +++ b/android/playback/build.gradle @@ -4,11 +4,11 @@ apply plugin: 'dagger.hilt.android.plugin' apply plugin: 'com.google.devtools.ksp' android { - compileSdk 34 + compileSdk 35 defaultConfig { minSdkVersion 21 - targetSdkVersion 34 + targetSdkVersion 35 } buildTypes { @@ -46,31 +46,31 @@ dependencies { implementation project(path: ':android:imageloader') // AndroidX Media - implementation 'androidx.media:media:1.6.0' + implementation libs.androidx.media // AndroidX DocumentFile - implementation 'androidx.documentfile:documentfile:1.0.1' + implementation libs.androidx.documentfile // Hilt - implementation 'com.google.dagger:hilt-android:2.48.1' - ksp 'com.google.dagger:hilt-compiler:2.48.1' + implementation libs.hilt + ksp libs.hilt.compiler // Chromecast - implementation 'com.google.android.gms:play-services-cast-framework:21.3.0' + implementation libs.google.play.services.cast.framework // NanoHttp - implementation 'org.nanohttpd:nanohttpd-webserver:2.3.1' + implementation libs.nanohttpd.webserver // ExoPlayer - implementation("com.github.timusus.exoplayer:exoplayer-core:2.14.2-shuttle") - implementation("com.github.timusus.exoplayer:exoplayer-hls:2.14.2-shuttle") - implementation("com.github.timusus.exoplayer:extension-flac:2.14.2-shuttle") - implementation("com.github.timusus.exoplayer:extension-opus:2.14.2-shuttle") + implementation(libs.exoplayer.core) + implementation(libs.exoplayer.hls) + implementation(libs.exoplayer.extensionFlac) + implementation(libs.exoplayer.extensionOpus) // Moshi - implementation 'com.squareup.moshi:moshi-kotlin:1.15.0' - ksp "com.squareup.moshi:moshi-kotlin-codegen:1.15.0" + implementation libs.moshi.kotlin + ksp libs.moshi.kotlinCodegen implementation(project(':android:data')) } \ No newline at end of file diff --git a/android/playback/src/main/java/com/simplecityapps/playback/androidauto/PackageValidator.kt b/android/playback/src/main/java/com/simplecityapps/playback/androidauto/PackageValidator.kt index 83522fe93..f52e1911c 100644 --- a/android/playback/src/main/java/com/simplecityapps/playback/androidauto/PackageValidator.kt +++ b/android/playback/src/main/java/com/simplecityapps/playback/androidauto/PackageValidator.kt @@ -180,13 +180,14 @@ class PackageValidator( */ private fun buildCallerInfo(callingPackage: String): CallerPackageInfo? { val packageInfo = getPackageInfo(callingPackage) ?: return null + val applicationInfo = packageInfo.applicationInfo ?: return null - val appName = packageInfo.applicationInfo.loadLabel(packageManager).toString() - val uid = packageInfo.applicationInfo.uid + val appName = applicationInfo.loadLabel(packageManager).toString() + val uid = applicationInfo.uid val signature = getSignature(packageInfo) val requestedPermissions = packageInfo.requestedPermissions - val permissionFlags = packageInfo.requestedPermissionsFlags + val permissionFlags = packageInfo.requestedPermissionsFlags ?: intArrayOf() val activePermissions = mutableSetOf() requestedPermissions?.forEachIndexed { index, permission -> if (permissionFlags[index] and REQUESTED_PERMISSION_GRANTED != 0) { @@ -220,16 +221,17 @@ class PackageValidator( * If the app is not found, or if the app does not have exactly one signature, this method * returns `null` as the signature. */ - private fun getSignature(packageInfo: PackageInfo): String? = - if (packageInfo.signatures == null || packageInfo.signatures.size != 1) { + private fun getSignature(packageInfo: PackageInfo): String? { + val signatures = packageInfo.signatures + return if (signatures == null || signatures.size != 1) { // Security best practices dictate that an app should be signed with exactly one (1) // signature. Because of this, if there are multiple signatures, reject it. null } else { - val certificate = packageInfo.signatures[0].toByteArray() + val certificate = signatures[0].toByteArray() getSignatureSha256(certificate) } - + } private fun buildCertificateWhitelist(parser: XmlResourceParser): Map { val certificateWhitelist = LinkedHashMap() try { @@ -290,7 +292,7 @@ class PackageValidator( var eventType = parser.next() while (eventType != XmlResourceParser.END_TAG) { val isRelease = parser.getAttributeBooleanValue(null, "release", false) - val signature = parser.nextText().replace(WHITESPACE_REGEX, "").toLowerCase() + val signature = parser.nextText().replace(WHITESPACE_REGEX, "").lowercase() callerSignatures += KnownSignature(signature, isRelease) eventType = parser.next() diff --git a/android/recyclerview-adapter/build.gradle b/android/recyclerview-adapter/build.gradle index 8a24e593f..17f5cdb5d 100644 --- a/android/recyclerview-adapter/build.gradle +++ b/android/recyclerview-adapter/build.gradle @@ -2,11 +2,11 @@ apply plugin: 'com.android.library' apply plugin: 'kotlin-android' android { - compileSdk 34 + compileSdk 35 defaultConfig { minSdkVersion 21 - targetSdkVersion 34 + targetSdkVersion 35 } buildTypes { @@ -32,14 +32,14 @@ dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) // Kotlin Standard Library - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.20" + implementation libs.kotlin.stdlib // RecyclerView - implementation 'androidx.recyclerview:recyclerview:1.3.2' + implementation libs.androidx.recyclerview // Timber - implementation "com.jakewharton.timber:timber:4.7.1" + implementation libs.timber // Coroutines - implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3") + implementation(libs.kotlinx.coroutinesCore) } \ No newline at end of file diff --git a/android/remote-config/build.gradle.kts b/android/remote-config/build.gradle.kts index 5b8ae1f01..98aa5ed36 100644 --- a/android/remote-config/build.gradle.kts +++ b/android/remote-config/build.gradle.kts @@ -6,7 +6,7 @@ plugins { } android { - compileSdk = 34 + compileSdk = 35 defaultConfig { minSdk = 21 @@ -33,22 +33,22 @@ android { dependencies { - implementation("androidx.core:core-ktx:1.12.0") + implementation(libs.androidx.core.ktx) // Firebase - api(platform("com.google.firebase:firebase-bom:32.6.0")) - api("com.google.firebase:firebase-config-ktx") - implementation("com.google.firebase:firebase-analytics-ktx") - api("org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.7.3") + api(platform(libs.firebase.bom)) + api(libs.firebase.config.ktx) + implementation(libs.firebase.analytics.ktx) + api(libs.kotlinx.coroutinesPlayServices) // Hilt - implementation("com.google.dagger:hilt-android:2.48.1") - ksp("com.google.dagger:hilt-compiler:2.48.1") + implementation(libs.hilt) + ksp(libs.hilt.compiler) // S2 Core implementation(project(":android:core")) - testImplementation("junit:junit:4.13.2") - androidTestImplementation("androidx.test.ext:junit:1.1.5") - androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1") + testImplementation(libs.junit) + androidTestImplementation(libs.androidx.junit) + androidTestImplementation(libs.androidx.espresso.core) } diff --git a/android/saf/build.gradle b/android/saf/build.gradle index db04749b2..1b80d8e7a 100644 --- a/android/saf/build.gradle +++ b/android/saf/build.gradle @@ -4,11 +4,11 @@ plugins { } android { - compileSdk 34 + compileSdk 35 defaultConfig { minSdkVersion 21 - targetSdkVersion 34 + targetSdkVersion 35 consumerProguardFiles 'consumer-rules.pro' } @@ -35,14 +35,14 @@ dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) // Kotlin Standard Library - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.20" + implementation libs.kotlin.stdlib // SAF - api 'androidx.documentfile:documentfile:1.0.1' + api libs.androidx.documentfile // Coroutines - implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3" + implementation libs.kotlinx.coroutinesCore // Timber - implementation 'com.jakewharton.timber:timber:4.7.1' + implementation libs.timber } diff --git a/android/trial/build.gradle b/android/trial/build.gradle index 2e94abdc7..973ebef11 100644 --- a/android/trial/build.gradle +++ b/android/trial/build.gradle @@ -5,11 +5,11 @@ plugins { } android { - compileSdk 34 + compileSdk 35 defaultConfig { minSdkVersion 21 - targetSdkVersion 34 + targetSdkVersion 35 testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" consumerProguardFiles "consumer-rules.pro" @@ -35,35 +35,35 @@ android { dependencies { - implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" - implementation 'androidx.core:core-ktx:1.12.0' - implementation 'androidx.appcompat:appcompat:1.6.1' - implementation 'com.google.android.material:material:1.10.0' + implementation libs.kotlin.stdlib + implementation libs.androidx.core.ktx + implementation libs.androidx.appcompat + implementation libs.google.material // OKHttp - implementation 'com.squareup.okhttp3:okhttp:4.12.0' + implementation libs.okhttp3.okhttp // Retrofit - implementation 'com.squareup.retrofit2:converter-moshi:2.10.0-SNAPSHOT' + implementation libs.retrofit2.converterMoshi // Billing - implementation 'com.android.billingclient:billing-ktx:6.1.0' + implementation libs.billingclient.billingKtx // Moshi - implementation 'com.squareup.moshi:moshi:1.15.0' - implementation 'com.squareup.moshi:moshi-kotlin:1.15.0' - implementation 'com.squareup.moshi:moshi-adapters:1.15.0' - ksp("com.squareup.moshi:moshi-kotlin-codegen:1.15.0") + implementation libs.moshi + implementation libs.moshi.kotlin + implementation libs.moshi.adapters + ksp(libs.moshi.kotlinCodegen) // Timber - implementation 'com.jakewharton.timber:timber:4.7.1' + implementation libs.timber // Hilt - implementation 'com.google.dagger:hilt-android:2.48.1' - ksp 'com.google.dagger:hilt-compiler:2.48.1' + implementation libs.hilt + ksp libs.hilt.compiler // Coroutines - api("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3") + api(libs.kotlinx.coroutinesCore) // Remote config implementation project(':android:remote-config') diff --git a/build.gradle.kts b/build.gradle.kts index ecf15bb87..eb386b1d9 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,30 +1,16 @@ -buildscript { - val kotlin_version by extra("1.9.20") - val compose_version by extra("1.5.4") - repositories { - gradlePluginPortal() - google() - mavenCentral() - } - dependencies { - classpath("com.android.tools.build:gradle:8.2.0") - classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.20") - classpath("androidx.navigation:navigation-safe-args-gradle-plugin:2.7.5") - classpath("com.google.gms:google-services:4.4.0") - classpath("com.mikepenz.aboutlibraries.plugin:aboutlibraries-plugin:10.9.2") - classpath("com.google.dagger:hilt-android-gradle-plugin:2.48.1") - classpath("com.google.firebase:firebase-crashlytics-gradle:2.9.9") - classpath("com.google.devtools.ksp:com.google.devtools.ksp.gradle.plugin:1.9.20-1.0.14") - } +plugins { + alias(libs.plugins.android.application) apply false + alias(libs.plugins.kotlin.android) apply false + alias(libs.plugins.kotlin.compose) apply false + alias(libs.plugins.hilt) apply false + alias(libs.plugins.ksp) apply false + alias(libs.plugins.google.services) apply false + alias(libs.plugins.firebase.crashlytics) apply false + alias(libs.plugins.aboutlibraries) apply false } -allprojects { - repositories { - google() - mavenCentral() - maven("https://jitpack.io") - maven("https://plugins.gradle.org/m2/") - maven("https://maven.pkg.jetbrains.space/public/p/compose/dev") - maven("https://oss.sonatype.org/content/repositories/snapshots") +buildscript { + dependencies { + classpath(libs.androidx.navigation.safe.args.gradle.plugin) } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml new file mode 100644 index 000000000..9a931d642 --- /dev/null +++ b/gradle/libs.versions.toml @@ -0,0 +1,160 @@ +[versions] +aboutlibraries = "10.9.2" +android-device-names = "2.0.0" +annotation = "1.9.1" +annotations = "4.16.0" +appcompat = "1.7.0" +agp = "8.8.0" +billing-ktx = "7.1.1" +circleindicator = "2.1.6" +ksp = "2.1.0-1.0.29" +constraintlayout = "2.2.0" +converter-moshi = "2.11.0" +core-ktx-version = "1.6.1" +desugar-jdk-libs = "2.1.4" +documentfile = "1.0.1" +drawerlayout = "1.2.0" +espresso-core = "3.6.1" +exoplayer-shuttle = "2.14.2-shuttle" +firebase-bom = "33.8.0" +firebase-crashlytics = "3.0.2" +fluent-system-icons = "1.1.137" +fragment-ktx = "1.8.5" +glide = "4.16.0" +google-services = "4.4.2" +hamcrest-library = "1.3" +hilt-android = "2.53" +hilt-compiler = "1.2.0" +hilt-work = "1.2.0" +junit = "4.13.2" +junit-version = "1.2.1" +kotlin = "2.1.0" +kotlinx-coroutines-android = "1.8.1" +kotlinx-coroutines-core = "1.8.1" +kotlinx-coroutines-play-services = "1.8.1" +kotlinx-datetime = "0.4.1" +glide-ksp = "4.14.2" +ktaglib = "1.4.1" +leakcanary-android = "2.10" +lifecycle-common-java8 = "2.8.7" +lifecycle-extensions = "2.2.0" +lifecycle-runtime-ktx = "2.8.7" +logging-interceptor = "4.12.0" +material = "1.12.0" +media = "1.7.0" +moshi = "1.15.1" +moshi-adapters = "1.15.0" +moshi-kotlin = "1.15.0" +moshi-kotlin-codegen = "1.15.0" +mpandroidchart = "3.1.0" +nanohttpd-webserver = "2.3.1" +navigation-safe-args-gradle-plugin = "2.8.5" +navigation-ui-ktx = "2.8.5" +noise = "2.0.0" +okhttp = "4.12.0" +okhttp3-integration = "4.16.0" +palette-ktx = "1.0.0" +phrase = "master-SNAPSHOT" +play-services-cast-framework = "22.0.0" +preference-ktx = "1.2.1" +recyclerview = "1.4.0" +recyclerview-fastscroll = "dev-SNAPSHOT" +review = "2.0.2" +room-compiler = "2.6.1" +runner = "1.6.2" +security-crypto = "1.1.0-alpha06" +semver4j = "3.1.0" +timber = "4.7.1" +viewpager2 = "1.1.0" +work-runtime-ktx = "2.10.0" + +[libraries] +androidx-annotation = { module = "androidx.annotation:annotation", version.ref = "annotation" } +androidx-appcompat = { module = "androidx.appcompat:appcompat", version.ref = "appcompat" } +androidx-constraintlayout = { module = "androidx.constraintlayout:constraintlayout", version.ref = "constraintlayout" } +androidx-core-ktx = { module = "androidx.test:core-ktx", version.ref = "core-ktx-version" } +androidx-documentfile = { module = "androidx.documentfile:documentfile", version.ref = "documentfile" } +androidx-drawerlayout = { module = "androidx.drawerlayout:drawerlayout", version.ref = "drawerlayout" } +androidx-espresso-core = { module = "androidx.test.espresso:espresso-core", version.ref = "espresso-core" } +androidx-fragment-ktx = { module = "androidx.fragment:fragment-ktx", version.ref = "fragment-ktx" } +androidx-hilt-compiler = { module = "androidx.hilt:hilt-compiler", version.ref = "hilt-compiler" } +androidx-hilt-work = { module = "androidx.hilt:hilt-work", version.ref = "hilt-work" } +androidx-junit = { module = "androidx.test.ext:junit", version.ref = "junit-version" } +androidx-lifecycle-common-java8 = { module = "androidx.lifecycle:lifecycle-common-java8", version.ref = "lifecycle-common-java8" } +androidx-lifecycle-extensions = { module = "androidx.lifecycle:lifecycle-extensions", version.ref = "lifecycle-extensions" } +androidx-lifecycle-runtime-ktx = { module = "androidx.lifecycle:lifecycle-runtime-ktx", version.ref = "lifecycle-runtime-ktx" } +androidx-media = { module = "androidx.media:media", version.ref = "media" } +androidx-navigation-fragment-ktx = { module = "androidx.navigation:navigation-fragment-ktx", version.ref = "navigation-ui-ktx" } +androidx-navigation-safe-args-gradle-plugin = { module = "androidx.navigation:navigation-safe-args-gradle-plugin", version.ref = "navigation-safe-args-gradle-plugin" } +androidx-navigation-ui-ktx = { module = "androidx.navigation:navigation-ui-ktx", version.ref = "navigation-ui-ktx" } +androidx-palette-ktx = { module = "androidx.palette:palette-ktx", version.ref = "palette-ktx" } +androidx-preference-ktx = { module = "androidx.preference:preference-ktx", version.ref = "preference-ktx" } +androidx-recyclerview = { module = "androidx.recyclerview:recyclerview", version.ref = "recyclerview" } +androidx-room-compiler = { module = "androidx.room:room-compiler", version.ref = "room-compiler" } +androidx-room-ktx = { module = "androidx.room:room-ktx", version.ref = "room-compiler" } +androidx-room-runtime = { module = "androidx.room:room-runtime", version.ref = "room-compiler" } +androidx-rules = { module = "androidx.test:rules", version.ref = "core-ktx-version" } +androidx-runner = { module = "androidx.test:runner", version.ref = "runner" } +androidx-security-crypto = { module = "androidx.security:security-crypto", version.ref = "security-crypto" } +androidx-viewpager2 = { module = "androidx.viewpager2:viewpager2", version.ref = "viewpager2" } +androidx-work-runtime-ktx = { module = "androidx.work:work-runtime-ktx", version.ref = "work-runtime-ktx" } +billingclient-billingKtx = { module = "com.android.billingclient:billing-ktx", version.ref = "billing-ktx" } +design-fluentSystemIcons = { module = "com.microsoft.design:fluent-system-icons", version.ref = "fluent-system-icons" } +exoplayer-core = { module = "com.github.timusus.exoplayer:exoplayer-core", version.ref = "exoplayer-shuttle" } +exoplayer-extensionFlac = { module = "com.github.timusus.exoplayer:extension-flac", version.ref = "exoplayer-shuttle" } +exoplayer-extensionOpus = { module = "com.github.timusus.exoplayer:extension-opus", version.ref = "exoplayer-shuttle" } +exoplayer-hls = { module = "com.github.timusus.exoplayer:exoplayer-hls", version.ref = "exoplayer-shuttle" } +firebase-analytics-ktx = { module = "com.google.firebase:firebase-analytics-ktx" } +firebase-bom = { module = "com.google.firebase:firebase-bom", version.ref = "firebase-bom" } +firebase-config-ktx = { module = "com.google.firebase:firebase-config-ktx" } +firebase-crashlytics = { module = "com.google.firebase:firebase-crashlytics" } +glide = { module = "com.github.bumptech.glide:glide", version.ref = "glide" } +glide-annotations = { module = "com.github.bumptech.glide:annotations", version.ref = "annotations" } +glide-ksp = { module = "com.github.bumptech.glide:ksp", version.ref = "glide-ksp" } +glide-okhttp3Integration = { module = "com.github.bumptech.glide:okhttp3-integration", version.ref = "okhttp3-integration" } +google-material = { module = "com.google.android.material:material", version.ref = "material" } +google-play-services-cast-framework = { module = "com.google.android.gms:play-services-cast-framework", version.ref = "play-services-cast-framework" } +google-review = { module = "com.google.android.play:review", version.ref = "review" } +google-review-ktx = { module = "com.google.android.play:review-ktx", version.ref = "review" } +hamcrest-library = { module = "org.hamcrest:hamcrest-library", version.ref = "hamcrest-library" } +hilt-android-testing = { module = "com.google.dagger:hilt-android-testing", version.ref = "hilt-android" } +hilt-compiler = { module = "com.google.dagger:hilt-compiler", version.ref = "hilt-android" } +hilt = { module = "com.google.dagger:hilt-android", version.ref = "hilt-android" } +jaredrummler-androidDeviceNames = { module = "com.jaredrummler:android-device-names", version.ref = "android-device-names" } +junit = { module = "junit:junit", version.ref = "junit" } +kotlin-stdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib", version.ref = "kotlin" } +kotlinx-coroutinesAndroid = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "kotlinx-coroutines-android" } +kotlinx-coroutinesCore = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinx-coroutines-core" } +kotlinx-coroutinesPlayServices = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-play-services", version.ref = "kotlinx-coroutines-play-services" } +kotlinx-datetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version.ref = "kotlinx-datetime" } +leakcanary-android = { module = "com.squareup.leakcanary:leakcanary-android", version.ref = "leakcanary-android" } +mikepenz-aboutlibrariesCore = { module = "com.mikepenz:aboutlibraries-core", version.ref = "aboutlibraries" } +moshi = { module = "com.squareup.moshi:moshi", version.ref = "moshi" } +moshi-adapters = { module = "com.squareup.moshi:moshi-adapters", version.ref = "moshi-adapters" } +moshi-kotlin = { module = "com.squareup.moshi:moshi-kotlin", version.ref = "moshi-kotlin" } +moshi-kotlinCodegen = { module = "com.squareup.moshi:moshi-kotlin-codegen", version.ref = "moshi-kotlin-codegen" } +nanohttpd-webserver = { module = "org.nanohttpd:nanohttpd-webserver", version.ref = "nanohttpd-webserver" } +okhttp3-loggingInterceptor = { module = "com.squareup.okhttp3:logging-interceptor", version.ref = "logging-interceptor" } +okhttp3-okhttp = { module = "com.squareup.okhttp3:okhttp", version.ref = "okhttp" } +paramsen-noise = { module = "com.github.paramsen:noise", version.ref = "noise" } +philjay-mpAndroidChart = { module = "com.github.PhilJay:MPAndroidChart", version.ref = "mpandroidchart" } +relex-circleindicator = { module = "me.relex:circleindicator", version.ref = "circleindicator" } +retrofit2-converterMoshi = { module = "com.squareup.retrofit2:converter-moshi", version.ref = "converter-moshi" } +retrofit2-retrofit = { module = "com.squareup.retrofit2:retrofit", version.ref = "converter-moshi" } +square-phrase = { module = "com.github.square:phrase", version.ref = "phrase" } +timber = { module = "com.jakewharton.timber:timber", version.ref = "timber" } +timusus-ktaglib = { module = "com.github.timusus:ktaglib", version.ref = "ktaglib" } +timusus-recyclerViewFastScroll = { module = "com.github.timusus:RecyclerView-FastScroll", version.ref = "recyclerview-fastscroll" } +tools-desugar_jdk_libs = { module = "com.android.tools:desugar_jdk_libs", version.ref = "desugar-jdk-libs" } +vdurmont-semver4j = { module = "com.vdurmont:semver4j", version.ref = "semver4j" } + +[plugins] + +aboutlibraries = { id = "com.mikepenz.aboutlibraries.plugin", version.ref = "aboutlibraries" } +android-application = { id = "com.android.application", version.ref = "agp" } +firebase-crashlytics = { id = "com.google.firebase.crashlytics", version.ref = "firebase-crashlytics" } +google-services = { id = "com.google.gms.google-services", version.ref = "google-services" } +hilt = { id = "com.google.dagger.hilt.android", version.ref = "hilt-android" } +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" } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 249e5832f..2c3521197 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index e411586a5..df97d72b8 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip +networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index a69d9cb6c..f5feea6d6 100755 --- a/gradlew +++ b/gradlew @@ -15,6 +15,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## # @@ -55,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -80,13 +82,12 @@ do esac done -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit - -APP_NAME="Gradle" +# This is normally unused +# shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s +' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -133,22 +134,29 @@ location of your Java installation." fi else JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac case $MAX_FD in #( '' | soft) :;; #( *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -193,11 +201,15 @@ if "$cygwin" || "$msys" ; then done fi -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ diff --git a/gradlew.bat b/gradlew.bat index f127cfd49..9d21a2183 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -13,6 +13,8 @@ @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem @if "%DEBUG%"=="" @echo off @rem ########################################################################## @@ -26,6 +28,7 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @@ -42,11 +45,11 @@ set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -56,11 +59,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail diff --git a/settings.gradle b/settings.gradle index e5f462c86..cba00a38e 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,3 +1,28 @@ +pluginManagement { + repositories { + google { + content { + includeGroupByRegex("com\\.android.*") + includeGroupByRegex("com\\.google.*") + includeGroupByRegex("androidx.*") + } + } + mavenCentral() + gradlePluginPortal() + } +} +dependencyResolutionManagement { + repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) + repositories { + google() + mavenCentral() + maven { url = "https://jitpack.io" } + maven { url = "https://oss.sonatype.org/content/repositories/snapshots" } + } +} + +rootProject.name = "shuttle" + include ':android:app' include ':android:core' include ':android:data' diff --git a/support/scripts/unit-test b/support/scripts/unit-test index 309ec88a5..49c9d5a9e 100755 --- a/support/scripts/unit-test +++ b/support/scripts/unit-test @@ -12,7 +12,6 @@ RESULT_PATH=${RESULT_PATH:-${BUILD_PATH}/Artifacts} # eg: JUNIT_PATH="${RESULT_PATH}/test-results.xml" #SUPPORT_DIR="${BASH_SOURCE[0]%/*}/.." - function finish() { # Do any work necessary even if script this fails echo "Finished" @@ -21,4 +20,4 @@ function finish() { trap finish EXIT # Perform Unit Tests -./gradlew :android:app:test +./gradlew testDebugUnitTest