Update to Kotlin 2.1.0 and add spotless linter (#7447)

* update kotlin & deps

* add spotless

* fetch depth

* lint...

* adjust rules

* Revert "lint..."

This reverts commit cc2f99fb218726d90045c5104ab9592a179cb6b6.

* lint

* rm generated file
This commit is contained in:
AwkwardPeak7 2025-02-02 12:20:28 +05:00 committed by Draff
parent 86a24181b5
commit 4867bf18a0
No known key found for this signature in database
GPG Key ID: E8A89F3211677653
9 changed files with 126 additions and 112 deletions

View File

@ -12,5 +12,5 @@ dependencies {
implementation(libs.gradle.agp)
implementation(libs.gradle.kotlin)
implementation(libs.gradle.serialization)
implementation(libs.gradle.kotlinter)
implementation(libs.spotless.gradle)
}

View File

@ -0,0 +1,50 @@
plugins {
id("com.diffplug.spotless")
}
spotless {
ratchetFrom = "105f615b339e681a630f21dc0d363b8ca1cb17d5"
kotlin {
target("**/*.kt", "**/*.kts")
targetExclude("**/build/**/*.kt")
ktlint()
.editorConfigOverride(mapOf(
"ktlint_standard_discouraged-comment-location" to "disabled",
"ktlint_function_signature_body_expression_wrapping" to "default",
"ktlint_standard_no-empty-first-line-in-class-body" to "disable",
"ktlint_standard_chain-method-continuation" to "disable"
))
trimTrailingWhitespace()
endWithNewline()
}
format("gradle") {
target("**/*.gradle")
trimTrailingWhitespace()
endWithNewline()
}
format("xml") {
target("**/*.xml")
targetExclude("**/build/**/*.xml")
trimTrailingWhitespace()
endWithNewline()
}
}
tasks {
named("preBuild") {
dependsOn(
tasks.getByName("spotlessCheck")
)
}
if (System.getenv("CI") != "true") {
named("spotlessCheck") {
dependsOn(
tasks.getByName("spotlessApply")
)
}
}
}

View File

@ -2,6 +2,7 @@ plugins {
id("com.android.library")
kotlin("android")
id("kotlinx-serialization")
id("keiyoushi.lint")
}
android {
@ -16,6 +17,16 @@ android {
buildFeatures {
androidResources = false
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = JavaVersion.VERSION_17.toString()
freeCompilerArgs += "-opt-in=kotlinx.serialization.ExperimentalSerializationApi"
}
}
dependencies {

View File

@ -2,7 +2,7 @@ plugins {
id("com.android.library")
kotlin("android")
id("kotlinx-serialization")
id("org.jmailen.kotlinter")
id("keiyoushi.lint")
}
android {
@ -23,31 +23,23 @@ android {
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = JavaVersion.VERSION_17.toString()
freeCompilerArgs += "-opt-in=kotlinx.serialization.ExperimentalSerializationApi"
}
}
kotlinter {
experimentalRules = true
disabledRules = arrayOf(
"experimental:argument-list-wrapping", // Doesn't play well with Android Studio
"experimental:comment-wrapping",
)
}
dependencies {
compileOnly(versionCatalogs.named("libs").findBundle("common").get())
}
tasks {
preBuild {
dependsOn(lintKotlin)
}
if (System.getenv("CI") != "true") {
lintKotlin {
dependsOn(formatKotlin)
}
tasks.register("printDependentExtensions") {
doLast {
project.printDependentExtensions()
}
}

View File

@ -1,7 +1,7 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlinx-serialization'
apply plugin: 'org.jmailen.kotlinter'
apply plugin: 'keiyoushi.lint'
assert !ext.has("pkgNameSuffix")
assert !ext.has("libVersion")
@ -18,6 +18,17 @@ android {
sourceSets {
main {
manifest.srcFile "AndroidManifest.xml"
if (!manifest.srcFile.exists()) {
def buildDir = layout.buildDirectory.get().getAsFile().path
mkdir(buildDir)
File tempFile = new File(buildDir, "tempAndroidManifest.xml")
if (!tempFile.exists()) {
tempFile.withWriter {
it.write('<?xml version="1.0" encoding="utf-8"?>\n<manifest />\n')
}
}
manifest.srcFile(tempFile.path)
}
java.srcDirs = ['src']
res.srcDirs = ['res']
assets.srcDirs = ['assets']
@ -81,22 +92,14 @@ android {
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = JavaVersion.VERSION_1_8.toString()
jvmTarget = JavaVersion.VERSION_17.toString()
freeCompilerArgs += "-opt-in=kotlinx.serialization.ExperimentalSerializationApi"
}
kotlinter {
experimentalRules = true
disabledRules = [
"experimental:argument-list-wrapping", // Doesn't play well with Android Studio
"experimental:comment-wrapping",
]
}
}
dependencies {
@ -104,23 +107,3 @@ dependencies {
implementation(project(":core"))
compileOnly(libs.bundles.common)
}
tasks.register("writeManifestFile") {
doLast {
def manifest = android.sourceSets.getByName("main").manifest
if (!manifest.srcFile.exists()) {
File tempFile = layout.buildDirectory.get().file("tempAndroidManifest.xml").getAsFile()
if (!tempFile.exists()) {
tempFile.withWriter {
it.write('<?xml version="1.0" encoding="utf-8"?>\n<manifest />\n')
}
}
manifest.srcFile(tempFile.path)
}
}
}
preBuild.dependsOn(writeManifestFile, lintKotlin)
if (System.getenv("CI") != "true") {
lintKotlin.dependsOn(formatKotlin)
}

View File

@ -1,13 +1,14 @@
[versions]
kotlin_version = "1.7.21"
coroutines_version = "1.6.4"
serialization_version = "1.4.0"
kotlin_version = "2.1.0"
coroutines_version = "1.10.1"
serialization_version = "1.8.0"
[libraries]
gradle-agp = { module = "com.android.tools.build:gradle", version = "8.6.1" }
gradle-agp = { module = "com.android.tools.build:gradle", version = "8.8.0" }
gradle-kotlin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin_version" }
gradle-serialization = { module = "org.jetbrains.kotlin:kotlin-serialization", version.ref = "kotlin_version" }
gradle-kotlinter = { module = "org.jmailen.gradle:kotlinter-gradle", version = "3.13.0" }
spotless-gradle = { group = "com.diffplug.spotless", name = "spotless-plugin-gradle", version = "7.0.2" }
tachiyomi-lib = { module = "com.github.tachiyomiorg:extensions-lib", version = "1.4.2" }
@ -20,8 +21,8 @@ coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-androi
injekt-core = { module = "com.github.null2264.injekt:injekt-core", version = "4135455a2a" }
rxjava = { module = "io.reactivex:rxjava", version = "1.3.8" }
jsoup = { module = "org.jsoup:jsoup", version = "1.15.1" }
okhttp = { module = "com.squareup.okhttp3:okhttp", version = "5.0.0-alpha.11" }
jsoup = { module = "org.jsoup:jsoup", version = "1.18.3" }
okhttp = { module = "com.squareup.okhttp3:okhttp", version = "5.0.0-alpha.14" }
quickjs = { module = "app.cash.quickjs:quickjs-android", version = "0.9.2" }
[bundles]

View File

@ -1,7 +1,7 @@
ext {
extName = 'Mangamo'
extClass = '.Mangamo'
extVersionCode = 1
extVersionCode = 2
isNsfw = false
}

View File

@ -9,7 +9,6 @@ import eu.kanade.tachiyomi.network.POST
import okhttp3.Headers
import okhttp3.OkHttpClient
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.internal.EMPTY_HEADERS
class MangamoAuth(
private val helper: MangamoHelper,
@ -53,8 +52,7 @@ class MangamoAuth(
val googleIdentityResponse = client.newCall(
POST(
"https://identitytoolkit.googleapis.com/v1/accounts:signInWithCustomToken?key=${MangamoConstants.FIREBASE_API_KEY}",
EMPTY_HEADERS,
"{\"token\":\"$customToken\",\"returnSecureToken\":true}".toRequestBody(),
body = "{\"token\":\"$customToken\",\"returnSecureToken\":true}".toRequestBody(),
),
).execute()
@ -97,8 +95,7 @@ class MangamoAuth(
val googleIdentityResponse = client.newCall(
POST(
"https://identitytoolkit.googleapis.com/v1/accounts:signUp?key=${MangamoConstants.FIREBASE_API_KEY}",
EMPTY_HEADERS,
"{\"returnSecureToken\":true}".toRequestBody(),
body = "{\"returnSecureToken\":true}".toRequestBody(),
),
).execute()

View File

@ -32,8 +32,6 @@ import okhttp3.MediaType.Companion.toMediaType
import okhttp3.Request
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.Response
import okhttp3.internal.http.HTTP_FORBIDDEN
import okhttp3.internal.http.HTTP_UNAUTHORIZED
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import org.jsoup.select.Elements
@ -41,6 +39,8 @@ import rx.Observable
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy
import java.net.HttpURLConnection.HTTP_FORBIDDEN
import java.net.HttpURLConnection.HTTP_UNAUTHORIZED
import java.text.SimpleDateFormat
import java.util.Locale
@ -85,15 +85,13 @@ class Taiyo : ParsedHttpSource() {
// =============================== Search ===============================
override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> {
return if (query.startsWith(PREFIX_SEARCH)) { // URL intent handler
val id = query.removePrefix(PREFIX_SEARCH)
client.newCall(GET("$baseUrl/media/$id"))
.asObservableSuccess()
.map(::searchMangaByIdParse)
} else {
super.fetchSearchManga(page, query, filters)
}
override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> = if (query.startsWith(PREFIX_SEARCH)) { // URL intent handler
val id = query.removePrefix(PREFIX_SEARCH)
client.newCall(GET("$baseUrl/media/$id"))
.asObservableSuccess()
.map(::searchMangaByIdParse)
} else {
super.fetchSearchManga(page, query, filters)
}
private fun searchMangaByIdParse(response: Response): MangasPage {
@ -146,17 +144,11 @@ class Taiyo : ParsedHttpSource() {
return MangasPage(mangas, mangas.isNotEmpty())
}
override fun searchMangaSelector(): String {
throw UnsupportedOperationException()
}
override fun searchMangaSelector(): String = throw UnsupportedOperationException()
override fun searchMangaFromElement(element: Element): SManga {
throw UnsupportedOperationException()
}
override fun searchMangaFromElement(element: Element): SManga = throw UnsupportedOperationException()
override fun searchMangaNextPageSelector(): String? {
throw UnsupportedOperationException()
}
override fun searchMangaNextPageSelector(): String? = throw UnsupportedOperationException()
// =========================== Manga Details ============================
override fun mangaDetailsParse(document: Document) = SManga.create().apply {
@ -235,13 +227,9 @@ class Taiyo : ParsedHttpSource() {
return Observable.just(chapters.sortedByDescending { it.chapter_number })
}
override fun chapterListSelector(): String {
throw UnsupportedOperationException()
}
override fun chapterListSelector(): String = throw UnsupportedOperationException()
override fun chapterFromElement(element: Element): SChapter {
throw UnsupportedOperationException()
}
override fun chapterFromElement(element: Element): SChapter = throw UnsupportedOperationException()
// =============================== Pages ================================
override fun pageListParse(document: Document): List<Page> {
@ -256,9 +244,7 @@ class Taiyo : ParsedHttpSource() {
}
}
override fun imageUrlParse(document: Document): String {
throw UnsupportedOperationException()
}
override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException()
// ============================= Utilities ==============================
private fun Element.getImageUrl() = absUrl("srcset").substringBefore(" ")
@ -267,23 +253,19 @@ class Taiyo : ParsedHttpSource() {
json.decodeFromStream(it.body.byteStream())
}
private fun String.toDate(): Long {
return runCatching { DATE_FORMATTER.parse(this)?.time }
.getOrNull() ?: 0L
}
private fun String.toDate(): Long = runCatching { DATE_FORMATTER.parse(this)?.time }
.getOrNull() ?: 0L
private inline fun <reified T> Document.parseJsonFromDocument(
itemName: String = "media",
crossinline transformer: String.() -> String,
): T? {
return runCatching {
val script = selectFirst("script:containsData($itemName\\\\\":):containsData(\\\"6:\\[)")!!.data()
val obj = script.substringAfter(",{\\\"$itemName\\\":")
.run(transformer)
.replace("\\", "")
json.decodeFromString<T>(obj)
}.onFailure { it.printStackTrace() }.getOrNull()
}
): T? = runCatching {
val script = selectFirst("script:containsData($itemName\\\\\":):containsData(\\\"6:\\[)")!!.data()
val obj = script.substringAfter(",{\\\"$itemName\\\":")
.run(transformer)
.replace("\\", "")
json.decodeFromString<T>(obj)
}.onFailure { it.printStackTrace() }.getOrNull()
// ============================= Authorization ========================
@ -304,12 +286,10 @@ class Taiyo : ParsedHttpSource() {
return chain.proceed(req)
}
private fun getToken(): String {
return fetchBearerToken().also {
preferences.edit()
.putString(BEARER_TOKEN_PREF, it)
.apply()
}
private fun getToken(): String = fetchBearerToken().also {
preferences.edit()
.putString(BEARER_TOKEN_PREF, it)
.apply()
}
private fun fetchBearerToken(): String {