From 320c693636f761c288d846997d2eaa97da369860 Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Tue, 14 Oct 2025 23:04:51 +0800 Subject: [PATCH 1/6] Revert "Add snippet to ensure baseline.profm file is sorted" This reverts commit 1db1a0058106af6b4b2c7e850a370c32f899e019. The issue has been long resolved making this fix no longer required. --- app/build.gradle | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 38765476a..784f11ee7 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,7 +1,3 @@ -import com.android.tools.profgen.ArtProfileKt -import com.android.tools.profgen.ArtProfileSerializer -import com.android.tools.profgen.DexFile - plugins { id "com.android.application" id "kotlin-android" @@ -336,25 +332,3 @@ static String getGitWorkingBranch() { return "" } } - -// fix reproducible builds -project.afterEvaluate { - tasks.compileReleaseArtProfile.doLast { - outputs.files.each { file -> - if (file.toString().endsWith(".profm")) { - println("Sorting ${file} ...") - def version = ArtProfileSerializer.valueOf("METADATA_0_0_2") - def profile = ArtProfileKt.ArtProfile(file) - def keys = new ArrayList(profile.profileData.keySet()) - def sortedData = new LinkedHashMap() - Collections.sort keys, new DexFile.Companion() - keys.each { key -> sortedData[key] = profile.profileData[key] } - new FileOutputStream(file).with { - write(version.magicBytes$profgen) - write(version.versionBytes$profgen) - version.write$profgen(it, sortedData, "") - } - } - } - } -} From d99435c4ad43ae20ba378d00135acf5908bd3899 Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Tue, 14 Oct 2025 23:02:42 +0800 Subject: [PATCH 2/6] Migrate build scripts to kotlin DSL Ref: https://developer.android.com/build/migrate-to-kotlin-dsl Signed-off-by: Aayush Gupta --- app/build.gradle | 334 ------------------------------------------- app/build.gradle.kts | 320 +++++++++++++++++++++++++++++++++++++++++ build.gradle | 25 ---- build.gradle.kts | 12 ++ settings.gradle | 11 -- settings.gradle.kts | 32 +++++ 6 files changed, 364 insertions(+), 370 deletions(-) delete mode 100644 app/build.gradle create mode 100644 app/build.gradle.kts delete mode 100644 build.gradle create mode 100644 build.gradle.kts delete mode 100644 settings.gradle create mode 100644 settings.gradle.kts diff --git a/app/build.gradle b/app/build.gradle deleted file mode 100644 index 784f11ee7..000000000 --- a/app/build.gradle +++ /dev/null @@ -1,334 +0,0 @@ -plugins { - id "com.android.application" - id "kotlin-android" - id "kotlin-kapt" - id "kotlin-parcelize" - id "checkstyle" - id "org.sonarqube" version "4.0.0.2929" -} - -android { - compileSdk 36 - namespace 'org.schabi.newpipe' - - defaultConfig { - applicationId "org.schabi.newpipe" - resValue "string", "app_name", "NewPipe" - minSdk 21 - targetSdk 35 - if (System.properties.containsKey('versionCodeOverride')) { - versionCode System.getProperty('versionCodeOverride') as Integer - } else { - versionCode 1005 - } - versionName "0.28.0" - if (System.properties.containsKey('versionNameSuffix')) { - versionNameSuffix System.getProperty('versionNameSuffix') - } - - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - - javaCompileOptions { - annotationProcessorOptions { - arguments = ["room.schemaLocation": "$projectDir/schemas".toString()] - } - } - } - - buildTypes { - debug { - debuggable true - - // suffix the app id and the app name with git branch name - def workingBranch = getGitWorkingBranch() - def normalizedWorkingBranch = workingBranch.replaceFirst("^[^A-Za-z]+", "").replaceAll("[^0-9A-Za-z]+", "") - if (normalizedWorkingBranch.isEmpty() || workingBranch == "master" || workingBranch == "dev") { - // default values when branch name could not be determined or is master or dev - applicationIdSuffix ".debug" - resValue "string", "app_name", "NewPipe Debug" - } else { - applicationIdSuffix ".debug." + normalizedWorkingBranch - resValue "string", "app_name", "NewPipe " + workingBranch - archivesBaseName = 'NewPipe_' + normalizedWorkingBranch - } - } - - release { - if (System.properties.containsKey('packageSuffix')) { - applicationIdSuffix System.getProperty('packageSuffix') - resValue "string", "app_name", "NewPipe " + System.getProperty('packageSuffix') - archivesBaseName = 'NewPipe_' + System.getProperty('packageSuffix') - } - minifyEnabled true - shrinkResources false // disabled to fix F-Droid's reproducible build - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - archivesBaseName = 'app' - } - } - - lint { - checkReleaseBuilds false - // Or, if you prefer, you can continue to check for errors in release builds, - // but continue the build even when errors are found: - abortOnError false - // suppress false warning ("Resource IDs will be non-final in Android Gradle Plugin version - // 5.0, avoid using them in switch case statements"), which affects only library projects - disable 'NonConstantResourceId' - } - - compileOptions { - // Flag to enable support for the new language APIs - coreLibraryDesugaringEnabled true - - sourceCompatibility JavaVersion.VERSION_17 - targetCompatibility JavaVersion.VERSION_17 - encoding 'utf-8' - } - - kotlinOptions { - jvmTarget = JavaVersion.VERSION_17 - } - - sourceSets { - androidTest.assets.srcDirs += files("$projectDir/schemas".toString()) - } - - androidResources { - generateLocaleConfig = true - } - - buildFeatures { - viewBinding true - buildConfig true - } - - packagingOptions { - resources { - // remove two files which belong to jsoup - // no idea how they ended up in the META-INF dir... - excludes += ['META-INF/README.md', 'META-INF/CHANGES', - // 'COPYRIGHT' belongs to RxJava... - 'META-INF/COPYRIGHT'] - } - } -} - -ext { - checkstyleVersion = '10.12.1' - - androidxLifecycleVersion = '2.6.2' - androidxRoomVersion = '2.6.1' - androidxWorkVersion = '2.8.1' - - stateSaverVersion = '1.4.1' - exoPlayerVersion = '2.18.7' - googleAutoServiceVersion = '1.1.1' - groupieVersion = '2.10.1' - markwonVersion = '4.6.2' - - leakCanaryVersion = '2.12' - stethoVersion = '1.6.0' -} - -configurations { - checkstyle - ktlint -} - -checkstyle { - getConfigDirectory().set(rootProject.file("checkstyle")) - ignoreFailures false - showViolations true - toolVersion = checkstyleVersion -} - -tasks.register('runCheckstyle', Checkstyle) { - source 'src' - include '**/*.java' - exclude '**/gen/**' - exclude '**/R.java' - exclude '**/BuildConfig.java' - exclude 'main/java/us/shandian/giga/**' - - classpath = configurations.checkstyle - - showViolations true - - reports { - xml.getRequired().set(true) - html.getRequired().set(true) - } -} - -def outputDir = "${project.buildDir}/reports/ktlint/" -def inputFiles = project.fileTree(dir: "src", include: "**/*.kt") - -tasks.register('runKtlint', JavaExec) { - inputs.files(inputFiles) - outputs.dir(outputDir) - getMainClass().set("com.pinterest.ktlint.Main") - classpath = configurations.ktlint - args "src/**/*.kt" - jvmArgs("--add-opens", "java.base/java.lang=ALL-UNNAMED") -} - -tasks.register('formatKtlint', JavaExec) { - inputs.files(inputFiles) - outputs.dir(outputDir) - getMainClass().set("com.pinterest.ktlint.Main") - classpath = configurations.ktlint - args "-F", "src/**/*.kt" - jvmArgs("--add-opens", "java.base/java.lang=ALL-UNNAMED") -} - -afterEvaluate { - if (!System.properties.containsKey('skipFormatKtlint')) { - preDebugBuild.dependsOn formatKtlint - } - preDebugBuild.dependsOn runCheckstyle, runKtlint -} - -sonar { - properties { - property "sonar.projectKey", "TeamNewPipe_NewPipe" - property "sonar.organization", "teamnewpipe" - property "sonar.host.url", "https://sonarcloud.io" - } -} - -dependencies { -/** Desugaring **/ - coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs_nio:2.0.4' - -/** NewPipe libraries **/ - // You can use a local version by uncommenting a few lines in settings.gradle - // Or you can use a commit you pushed to GitHub by just replacing TeamNewPipe with your GitHub - // name and the commit hash with the commit hash of the (pushed) commit you want to test - // This works thanks to JitPack: https://jitpack.io/ - implementation 'com.github.TeamNewPipe:nanojson:e9d656ddb49a412a5a0a5d5ef20ca7ef09549996' - // WORKAROUND: if you get errors with the NewPipeExtractor dependency, replace `v0.24.3` with - // the corresponding commit hash, since JitPack sometimes deletes artifacts. - // If there’s already a git hash, just add more of it to the end (or remove a letter) - // to cause jitpack to regenerate the artifact. - implementation 'com.github.TeamNewPipe:NewPipeExtractor:0023b22095a2d62a60cdfc87f4b5cd85c8b266c3' - implementation 'com.github.TeamNewPipe:NoNonsense-FilePicker:5.0.0' - -/** Checkstyle **/ - checkstyle "com.puppycrawl.tools:checkstyle:${checkstyleVersion}" - ktlint 'com.pinterest:ktlint:0.45.2' - -/** Kotlin **/ - implementation "org.jetbrains.kotlin:kotlin-stdlib:${kotlin_version}" - -/** AndroidX **/ - implementation 'androidx.appcompat:appcompat:1.7.1' - implementation 'androidx.cardview:cardview:1.0.0' - implementation 'androidx.constraintlayout:constraintlayout:2.1.4' - implementation 'androidx.core:core-ktx:1.12.0' - implementation 'androidx.documentfile:documentfile:1.0.1' - implementation 'androidx.fragment:fragment-ktx:1.6.2' - implementation "androidx.lifecycle:lifecycle-livedata-ktx:${androidxLifecycleVersion}" - implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:${androidxLifecycleVersion}" - implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.1.0' - implementation 'androidx.media:media:1.7.0' - implementation 'androidx.preference:preference:1.2.1' - implementation 'androidx.recyclerview:recyclerview:1.3.2' - implementation "androidx.room:room-runtime:${androidxRoomVersion}" - implementation "androidx.room:room-rxjava3:${androidxRoomVersion}" - kapt "androidx.room:room-compiler:${androidxRoomVersion}" - implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0' - // Newer version specified to prevent accessibility regressions with RecyclerView, see: - // https://developer.android.com/jetpack/androidx/releases/viewpager2#1.1.0-alpha01 - implementation 'androidx.viewpager2:viewpager2:1.1.0-beta02' - implementation "androidx.work:work-runtime-ktx:${androidxWorkVersion}" - implementation "androidx.work:work-rxjava3:${androidxWorkVersion}" - implementation 'com.google.android.material:material:1.11.0' - implementation "androidx.webkit:webkit:1.9.0" - -/** Third-party libraries **/ - // Instance state boilerplate elimination - implementation 'com.github.livefront:bridge:v2.0.2' - implementation "com.evernote:android-state:$stateSaverVersion" - kapt "com.evernote:android-state-processor:$stateSaverVersion" - - // HTML parser - implementation "org.jsoup:jsoup:1.17.2" - - // HTTP client - implementation "com.squareup.okhttp3:okhttp:4.12.0" - - // Media player - implementation "com.google.android.exoplayer:exoplayer-core:${exoPlayerVersion}" - implementation "com.google.android.exoplayer:exoplayer-dash:${exoPlayerVersion}" - implementation "com.google.android.exoplayer:exoplayer-database:${exoPlayerVersion}" - implementation "com.google.android.exoplayer:exoplayer-datasource:${exoPlayerVersion}" - implementation "com.google.android.exoplayer:exoplayer-hls:${exoPlayerVersion}" - implementation "com.google.android.exoplayer:exoplayer-smoothstreaming:${exoPlayerVersion}" - implementation "com.google.android.exoplayer:exoplayer-ui:${exoPlayerVersion}" - implementation "com.google.android.exoplayer:extension-mediasession:${exoPlayerVersion}" - - // Metadata generator for service descriptors - compileOnly "com.google.auto.service:auto-service-annotations:${googleAutoServiceVersion}" - kapt "com.google.auto.service:auto-service:${googleAutoServiceVersion}" - - // Manager for complex RecyclerView layouts - implementation "com.github.lisawray.groupie:groupie:${groupieVersion}" - implementation "com.github.lisawray.groupie:groupie-viewbinding:${groupieVersion}" - - // Image loading - //noinspection NewerVersionAvailable,GradleDependency --> 2.8 is the last version, not 2.71828! - implementation "com.squareup.picasso:picasso:2.8" - - // Markdown library for Android - implementation "io.noties.markwon:core:${markwonVersion}" - implementation "io.noties.markwon:linkify:${markwonVersion}" - - // Crash reporting - implementation "ch.acra:acra-core:5.11.3" - - // Properly restarting - implementation 'com.jakewharton:process-phoenix:2.1.2' - - // Reactive extensions for Java VM - implementation "io.reactivex.rxjava3:rxjava:3.1.8" - implementation "io.reactivex.rxjava3:rxandroid:3.0.2" - // RxJava binding APIs for Android UI widgets - implementation "com.jakewharton.rxbinding4:rxbinding:4.0.0" - - // Date and time formatting - implementation "org.ocpsoft.prettytime:prettytime:5.0.8.Final" - -/** Debugging **/ - // Memory leak detection - debugImplementation "com.squareup.leakcanary:leakcanary-object-watcher-android:${leakCanaryVersion}" - debugImplementation "com.squareup.leakcanary:plumber-android:${leakCanaryVersion}" - debugImplementation "com.squareup.leakcanary:leakcanary-android-core:${leakCanaryVersion}" - // Debug bridge for Android - debugImplementation "com.facebook.stetho:stetho:${stethoVersion}" - debugImplementation "com.facebook.stetho:stetho-okhttp3:${stethoVersion}" - -/** Testing **/ - testImplementation 'junit:junit:4.13.2' - testImplementation 'org.mockito:mockito-core:5.6.0' - - androidTestImplementation "androidx.test.ext:junit:1.1.5" - androidTestImplementation "androidx.test:runner:1.5.2" - androidTestImplementation "androidx.room:room-testing:${androidxRoomVersion}" - androidTestImplementation "org.assertj:assertj-core:3.24.2" -} - -static String getGitWorkingBranch() { - try { - def gitProcess = "git rev-parse --abbrev-ref HEAD".execute() - gitProcess.waitFor() - if (gitProcess.exitValue() == 0) { - return gitProcess.text.trim() - } else { - // not a git repository - return "" - } - } catch (IOException ignored) { - // git was not found - return "" - } -} diff --git a/app/build.gradle.kts b/app/build.gradle.kts new file mode 100644 index 000000000..4bbb8ad93 --- /dev/null +++ b/app/build.gradle.kts @@ -0,0 +1,320 @@ +/* + * SPDX-FileCopyrightText: 2025 NewPipe e.V. + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +plugins { + id("com.android.application") + id("kotlin-android") + id("kotlin-kapt") + id("kotlin-parcelize") + id("org.sonarqube") + checkstyle +} + +val gitWorkingBranch = providers.exec { + commandLine("git", "rev-parse", "--abbrev-ref", "HEAD") +}.standardOutput.asText.map { it.trim() } + +android { + compileSdk = 36 + namespace = "org.schabi.newpipe" + + defaultConfig { + applicationId = "org.schabi.newpipe" + resValue("string", "app_name", "NewPipe") + minSdk = 21 + targetSdk = 35 + + versionCode = System.getProperty("versionCodeOverride")?.toInt() ?: 1005 + + versionName = "0.28.0" + System.getProperty("versionNameSuffix")?.let { versionNameSuffix = it } + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + + javaCompileOptions { + annotationProcessorOptions { + arguments["room.schemaLocation"] = "$projectDir/schemas" + } + } + } + + buildTypes { + debug { + isDebuggable = true + + // suffix the app id and the app name with git branch name + val defaultBranches = listOf("master", "dev") + val workingBranch = gitWorkingBranch.getOrElse("") + val normalizedWorkingBranch = workingBranch + .replaceFirst("^[^A-Za-z]+".toRegex(), "") + .replace("[^0-9A-Za-z]+".toRegex(), "") + + if (normalizedWorkingBranch.isEmpty() || workingBranch in defaultBranches) { + // default values when branch name could not be determined or is master or dev + applicationIdSuffix = ".debug" + resValue("string", "app_name", "NewPipe Debug") + } else { + applicationIdSuffix = ".debug.$normalizedWorkingBranch" + resValue("string", "app_name", "NewPipe $workingBranch") + setProperty("archivesBaseName", "NewPipe_$normalizedWorkingBranch") + } + } + + release { + System.getProperty("packageSuffix")?.let { suffix -> + applicationIdSuffix = suffix + resValue("string", "app_name", "NewPipe $suffix") + setProperty("archivesBaseName", "NewPipe_" + System.getProperty("packageSuffix")) + } + isMinifyEnabled = true + isShrinkResources = false // disabled to fix F-Droid"s reproducible build + proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") + setProperty("archivesBaseName", "app") + } + } + + lint { + checkReleaseBuilds = false + // Or, if you prefer, you can continue to check for errors in release builds, + // but continue the build even when errors are found: + abortOnError = false + // suppress false warning ("Resource IDs will be non-final in Android Gradle Plugin version + // 5.0, avoid using them in switch case statements"), which affects only library projects + disable += "NonConstantResourceId" + } + + compileOptions { + // Flag to enable support for the new language APIs + isCoreLibraryDesugaringEnabled = true + + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + encoding = "utf-8" + } + + kotlinOptions { + jvmTarget = "17" + } + + sourceSets { + getByName("androidTest") { + assets.srcDir("$projectDir/schemas") + } + } + + androidResources { + generateLocaleConfig = true + } + + buildFeatures { + viewBinding = true + buildConfig = true + } + + packaging { + resources { + // remove two files which belong to jsoup + // no idea how they ended up in the META-INF dir... + excludes += setOf( + "META-INF/README.md", + "META-INF/CHANGES", + "META-INF/COPYRIGHT" // "COPYRIGHT" belongs to RxJava... + ) + } + } +} + +val checkstyleVersion = "10.12.1" + +val androidxLifecycleVersion = "2.6.2" +val androidxRoomVersion = "2.6.1" +val androidxWorkVersion = "2.8.1" + +val stateSaverVersion = "1.4.1" +val exoPlayerVersion = "2.18.7" +val googleAutoServiceVersion = "1.1.1" +val groupieVersion = "2.10.1" +val markwonVersion = "4.6.2" + +val leakCanaryVersion = "2.12" +val stethoVersion = "1.6.0" + +val ktlint by configurations.creating + +checkstyle { + configDirectory = rootProject.file("checkstyle") + isIgnoreFailures = false + isShowViolations = true + toolVersion = checkstyleVersion +} + +tasks.register("runCheckstyle") { + source("src") + include("**/*.java") + exclude("**/gen/**") + exclude("**/R.java") + exclude("**/BuildConfig.java") + exclude("main/java/us/shandian/giga/**") + + classpath = configurations.getByName("checkstyle") + + isShowViolations = true + + reports { + xml.required = true + html.required = true + } +} + +val outputDir = project.layout.buildDirectory.dir("reports/ktlint/") +val inputFiles = fileTree("src") { include("**/*.kt") } + +tasks.register("runKtlint") { + inputs.files(inputFiles) + outputs.dir(outputDir) + mainClass.set("com.pinterest.ktlint.Main") + classpath = configurations.getByName("ktlint") + args = listOf("src/**/*.kt") + jvmArgs = listOf("--add-opens", "java.base/java.lang=ALL-UNNAMED") +} + +tasks.register("formatKtlint") { + inputs.files(inputFiles) + outputs.dir(outputDir) + mainClass.set("com.pinterest.ktlint.Main") + classpath = configurations.getByName("ktlint") + args = listOf("-F", "src/**/*.kt") + jvmArgs = listOf("--add-opens", "java.base/java.lang=ALL-UNNAMED") +} + +afterEvaluate { + tasks.named("preDebugBuild").configure { + if (!System.getProperties().containsKey("skipFormatKtlint")) { + dependsOn("formatKtlint") + } + dependsOn("runCheckstyle", "runKtlint") + } +} + +sonar { + properties { + property("sonar.projectKey", "TeamNewPipe_NewPipe") + property("sonar.organization", "teamnewpipe") + property("sonar.host.url", "https://sonarcloud.io") + } +} + +dependencies { + /** Desugaring **/ + coreLibraryDesugaring("com.android.tools:desugar_jdk_libs_nio:2.0.4") + + /** NewPipe libraries **/ + implementation("com.github.TeamNewPipe:nanojson:e9d656ddb49a412a5a0a5d5ef20ca7ef09549996") + // WORKAROUND: if you get errors with the NewPipeExtractor dependency, replace `v0.24.3` with + // the corresponding commit hash, since JitPack sometimes deletes artifacts. + // If there’s already a git hash, just add more of it to the end (or remove a letter) + // to cause jitpack to regenerate the artifact. + implementation("com.github.TeamNewPipe:NewPipeExtractor:0023b22095a2d62a60cdfc87f4b5cd85c8b266c3") + implementation("com.github.TeamNewPipe:NoNonsense-FilePicker:5.0.0") + + /** Checkstyle **/ + checkstyle("com.puppycrawl.tools:checkstyle:$checkstyleVersion") + ktlint("com.pinterest:ktlint:0.45.2") + + /** AndroidX **/ + implementation("androidx.appcompat:appcompat:1.7.1") + implementation("androidx.cardview:cardview:1.0.0") + implementation("androidx.constraintlayout:constraintlayout:2.1.4") + implementation("androidx.core:core-ktx:1.12.0") + implementation("androidx.documentfile:documentfile:1.0.1") + implementation("androidx.fragment:fragment-ktx:1.6.2") + implementation("androidx.lifecycle:lifecycle-livedata-ktx:$androidxLifecycleVersion") + implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:$androidxLifecycleVersion") + implementation("androidx.localbroadcastmanager:localbroadcastmanager:1.1.0") + implementation("androidx.media:media:1.7.0") + implementation("androidx.preference:preference:1.2.1") + implementation("androidx.recyclerview:recyclerview:1.3.2") + implementation("androidx.room:room-runtime:$androidxRoomVersion") + implementation("androidx.room:room-rxjava3:$androidxRoomVersion") + kapt("androidx.room:room-compiler:$androidxRoomVersion") + implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0") + // Newer version specified to prevent accessibility regressions with RecyclerView, see: + // https://developer.android.com/jetpack/androidx/releases/viewpager2#1.1.0-alpha01 + implementation("androidx.viewpager2:viewpager2:1.1.0-beta02") + implementation("androidx.work:work-runtime-ktx:$androidxWorkVersion") + implementation("androidx.work:work-rxjava3:$androidxWorkVersion") + implementation("com.google.android.material:material:1.11.0") + implementation("androidx.webkit:webkit:1.9.0") + + /** Third-party libraries **/ + implementation("com.github.livefront:bridge:v2.0.2") + implementation("com.evernote:android-state:$stateSaverVersion") + kapt("com.evernote:android-state-processor:$stateSaverVersion") + + // HTML parser + implementation("org.jsoup:jsoup:1.17.2") + + // HTTP client + implementation("com.squareup.okhttp3:okhttp:4.12.0") + + // Media player + implementation("com.google.android.exoplayer:exoplayer-core:$exoPlayerVersion") + implementation("com.google.android.exoplayer:exoplayer-dash:$exoPlayerVersion") + implementation("com.google.android.exoplayer:exoplayer-database:$exoPlayerVersion") + implementation("com.google.android.exoplayer:exoplayer-datasource:$exoPlayerVersion") + implementation("com.google.android.exoplayer:exoplayer-hls:$exoPlayerVersion") + implementation("com.google.android.exoplayer:exoplayer-smoothstreaming:$exoPlayerVersion") + implementation("com.google.android.exoplayer:exoplayer-ui:$exoPlayerVersion") + implementation("com.google.android.exoplayer:extension-mediasession:$exoPlayerVersion") + + // Metadata generator for service descriptors + compileOnly("com.google.auto.service:auto-service-annotations:$googleAutoServiceVersion") + kapt("com.google.auto.service:auto-service:$googleAutoServiceVersion") + + // Manager for complex RecyclerView layouts + implementation("com.github.lisawray.groupie:groupie:$groupieVersion") + implementation("com.github.lisawray.groupie:groupie-viewbinding:$groupieVersion") + + // Image loading + //noinspection NewerVersionAvailable,GradleDependency --> 2.8 is the last version, not 2.71828! + implementation("com.squareup.picasso:picasso:2.8") + + // Markdown library for Android + implementation("io.noties.markwon:core:$markwonVersion") + implementation("io.noties.markwon:linkify:$markwonVersion") + + // Crash reporting + implementation("ch.acra:acra-core:5.11.3") + + // Properly restarting + implementation("com.jakewharton:process-phoenix:2.1.2") + + // Reactive extensions for Java VM + implementation("io.reactivex.rxjava3:rxjava:3.1.8") + implementation("io.reactivex.rxjava3:rxandroid:3.0.2") + // RxJava binding APIs for Android UI widgets + implementation("com.jakewharton.rxbinding4:rxbinding:4.0.0") + + // Date and time formatting + implementation("org.ocpsoft.prettytime:prettytime:5.0.8.Final") + + /** Debugging **/ + // Memory leak detection + debugImplementation("com.squareup.leakcanary:leakcanary-object-watcher-android:$leakCanaryVersion") + debugImplementation("com.squareup.leakcanary:plumber-android:$leakCanaryVersion") + debugImplementation("com.squareup.leakcanary:leakcanary-android-core:$leakCanaryVersion") + // Debug bridge for Android + debugImplementation("com.facebook.stetho:stetho:$stethoVersion") + debugImplementation("com.facebook.stetho:stetho-okhttp3:$stethoVersion") + + /** Testing **/ + testImplementation("junit:junit:4.13.2") + testImplementation("org.mockito:mockito-core:5.6.0") + + androidTestImplementation("androidx.test.ext:junit:1.1.5") + androidTestImplementation("androidx.test:runner:1.5.2") + androidTestImplementation("androidx.room:room-testing:$androidxRoomVersion") + androidTestImplementation("org.assertj:assertj-core:3.24.2") +} diff --git a/build.gradle b/build.gradle deleted file mode 100644 index 3cdc0dc59..000000000 --- a/build.gradle +++ /dev/null @@ -1,25 +0,0 @@ -// Top-level build file where you can add configuration options common to all sub-projects/modules. - -buildscript { - ext.kotlin_version = '1.9.25' - repositories { - google() - mavenCentral() - } - dependencies { - classpath 'com.android.tools.build:gradle:8.13.0' - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - - // NOTE: Do not place your application dependencies here; they belong - // in the individual module build.gradle files - } -} - -allprojects { - repositories { - google() - mavenCentral() - maven { url "https://jitpack.io" } - maven { url "https://repo.clojars.org" } - } -} diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 000000000..d08a3cda5 --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,12 @@ +/* + * SPDX-FileCopyrightText: 2025 NewPipe e.V. + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +plugins { + id("com.android.application") version "8.13.0" apply false + id("org.jetbrains.kotlin.android") version "1.9.25" apply false + id("org.jetbrains.kotlin.kapt") version "1.9.25" apply false + id("org.jetbrains.kotlin.plugin.parcelize") version "1.9.25" apply false + id("org.sonarqube") version "4.0.0.2929" apply false +} diff --git a/settings.gradle b/settings.gradle deleted file mode 100644 index 0338fde6c..000000000 --- a/settings.gradle +++ /dev/null @@ -1,11 +0,0 @@ -include ':app' - -// Use a local copy of NewPipe Extractor by uncommenting the lines below. -// We assume, that NewPipe and NewPipe Extractor have the same parent directory. -// If this is not the case, please change the path in includeBuild(). - -//includeBuild('../NewPipeExtractor') { -// dependencySubstitution { -// substitute module('com.github.TeamNewPipe:NewPipeExtractor') using project(':extractor') -// } -//} diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 000000000..d9e899151 --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1,32 @@ +/* + * SPDX-FileCopyrightText: 2025 NewPipe e.V. + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +pluginManagement { + repositories { + gradlePluginPortal() + google() + mavenCentral() + } +} +dependencyResolutionManagement { + repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) + repositories { + google() + mavenCentral() + maven(url = "https://jitpack.io") + maven(url = "https://repo.clojars.org") + } +} +include (":app") + +// Use a local copy of NewPipe Extractor by uncommenting the lines below. +// We assume, that NewPipe and NewPipe Extractor have the same parent directory. +// If this is not the case, please change the path in includeBuild(). + +//includeBuild('../NewPipeExtractor') { +// dependencySubstitution { +// substitute module('com.github.TeamNewPipe:NewPipeExtractor') using project(':extractor') +// } +//} From 15089245bb48faa3ce42d049f0b0dbb8adaab9c3 Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Wed, 15 Oct 2025 12:58:54 +0800 Subject: [PATCH 3/6] Migrate to build version catalog Ref: https://developer.android.com/build/migrate-to-catalogs Signed-off-by: Aayush Gupta --- app/build.gradle.kts | 163 +++++++++++++++++--------------------- build.gradle.kts | 10 +-- gradle/libs.versions.toml | 130 ++++++++++++++++++++++++++++++ 3 files changed, 206 insertions(+), 97 deletions(-) create mode 100644 gradle/libs.versions.toml diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 4bbb8ad93..e5f9ce3e4 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -4,11 +4,11 @@ */ plugins { - id("com.android.application") - id("kotlin-android") - id("kotlin-kapt") - id("kotlin-parcelize") - id("org.sonarqube") + alias(libs.plugins.android.application) + alias(libs.plugins.jetbrains.kotlin.android) + alias(libs.plugins.jetbrains.kotlin.kapt) + alias(libs.plugins.jetbrains.kotlin.parcelize) + alias(libs.plugins.sonarqube) checkstyle } @@ -126,28 +126,14 @@ android { } } -val checkstyleVersion = "10.12.1" - -val androidxLifecycleVersion = "2.6.2" -val androidxRoomVersion = "2.6.1" -val androidxWorkVersion = "2.8.1" - -val stateSaverVersion = "1.4.1" -val exoPlayerVersion = "2.18.7" -val googleAutoServiceVersion = "1.1.1" -val groupieVersion = "2.10.1" -val markwonVersion = "4.6.2" - -val leakCanaryVersion = "2.12" -val stethoVersion = "1.6.0" - +// Custom dependency configuration for ktlint val ktlint by configurations.creating checkstyle { configDirectory = rootProject.file("checkstyle") isIgnoreFailures = false isShowViolations = true - toolVersion = checkstyleVersion + toolVersion = libs.versions.checkstyle.get() } tasks.register("runCheckstyle") { @@ -208,113 +194,106 @@ sonar { dependencies { /** Desugaring **/ - coreLibraryDesugaring("com.android.tools:desugar_jdk_libs_nio:2.0.4") + coreLibraryDesugaring(libs.android.desugar) /** NewPipe libraries **/ - implementation("com.github.TeamNewPipe:nanojson:e9d656ddb49a412a5a0a5d5ef20ca7ef09549996") - // WORKAROUND: if you get errors with the NewPipeExtractor dependency, replace `v0.24.3` with - // the corresponding commit hash, since JitPack sometimes deletes artifacts. - // If there’s already a git hash, just add more of it to the end (or remove a letter) - // to cause jitpack to regenerate the artifact. - implementation("com.github.TeamNewPipe:NewPipeExtractor:0023b22095a2d62a60cdfc87f4b5cd85c8b266c3") - implementation("com.github.TeamNewPipe:NoNonsense-FilePicker:5.0.0") + implementation(libs.newpipe.nanojson) + implementation(libs.newpipe.extractor) + implementation(libs.newpipe.filepicker) /** Checkstyle **/ - checkstyle("com.puppycrawl.tools:checkstyle:$checkstyleVersion") - ktlint("com.pinterest:ktlint:0.45.2") + checkstyle(libs.puppycrawl.checkstyle) + ktlint(libs.pinterest.ktlint) /** AndroidX **/ - implementation("androidx.appcompat:appcompat:1.7.1") - implementation("androidx.cardview:cardview:1.0.0") - implementation("androidx.constraintlayout:constraintlayout:2.1.4") - implementation("androidx.core:core-ktx:1.12.0") - implementation("androidx.documentfile:documentfile:1.0.1") - implementation("androidx.fragment:fragment-ktx:1.6.2") - implementation("androidx.lifecycle:lifecycle-livedata-ktx:$androidxLifecycleVersion") - implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:$androidxLifecycleVersion") - implementation("androidx.localbroadcastmanager:localbroadcastmanager:1.1.0") - implementation("androidx.media:media:1.7.0") - implementation("androidx.preference:preference:1.2.1") - implementation("androidx.recyclerview:recyclerview:1.3.2") - implementation("androidx.room:room-runtime:$androidxRoomVersion") - implementation("androidx.room:room-rxjava3:$androidxRoomVersion") - kapt("androidx.room:room-compiler:$androidxRoomVersion") - implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0") - // Newer version specified to prevent accessibility regressions with RecyclerView, see: - // https://developer.android.com/jetpack/androidx/releases/viewpager2#1.1.0-alpha01 - implementation("androidx.viewpager2:viewpager2:1.1.0-beta02") - implementation("androidx.work:work-runtime-ktx:$androidxWorkVersion") - implementation("androidx.work:work-rxjava3:$androidxWorkVersion") - implementation("com.google.android.material:material:1.11.0") - implementation("androidx.webkit:webkit:1.9.0") + implementation(libs.androidx.appcompat) + implementation(libs.androidx.cardview) + implementation(libs.androidx.constraintlayout) + implementation(libs.androidx.core) + implementation(libs.androidx.documentfile) + implementation(libs.androidx.fragment) + implementation(libs.androidx.lifecycle.livedata) + implementation(libs.androidx.lifecycle.viewmodel) + implementation(libs.androidx.localbroadcastmanager) + implementation(libs.androidx.media) + implementation(libs.androidx.preference) + implementation(libs.androidx.recyclerview) + implementation(libs.androidx.room.runtime) + implementation(libs.androidx.room.rxjava3) + kapt(libs.androidx.room.compiler) + implementation(libs.androidx.swiperefreshlayout) + implementation(libs.androidx.viewpager2) + implementation(libs.androidx.work.runtime) + implementation(libs.androidx.work.rxjava3) + implementation(libs.google.android.material) + implementation(libs.androidx.webkit) /** Third-party libraries **/ - implementation("com.github.livefront:bridge:v2.0.2") - implementation("com.evernote:android-state:$stateSaverVersion") - kapt("com.evernote:android-state-processor:$stateSaverVersion") + implementation(libs.livefront.bridge) + implementation(libs.evernote.statesaver.core) + kapt(libs.evernote.statesaver.compiler) // HTML parser - implementation("org.jsoup:jsoup:1.17.2") + implementation(libs.jsoup) // HTTP client - implementation("com.squareup.okhttp3:okhttp:4.12.0") + implementation(libs.squareup.okhttp) // Media player - implementation("com.google.android.exoplayer:exoplayer-core:$exoPlayerVersion") - implementation("com.google.android.exoplayer:exoplayer-dash:$exoPlayerVersion") - implementation("com.google.android.exoplayer:exoplayer-database:$exoPlayerVersion") - implementation("com.google.android.exoplayer:exoplayer-datasource:$exoPlayerVersion") - implementation("com.google.android.exoplayer:exoplayer-hls:$exoPlayerVersion") - implementation("com.google.android.exoplayer:exoplayer-smoothstreaming:$exoPlayerVersion") - implementation("com.google.android.exoplayer:exoplayer-ui:$exoPlayerVersion") - implementation("com.google.android.exoplayer:extension-mediasession:$exoPlayerVersion") + implementation(libs.google.exoplayer.core) + implementation(libs.google.exoplayer.dash) + implementation(libs.google.exoplayer.database) + implementation(libs.google.exoplayer.datasource) + implementation(libs.google.exoplayer.hls) + implementation(libs.google.exoplayer.mediasession) + implementation(libs.google.exoplayer.smoothstreaming) + implementation(libs.google.exoplayer.ui) // Metadata generator for service descriptors - compileOnly("com.google.auto.service:auto-service-annotations:$googleAutoServiceVersion") - kapt("com.google.auto.service:auto-service:$googleAutoServiceVersion") + compileOnly(libs.google.autoservice.annotations) + kapt(libs.google.autoservice.compiler) // Manager for complex RecyclerView layouts - implementation("com.github.lisawray.groupie:groupie:$groupieVersion") - implementation("com.github.lisawray.groupie:groupie-viewbinding:$groupieVersion") + implementation(libs.lisawray.groupie.core) + implementation(libs.lisawray.groupie.viewbinding) // Image loading - //noinspection NewerVersionAvailable,GradleDependency --> 2.8 is the last version, not 2.71828! - implementation("com.squareup.picasso:picasso:2.8") + implementation(libs.squareup.picasso) // Markdown library for Android - implementation("io.noties.markwon:core:$markwonVersion") - implementation("io.noties.markwon:linkify:$markwonVersion") + implementation(libs.noties.markwon.core) + implementation(libs.noties.markwon.linkify) // Crash reporting - implementation("ch.acra:acra-core:5.11.3") + implementation(libs.acra.core) // Properly restarting - implementation("com.jakewharton:process-phoenix:2.1.2") + implementation(libs.jakewharton.phoenix) // Reactive extensions for Java VM - implementation("io.reactivex.rxjava3:rxjava:3.1.8") - implementation("io.reactivex.rxjava3:rxandroid:3.0.2") + implementation(libs.reactivex.rxjava) + implementation(libs.reactivex.rxandroid) // RxJava binding APIs for Android UI widgets - implementation("com.jakewharton.rxbinding4:rxbinding:4.0.0") + implementation(libs.jakewharton.rxbinding) // Date and time formatting - implementation("org.ocpsoft.prettytime:prettytime:5.0.8.Final") + implementation(libs.ocpsoft.prettytime) /** Debugging **/ // Memory leak detection - debugImplementation("com.squareup.leakcanary:leakcanary-object-watcher-android:$leakCanaryVersion") - debugImplementation("com.squareup.leakcanary:plumber-android:$leakCanaryVersion") - debugImplementation("com.squareup.leakcanary:leakcanary-android-core:$leakCanaryVersion") + debugImplementation(libs.squareup.leakcanary.watcher) + debugImplementation(libs.squareup.leakcanary.plumber) + debugImplementation(libs.squareup.leakcanary.core) // Debug bridge for Android - debugImplementation("com.facebook.stetho:stetho:$stethoVersion") - debugImplementation("com.facebook.stetho:stetho-okhttp3:$stethoVersion") + debugImplementation(libs.facebook.stetho.core) + debugImplementation(libs.facebook.stetho.okhttp3) /** Testing **/ - testImplementation("junit:junit:4.13.2") - testImplementation("org.mockito:mockito-core:5.6.0") + testImplementation(libs.junit) + testImplementation(libs.mockito.core) - androidTestImplementation("androidx.test.ext:junit:1.1.5") - androidTestImplementation("androidx.test:runner:1.5.2") - androidTestImplementation("androidx.room:room-testing:$androidxRoomVersion") - androidTestImplementation("org.assertj:assertj-core:3.24.2") + androidTestImplementation(libs.androidx.junit) + androidTestImplementation(libs.androidx.runner) + androidTestImplementation(libs.androidx.room.testing) + androidTestImplementation(libs.assertj.core) } diff --git a/build.gradle.kts b/build.gradle.kts index d08a3cda5..e79ccc3e0 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -4,9 +4,9 @@ */ plugins { - id("com.android.application") version "8.13.0" apply false - id("org.jetbrains.kotlin.android") version "1.9.25" apply false - id("org.jetbrains.kotlin.kapt") version "1.9.25" apply false - id("org.jetbrains.kotlin.plugin.parcelize") version "1.9.25" apply false - id("org.sonarqube") version "4.0.0.2929" apply false + alias(libs.plugins.android.application) apply false + alias(libs.plugins.jetbrains.kotlin.android) apply false + alias(libs.plugins.jetbrains.kotlin.kapt) apply false + alias(libs.plugins.jetbrains.kotlin.parcelize) apply false + alias(libs.plugins.sonarqube) apply false } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml new file mode 100644 index 000000000..f0718d4fb --- /dev/null +++ b/gradle/libs.versions.toml @@ -0,0 +1,130 @@ +# +# SPDX-FileCopyrightText: 2025 NewPipe e.V. +# SPDX-License-Identifier: GPL-3.0-or-later +# + +[versions] +acra = "5.11.3" +agp = "8.13.0" +appcompat = "1.7.1" +assertj = "3.24.2" +autoservice = "1.1.1" +bridge = "v2.0.2" +cardview = "1.0.0" +checkstyle = "10.12.1" +constraintlayout = "2.1.4" +core = "1.12.0" +desugar = "2.0.4" +documentfile = "1.0.1" +exoplayer = "2.18.7" +extractor = "0023b22095a2d62a60cdfc87f4b5cd85c8b266c3" +filepicker = "5.0.0" +fragment = "1.6.2" +groupie = "2.10.1" +jsoup = "1.17.2" +junit = "4.13.2" +junit-ext = "1.1.5" +kotlin = "1.9.25" +ktlint = "0.45.2" +leakcanary = "2.12" +lifecycle = "2.6.2" +localbroadcastmanager = "1.1.0" +markwon = "4.6.2" +material = "1.11.0" +media = "1.7.0" +mockitoCore = "5.6.0" +nanojson = "e9d656ddb49a412a5a0a5d5ef20ca7ef09549996" +okhttp = "4.12.0" +phoenix = "2.1.2" +#noinspection NewerVersionAvailable,GradleDependency --> 2.8 is the last version, not 2.71828! +picasso = "2.8" +preference = "1.2.1" +prettytime = "5.0.8.Final" +recyclerview = "1.3.2" +room = "2.6.1" +runner = "1.5.2" +rxandroid = "3.0.2" +rxbinding = "4.0.0" +rxjava = "3.1.8" +sonarqube = "4.0.0.2929" +statesaver = "1.4.1" +stetho = "1.6.0" +swiperefreshlayout = "1.1.0" +# Newer version specified to prevent accessibility regressions with RecyclerView +# see: https://developer.android.com/jetpack/androidx/releases/viewpager2#1.1.0-alpha01 +viewpager2 = "1.1.0-beta02" +webkit = "1.9.0" +work = "2.8.1" + +[libraries] +acra-core = { module = "ch.acra:acra-core", version.ref = "acra" } +android-desugar = { module = "com.android.tools:desugar_jdk_libs_nio", version.ref = "desugar" } +androidx-appcompat = { module = "androidx.appcompat:appcompat", version.ref = "appcompat" } +androidx-cardview = { module = "androidx.cardview:cardview", version.ref = "cardview" } +androidx-constraintlayout = { module = "androidx.constraintlayout:constraintlayout", version.ref = "constraintlayout" } +androidx-core = { module = "androidx.core:core-ktx", version.ref = "core" } +androidx-documentfile = { module = "androidx.documentfile:documentfile", version.ref = "documentfile" } +androidx-fragment = { module = "androidx.fragment:fragment-ktx", version.ref = "fragment" } +androidx-junit = { module = "androidx.test.ext:junit", version.ref = "junit-ext" } +androidx-lifecycle-livedata = { module = "androidx.lifecycle:lifecycle-livedata-ktx", version.ref = "lifecycle" } +androidx-lifecycle-viewmodel = { module = "androidx.lifecycle:lifecycle-viewmodel-ktx", version.ref = "lifecycle" } +androidx-localbroadcastmanager = { module = "androidx.localbroadcastmanager:localbroadcastmanager", version.ref = "localbroadcastmanager" } +androidx-media = { module = "androidx.media:media", version.ref = "media" } +androidx-preference = { module = "androidx.preference:preference", version.ref = "preference" } +androidx-recyclerview = { module = "androidx.recyclerview:recyclerview", version.ref = "recyclerview" } +androidx-room-compiler = { module = "androidx.room:room-compiler", version.ref = "room" } +androidx-room-runtime = { module = "androidx.room:room-runtime", version.ref = "room" } +androidx-room-rxjava3 = { module = "androidx.room:room-rxjava3", version.ref = "room" } +androidx-room-testing = { module = "androidx.room:room-testing", version.ref = "room" } +androidx-runner = { module = "androidx.test:runner", version.ref = "runner" } +androidx-swiperefreshlayout = { module = "androidx.swiperefreshlayout:swiperefreshlayout", version.ref = "swiperefreshlayout" } +androidx-viewpager2 = { module = "androidx.viewpager2:viewpager2", version.ref = "viewpager2" } +androidx-webkit = { module = "androidx.webkit:webkit", version.ref = "webkit" } +androidx-work-runtime = { module = "androidx.work:work-runtime-ktx", version.ref = "work" } +androidx-work-rxjava3 = { module = "androidx.work:work-rxjava3", version.ref = "work" } +assertj-core = { module = "org.assertj:assertj-core", version.ref = "assertj" } +evernote-statesaver-compiler = { module = "com.evernote:android-state-processor", version.ref = "statesaver" } +evernote-statesaver-core = { module = "com.evernote:android-state", version.ref = "statesaver" } +facebook-stetho-core = { module = "com.facebook.stetho:stetho", version.ref = "stetho" } +facebook-stetho-okhttp3 = { module = "com.facebook.stetho:stetho-okhttp3", version.ref = "stetho" } +google-android-material = { module = "com.google.android.material:material", version.ref = "material" } +google-autoservice-annotations = { module = "com.google.auto.service:auto-service-annotations", version.ref = "autoservice" } +google-autoservice-compiler = { module = "com.google.auto.service:auto-service", version.ref = "autoservice" } +google-exoplayer-core = { module = "com.google.android.exoplayer:exoplayer-core", version.ref = "exoplayer" } +google-exoplayer-dash = { module = "com.google.android.exoplayer:exoplayer-dash", version.ref = "exoplayer" } +google-exoplayer-database = { module = "com.google.android.exoplayer:exoplayer-database", version.ref = "exoplayer" } +google-exoplayer-datasource = { module = "com.google.android.exoplayer:exoplayer-datasource", version.ref = "exoplayer" } +google-exoplayer-hls = { module = "com.google.android.exoplayer:exoplayer-hls", version.ref = "exoplayer" } +google-exoplayer-mediasession = { module = "com.google.android.exoplayer:extension-mediasession", version.ref = "exoplayer" } +google-exoplayer-smoothstreaming = { module = "com.google.android.exoplayer:exoplayer-smoothstreaming", version.ref = "exoplayer" } +google-exoplayer-ui = { module = "com.google.android.exoplayer:exoplayer-ui", version.ref = "exoplayer" } +jakewharton-phoenix = { module = "com.jakewharton:process-phoenix", version.ref = "phoenix" } +jakewharton-rxbinding = { module = "com.jakewharton.rxbinding4:rxbinding", version.ref = "rxbinding" } +jsoup = { module = "org.jsoup:jsoup", version.ref = "jsoup" } +junit = { module = "junit:junit", version.ref = "junit" } +lisawray-groupie-core = { module = "com.github.lisawray.groupie:groupie", version.ref = "groupie" } +lisawray-groupie-viewbinding = { module = "com.github.lisawray.groupie:groupie-viewbinding", version.ref = "groupie" } +livefront-bridge = { module = "com.github.livefront:bridge", version.ref = "bridge" } +mockito-core = { module = "org.mockito:mockito-core", version.ref = "mockitoCore" } +newpipe-extractor = { module = "com.github.TeamNewPipe:NewPipeExtractor", version.ref = "extractor" } +newpipe-filepicker = { module = "com.github.TeamNewPipe:NoNonsense-FilePicker", version.ref = "filepicker" } +newpipe-nanojson = { module = "com.github.TeamNewPipe:nanojson", version.ref = "nanojson" } +noties-markwon-core = { module = "io.noties.markwon:core", version.ref = "markwon" } +noties-markwon-linkify = { module = "io.noties.markwon:linkify", version.ref = "markwon" } +ocpsoft-prettytime = { module = "org.ocpsoft.prettytime:prettytime", version.ref = "prettytime" } +pinterest-ktlint = { module = "com.pinterest:ktlint", version.ref = "ktlint" } +puppycrawl-checkstyle = { module = "com.puppycrawl.tools:checkstyle", version.ref = "checkstyle" } +reactivex-rxandroid = { module = "io.reactivex.rxjava3:rxandroid", version.ref = "rxandroid" } +reactivex-rxjava = { module = "io.reactivex.rxjava3:rxjava", version.ref = "rxjava" } +squareup-leakcanary-core = { module = "com.squareup.leakcanary:leakcanary-android-core", version.ref = "leakcanary" } +squareup-leakcanary-plumber = { module = "com.squareup.leakcanary:plumber-android", version.ref = "leakcanary" } +squareup-leakcanary-watcher = { module = "com.squareup.leakcanary:leakcanary-object-watcher-android", version.ref = "leakcanary" } +squareup-okhttp = { module = "com.squareup.okhttp3:okhttp", version.ref = "okhttp" } +squareup-picasso = { module = "com.squareup.picasso:picasso", version.ref = "picasso" } + +[plugins] +android-application = { id = "com.android.application", version.ref = "agp" } +jetbrains-kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } +jetbrains-kotlin-kapt = { id = "org.jetbrains.kotlin.kapt", version.ref = "kotlin" } +jetbrains-kotlin-parcelize = { id = "org.jetbrains.kotlin.plugin.parcelize", version.ref = "kotlin" } +sonarqube = { id = "org.sonarqube", version.ref = "sonarqube" } From 061ce870aca24005e4fbd301887aceb1ac6eeb72 Mon Sep 17 00:00:00 2001 From: Jie Li Date: Tue, 26 Nov 2024 18:32:44 +0000 Subject: [PATCH 4/6] Gradle script to enforce dependencies order Signed-off-by: Aayush Gupta --- app/build.gradle.kts | 4 ++- app/check-dependencies.gradle.kts | 59 +++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 app/check-dependencies.gradle.kts diff --git a/app/build.gradle.kts b/app/build.gradle.kts index e5f9ce3e4..8dd1594f2 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -12,6 +12,8 @@ plugins { checkstyle } +apply(from = "check-dependencies.gradle.kts") + val gitWorkingBranch = providers.exec { commandLine("git", "rev-parse", "--abbrev-ref", "HEAD") }.standardOutput.asText.map { it.trim() } @@ -180,7 +182,7 @@ afterEvaluate { if (!System.getProperties().containsKey("skipFormatKtlint")) { dependsOn("formatKtlint") } - dependsOn("runCheckstyle", "runKtlint") + dependsOn("runCheckstyle", "runKtlint", "checkDependenciesOrder") } } diff --git a/app/check-dependencies.gradle.kts b/app/check-dependencies.gradle.kts new file mode 100644 index 000000000..fc77148db --- /dev/null +++ b/app/check-dependencies.gradle.kts @@ -0,0 +1,59 @@ +/* + * SPDX-FileCopyrightText: 2024 NewPipe contributors + * SPDX-FileCopyrightText: 2025 NewPipe e.V. + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +tasks.register("checkDependenciesOrder") { + group = "verification" + description = "Checks that each section in libs.versions.toml is sorted alphabetically" + + val tomlFile = file("../gradle/libs.versions.toml") + + doLast { + if (!tomlFile.exists()) { + throw GradleException("TOML file not found") + } + + val lines = tomlFile.readLines() + val nonSortedBlocks = mutableListOf>() + var currentBlock = mutableListOf() + var prevLine = "" + var prevIndex = 0 + + lines.forEachIndexed { lineIndex, line -> + if (line.trim().isNotEmpty() && !line.startsWith("#")) { + if (line.startsWith("[")) { + prevLine = "" + } else { + val currIndex = lineIndex + 1 + if (prevLine > line) { + if (currentBlock.isNotEmpty() && currentBlock.last() == "$prevIndex: $prevLine") { + currentBlock.add("$currIndex: $line") + } else { + if (currentBlock.isNotEmpty()) { + nonSortedBlocks.add(currentBlock) + currentBlock = mutableListOf() + } + currentBlock.add("$prevIndex: $prevLine") + currentBlock.add("$currIndex: $line") + } + } + prevLine = line + prevIndex = lineIndex + 1 + } + } + } + + if (currentBlock.isNotEmpty()) { + nonSortedBlocks.add(currentBlock) + } + + if (nonSortedBlocks.isNotEmpty()) { + throw GradleException( + "The following lines were not sorted:\n" + + nonSortedBlocks.joinToString("\n\n") { it.joinToString("\n") } + ) + } + } +} From 1bef2fdc253c5d7a6574258a06f6da071ed4f5ad Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Thu, 16 Oct 2025 22:27:56 +0800 Subject: [PATCH 5/6] Drop deprecated non-working archivesBaseName property Signed-off-by: Aayush Gupta --- app/build.gradle.kts | 3 --- 1 file changed, 3 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 8dd1594f2..e4c186e50 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -60,7 +60,6 @@ android { } else { applicationIdSuffix = ".debug.$normalizedWorkingBranch" resValue("string", "app_name", "NewPipe $workingBranch") - setProperty("archivesBaseName", "NewPipe_$normalizedWorkingBranch") } } @@ -68,12 +67,10 @@ android { System.getProperty("packageSuffix")?.let { suffix -> applicationIdSuffix = suffix resValue("string", "app_name", "NewPipe $suffix") - setProperty("archivesBaseName", "NewPipe_" + System.getProperty("packageSuffix")) } isMinifyEnabled = true isShrinkResources = false // disabled to fix F-Droid"s reproducible build proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") - setProperty("archivesBaseName", "app") } } From ee01ba32099558c35bf4279bd771ab8616142622 Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Fri, 17 Oct 2025 16:25:51 +0800 Subject: [PATCH 6/6] Specify JDK toolchain directly Specifying JDK toolchain in the java block lets us avoid specifying same version again and again for different options while ensuring everything is on the same version Ref: https://developer.android.com/build/jdks#toolchain Signed-off-by: Aayush Gupta --- app/build.gradle.kts | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index e4c186e50..037c3cb53 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -18,6 +18,12 @@ val gitWorkingBranch = providers.exec { commandLine("git", "rev-parse", "--abbrev-ref", "HEAD") }.standardOutput.asText.map { it.trim() } +java { + toolchain { + languageVersion = JavaLanguageVersion.of(17) + } +} + android { compileSdk = 36 namespace = "org.schabi.newpipe" @@ -87,16 +93,9 @@ android { compileOptions { // Flag to enable support for the new language APIs isCoreLibraryDesugaringEnabled = true - - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 encoding = "utf-8" } - kotlinOptions { - jvmTarget = "17" - } - sourceSets { getByName("androidTest") { assets.srcDir("$projectDir/schemas")