Update Source interface

This commit is contained in:
arkon 2023-09-02 23:22:37 -04:00
parent e301768a5d
commit 1f03ebad2b
11 changed files with 160 additions and 28 deletions

View File

@ -24,7 +24,7 @@ jobs:
- name: Set up JDK - name: Set up JDK
uses: actions/setup-java@v3 uses: actions/setup-java@v3
with: with:
java-version: 11 java-version: 17
distribution: adopt distribution: adopt
- name: Generate android.jar - name: Generate android.jar

View File

@ -24,7 +24,7 @@ jobs:
- name: Set up JDK - name: Set up JDK
uses: actions/setup-java@v3 uses: actions/setup-java@v3
with: with:
java-version: 11 java-version: 17
distribution: adopt distribution: adopt
- name: Generate android.jar - name: Generate android.jar

View File

@ -26,7 +26,7 @@ jobs:
- name: Set up JDK - name: Set up JDK
uses: actions/setup-java@v3 uses: actions/setup-java@v3
with: with:
java-version: 11 java-version: 17
distribution: adopt distribution: adopt
- name: Generate android.jar - name: Generate android.jar

View File

@ -33,13 +33,13 @@ configure(projects) {
apply(plugin = "org.jetbrains.kotlin.jvm") apply(plugin = "org.jetbrains.kotlin.jvm")
java { java {
sourceCompatibility = JavaVersion.VERSION_11 sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_11 targetCompatibility = JavaVersion.VERSION_17
} }
tasks.withType<KotlinCompile> { tasks.withType<KotlinCompile> {
kotlinOptions { kotlinOptions {
jvmTarget = JavaVersion.VERSION_11.toString() jvmTarget = JavaVersion.VERSION_17.toString()
} }
} }
@ -59,7 +59,6 @@ configure(projects) {
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:$kotlinSerializationVersion") implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:$kotlinSerializationVersion")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-protobuf:$kotlinSerializationVersion") implementation("org.jetbrains.kotlinx:kotlinx-serialization-protobuf:$kotlinSerializationVersion")
// Dependency Injection // Dependency Injection
implementation("org.kodein.di:kodein-di-conf-jvm:7.11.0") implementation("org.kodein.di:kodein-di-conf-jvm:7.11.0")
@ -71,7 +70,6 @@ configure(projects) {
// ReactiveX // ReactiveX
implementation("io.reactivex:rxjava:1.3.8") implementation("io.reactivex:rxjava:1.3.8")
implementation("io.reactivex:rxkotlin:1.0.0") implementation("io.reactivex:rxkotlin:1.0.0")
implementation("com.jakewharton.rxrelay:rxrelay:1.2.0")
// JSoup // JSoup
implementation("org.jsoup:jsoup:1.15.3") implementation("org.jsoup:jsoup:1.15.3")
@ -81,7 +79,7 @@ configure(projects) {
implementation("io.github.config4k:config4k:0.4.2") implementation("io.github.config4k:config4k:0.4.2")
// dex2jar // dex2jar
val dex2jarVersion = "v59" val dex2jarVersion = "v71"
implementation("com.github.ThexXTURBOXx.dex2jar:dex-translator:$dex2jarVersion") implementation("com.github.ThexXTURBOXx.dex2jar:dex-translator:$dex2jarVersion")
implementation("com.github.ThexXTURBOXx.dex2jar:dex-tools:$dex2jarVersion") implementation("com.github.ThexXTURBOXx.dex2jar:dex-tools:$dex2jarVersion")

View File

@ -1,5 +1,7 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists

View File

@ -29,11 +29,6 @@ dependencies {
implementation("org.jsoup:jsoup:1.15.3") implementation("org.jsoup:jsoup:1.15.3")
implementation("app.cash.quickjs:quickjs-jvm:0.9.2") implementation("app.cash.quickjs:quickjs-jvm:0.9.2")
// Source models and interfaces from Tachiyomi 1.x
// using source class from tachiyomi commit 9493577de27c40ce8b2b6122cc447d025e34c477 to not depend on tachiyomi.sourceapi
// implementation("tachiyomi.sourceapi:source-api:1.1")
// AndroidCompat // AndroidCompat
implementation(project(":AndroidCompat")) implementation(project(":AndroidCompat"))
implementation(project(":AndroidCompat:Config")) implementation(project(":AndroidCompat:Config"))
@ -59,7 +54,7 @@ sourceSets {
} }
// should be bumped with each stable release // should be bumped with each stable release
val inspectorVersion = "v1.4.2" val inspectorVersion = "v1.4.3"
// counts commit count on master // counts commit count on master
val inspectorRevision = runCatching { val inspectorRevision = runCatching {
@ -110,10 +105,10 @@ tasks {
withType<KotlinCompile> { withType<KotlinCompile> {
kotlinOptions { kotlinOptions {
freeCompilerArgs = listOf( freeCompilerArgs = listOf(
"-Xopt-in=kotlin.RequiresOptIn", "-Xopt-in=kotlin.RequiresOptIn",
"-Xopt-in=kotlinx.coroutines.ExperimentalCoroutinesApi", "-Xopt-in=kotlinx.coroutines.ExperimentalCoroutinesApi",
"-Xopt-in=kotlinx.coroutines.InternalCoroutinesApi", "-Xopt-in=kotlinx.coroutines.InternalCoroutinesApi",
"-Xopt-in=kotlin.io.path.ExperimentalPathApi", "-Xopt-in=kotlin.io.path.ExperimentalPathApi",
) )
} }
} }

View File

@ -9,7 +9,7 @@ interface CatalogueSource : Source {
/** /**
* An ISO 639-1 compliant language code (two letters in lower case). * An ISO 639-1 compliant language code (two letters in lower case).
*/ */
val lang: String override val lang: String
/** /**
* Whether the source has support for latest updates. * Whether the source has support for latest updates.

View File

@ -3,15 +3,16 @@ package eu.kanade.tachiyomi.source
import eu.kanade.tachiyomi.source.model.Page import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.util.awaitSingle
import rx.Observable import rx.Observable
/** /**
* A basic interface for creating a source. It could be an online source, a local source, etc... * A basic interface for creating a source. It could be an online source, a local source, etc.
*/ */
interface Source { interface Source {
/** /**
* Id for the source. Must be unique. * ID for the source. Must be unique.
*/ */
val id: Long val id: Long
@ -20,24 +21,81 @@ interface Source {
*/ */
val name: String val name: String
val lang: String
get() = ""
/**
* Get the updated details for a manga.
*
* @since extensions-lib 1.4
* @param manga the manga to update.
* @return the updated manga.
*/
@Suppress("DEPRECATION")
suspend fun getMangaDetails(manga: SManga): SManga {
return fetchMangaDetails(manga).awaitSingle()
}
/**
* Get all the available chapters for a manga.
*
* @since extensions-lib 1.4
* @param manga the manga to update.
* @return the chapters for the manga.
*/
@Suppress("DEPRECATION")
suspend fun getChapterList(manga: SManga): List<SChapter> {
return fetchChapterList(manga).awaitSingle()
}
/**
* Get the list of pages a chapter has. Pages should be returned
* in the expected order; the index is ignored.
*
* @since extensions-lib 1.4
* @param chapter the chapter.
* @return the pages for the chapter.
*/
@Suppress("DEPRECATION")
suspend fun getPageList(chapter: SChapter): List<Page> {
return fetchPageList(chapter).awaitSingle()
}
/** /**
* Returns an observable with the updated details for a manga. * Returns an observable with the updated details for a manga.
* *
* @param manga the manga to update. * @param manga the manga to update.
*/ */
fun fetchMangaDetails(manga: SManga): Observable<SManga> @Deprecated(
"Use the non-RxJava API instead",
ReplaceWith("getMangaDetails"),
)
fun fetchMangaDetails(manga: SManga): Observable<SManga> = throw IllegalStateException(
"Not used",
)
/** /**
* Returns an observable with all the available chapters for a manga. * Returns an observable with all the available chapters for a manga.
* *
* @param manga the manga to update. * @param manga the manga to update.
*/ */
fun fetchChapterList(manga: SManga): Observable<List<SChapter>> @Deprecated(
"Use the non-RxJava API instead",
ReplaceWith("getChapterList"),
)
fun fetchChapterList(manga: SManga): Observable<List<SChapter>> = throw IllegalStateException(
"Not used",
)
/** /**
* Returns an observable with the list of pages a chapter has. * Returns an observable with the list of pages a chapter has. Pages should be returned
* in the expected order; the index is ignored.
* *
* @param chapter the chapter. * @param chapter the chapter.
*/ */
fun fetchPageList(chapter: SChapter): Observable<List<Page>> @Deprecated(
"Use the non-RxJava API instead",
ReplaceWith("getPageList"),
)
fun fetchPageList(chapter: SChapter): Observable<List<Page>> = Observable.empty()
} }

View File

@ -0,0 +1,26 @@
package eu.kanade.tachiyomi.source.online
import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.source.model.SManga
/**
* A source that may handle opening an SManga for a given URI.
*
* @since extensions-lib 1.5
*/
interface ResolvableSource : Source {
/**
* Whether this source may potentially handle the given URI.
*
* @since extensions-lib 1.5
*/
fun canResolveUri(uri: String): Boolean
/**
* Called if canHandleUri is true. Returns the corresponding SManga, if possible.
*
* @since extensions-lib 1.5
*/
suspend fun getManga(uri: String): SManga?
}

View File

@ -0,0 +1,54 @@
package eu.kanade.tachiyomi.util
import kotlinx.coroutines.CancellableContinuation
import kotlinx.coroutines.InternalCoroutinesApi
import kotlinx.coroutines.suspendCancellableCoroutine
import rx.Observable
import rx.Subscriber
import rx.Subscription
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
suspend fun <T> Observable<T>.awaitSingle(): T = single().awaitOne()
@OptIn(InternalCoroutinesApi::class)
private suspend fun <T> Observable<T>.awaitOne(): T = suspendCancellableCoroutine { cont ->
cont.unsubscribeOnCancellation(
subscribe(
object : Subscriber<T>() {
override fun onStart() {
request(1)
}
override fun onNext(t: T) {
cont.resume(t)
}
override fun onCompleted() {
if (cont.isActive) {
cont.resumeWithException(
IllegalStateException(
"Should have invoked onNext",
),
)
}
}
override fun onError(e: Throwable) {
/*
* Rx1 observable throws NoSuchElementException if cancellation happened before
* element emission. To mitigate this we try to atomically resume continuation with exception:
* if resume failed, then we know that continuation successfully cancelled itself
*/
val token = cont.tryResumeWithException(e)
if (token != null) {
cont.completeResume(token)
}
}
},
),
)
}
private fun <T> CancellableContinuation<T>.unsubscribeOnCancellation(sub: Subscription) =
invokeOnCancellation { sub.unsubscribe() }

View File

@ -1,6 +1,5 @@
rootProject.name = "Tachiyomi Extensions Inspector" rootProject.name = "Tachiyomi Extensions Inspector"
include("server") include("server")
include("AndroidCompat") include("AndroidCompat")
include("AndroidCompat:Config") include("AndroidCompat:Config")