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
uses: actions/setup-java@v3
with:
java-version: 11
java-version: 17
distribution: adopt
- name: Generate android.jar

View File

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

View File

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

View File

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

View File

@ -1,5 +1,7 @@
distributionBase=GRADLE_USER_HOME
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
zipStorePath=wrapper/dists

View File

@ -29,11 +29,6 @@ dependencies {
implementation("org.jsoup:jsoup:1.15.3")
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
implementation(project(":AndroidCompat"))
implementation(project(":AndroidCompat:Config"))
@ -59,7 +54,7 @@ sourceSets {
}
// should be bumped with each stable release
val inspectorVersion = "v1.4.2"
val inspectorVersion = "v1.4.3"
// counts commit count on master
val inspectorRevision = runCatching {
@ -110,10 +105,10 @@ tasks {
withType<KotlinCompile> {
kotlinOptions {
freeCompilerArgs = listOf(
"-Xopt-in=kotlin.RequiresOptIn",
"-Xopt-in=kotlinx.coroutines.ExperimentalCoroutinesApi",
"-Xopt-in=kotlinx.coroutines.InternalCoroutinesApi",
"-Xopt-in=kotlin.io.path.ExperimentalPathApi",
"-Xopt-in=kotlin.RequiresOptIn",
"-Xopt-in=kotlinx.coroutines.ExperimentalCoroutinesApi",
"-Xopt-in=kotlinx.coroutines.InternalCoroutinesApi",
"-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).
*/
val lang: String
override val lang: String
/**
* 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.SChapter
import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.util.awaitSingle
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 {
/**
* Id for the source. Must be unique.
* ID for the source. Must be unique.
*/
val id: Long
@ -20,24 +21,81 @@ interface Source {
*/
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.
*
* @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.
*
* @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.
*/
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"
include("server")
include("AndroidCompat")
include("AndroidCompat:Config")