Support showing related titles for all extensions...

...by using getSearchManga (if extension support searching)

Drop old API style (using suspend function instead of RxJava)

Cleanup
This commit is contained in:
Cuong M. Tran 2024-04-29 03:18:36 +07:00
parent 255d257d0a
commit d9e440084e
No known key found for this signature in database
GPG key ID: 733AA7624B9315C2
4 changed files with 32 additions and 55 deletions

View file

@ -209,11 +209,6 @@ class MangaScreenModel(
private val filteredChapters: List<ChapterList.Item>? private val filteredChapters: List<ChapterList.Item>?
get() = successState?.processedChapters get() = successState?.processedChapters
// KMK -->
private val relatedMangas: List<Manga>
get() = successState?.relatedMangas ?: emptyList()
// KMK <--
val chapterSwipeStartAction = libraryPreferences.swipeToEndAction().get() val chapterSwipeStartAction = libraryPreferences.swipeToEndAction().get()
val chapterSwipeEndAction = libraryPreferences.swipeToStartAction().get() val chapterSwipeEndAction = libraryPreferences.swipeToStartAction().get()
@ -1107,14 +1102,16 @@ class MangaScreenModel(
try { try {
withIOContext { withIOContext {
if (state.source !is MergedSource) { if (state.source !is MergedSource) {
val relatedMangas = if (Injekt.get<SourcePreferences>().relatedMangas().get()) val relatedMangas = if (Injekt.get<SourcePreferences>().relatedMangas().get()) {
withIOContext { withIOContext {
state.source.getRelatedMangaList(state.manga.toSManga()) state.source.getRelatedMangaList(state.manga.toSManga())
.map { .map {
networkToLocalManga.await(it.toDomainManga(state.source.id)) networkToLocalManga.await(it.toDomainManga(state.source.id))
} }
} }
else null } else {
null
}
updateSuccessState { it.copy(relatedMangas = relatedMangas) } updateSuccessState { it.copy(relatedMangas = relatedMangas) }
} else { } else {
throw UnsupportedOperationException("Fetching related titles for merged entry is not supported") throw UnsupportedOperationException("Fetching related titles for merged entry is not supported")

View file

@ -52,14 +52,12 @@ interface Source {
/** /**
* Get all the available related mangas for a manga. * Get all the available related mangas for a manga.
* *
* @since extensions-lib 1.6 * @since komikku/extensions-lib 1.6
* @param manga the current manga to get related mangas. * @param manga the current manga to get related mangas.
* @return the related mangas for the current manga. * @return the related mangas for the current manga.
*/ */
@Suppress("DEPRECATION") suspend fun getRelatedMangaList(manga: SManga): List<SManga> =
suspend fun getRelatedMangaList(manga: SManga): List<SManga> { throw IllegalStateException("Not used")
return fetchRelatedMangaList(manga).awaitSingle()
}
// KMK <-- // KMK <--
/** /**
@ -89,22 +87,6 @@ interface Source {
fun fetchChapterList(manga: SManga): Observable<List<SChapter>> = fun fetchChapterList(manga: SManga): Observable<List<SChapter>> =
throw IllegalStateException("Not used") throw IllegalStateException("Not used")
// KMK -->
/**
* Get all the available related mangas for a manga.
*
* @since extensions-lib 1.6
* @param manga the current manga to get related mangas.
* @return the related mangas for the current manga.
*/
@Deprecated(
"Use the non-RxJava API instead",
ReplaceWith("getRelatedMangaList"),
)
fun fetchRelatedMangaList(manga: SManga): Observable<List<SManga>> =
throw IllegalStateException("Not used")
// KMK <--
@Deprecated( @Deprecated(
"Use the non-RxJava API instead", "Use the non-RxJava API instead",
ReplaceWith("getPageList"), ReplaceWith("getPageList"),

View file

@ -286,7 +286,7 @@ abstract class HttpSource : CatalogueSource {
* Whether parsing related mangas in manga page or extension provide custom related mangas request (true) * Whether parsing related mangas in manga page or extension provide custom related mangas request (true)
* or using search keyword to search for related mangas (false - default) * or using search keyword to search for related mangas (false - default)
* @default false * @default false
* @since extensions-lib 1.6 * @since komikku/extensions-lib 1.6
*/ */
protected open val supportsRelatedMangas: Boolean get() = false protected open val supportsRelatedMangas: Boolean get() = false
protected open val disableRelatedMangas: Boolean get() = false protected open val disableRelatedMangas: Boolean get() = false
@ -295,23 +295,31 @@ abstract class HttpSource : CatalogueSource {
* Get all the available related mangas for a manga. * Get all the available related mangas for a manga.
* Normally it's not needed to override this method. * Normally it's not needed to override this method.
* *
* @since komikku/extensions-lib 1.6
* @param manga the current manga to get related mangas. * @param manga the current manga to get related mangas.
* @return the related mangas for the current manga. * @return the related mangas for the current manga.
* @throws UnsupportedOperationException if a source doesn't support related mangas. * @throws UnsupportedOperationException if a source doesn't support related mangas.
*/ */
@Suppress("DEPRECATION")
override suspend fun getRelatedMangaList(manga: SManga): List<SManga> { override suspend fun getRelatedMangaList(manga: SManga): List<SManga> {
return when { return when {
supportsRelatedMangas -> fetchRelatedMangaList(manga).awaitSingle() supportsRelatedMangas -> {
client.newCall(relatedMangaListRequest(manga))
.execute()
.let { response ->
relatedMangaListParse(response)
}
}
disableRelatedMangas -> emptyList() disableRelatedMangas -> emptyList()
else -> fetchRelatedMangaListBySearch(manga) else -> getRelatedMangaListBySearch(manga)
} }
} }
/** /**
* Fetch related mangas by searching for each keywords from manga's title * Fetch related mangas by searching for each keywords from manga's title
*
* @since komikku/extensions-lib 1.6
*/ */
protected open suspend fun fetchRelatedMangaListBySearch(manga: SManga): List<SManga> { protected open suspend fun getRelatedMangaListBySearch(manga: SManga): List<SManga> {
fun String.stripKeyword(): List<String> { fun String.stripKeyword(): List<String> {
val regexWhitespace = Regex("\\s+") val regexWhitespace = Regex("\\s+")
val regexSpecialCharacters = Regex("[\\[(!~@#$%^&*|,?:\"<>)\\]]") val regexSpecialCharacters = Regex("[\\[(!~@#$%^&*|,?:\"<>)\\]]")
@ -338,19 +346,16 @@ abstract class HttpSource : CatalogueSource {
} }
return words.map { keyword -> return words.map { keyword ->
// Make multiple search in parallel
scope.async { scope.async {
try { try {
client.newCall(searchMangaRequest(0, keyword, FilterList())) getSearchManga(0, keyword, FilterList())
.execute() .mangas.filter {
.let { response -> it.url != manga.url &&
searchMangaParse(response).mangas it.title.lowercase().contains(keyword)
.filter {
it.url != manga.url &&
it.title.lowercase().contains(keyword)
}
} }
} catch (e: Exception) { } catch (e: Exception) {
logcat(LogPriority.ERROR, e) { "Related titles: $e" } logcat(LogPriority.ERROR, e) { "getRelatedMangaListBySearch: $e" }
emptyList() emptyList()
} }
} }
@ -358,24 +363,12 @@ abstract class HttpSource : CatalogueSource {
.minBy { if (it.isEmpty()) Int.MAX_VALUE else it.size } .minBy { if (it.isEmpty()) Int.MAX_VALUE else it.size }
} }
/**
* Fetch related mangas found in manga's page which is provided by sites.
* If using this, must also: 'override val supportsRelatedMangas = true'
*/
@Deprecated("Use the non-RxJava API instead", replaceWith = ReplaceWith("getRelatedMangaList"))
override fun fetchRelatedMangaList(manga: SManga): Observable<List<SManga>> {
return client.newCall(relatedMangaListRequest(manga))
.asObservableSuccess()
.map { response ->
relatedMangaListParse(response)
}
}
/** /**
* Returns the request for get related manga list. Override only if it's needed to override * Returns the request for get related manga list. Override only if it's needed to override
* the url, send different headers or request method like POST. * the url, send different headers or request method like POST.
* If using this, must also: 'override val supportsRelatedMangas = true' * If using this, must also: 'override val supportsRelatedMangas = true'
* *
* @since komikku/extensions-lib 1.6
* @param manga the manga to look for related mangas. * @param manga the manga to look for related mangas.
*/ */
protected open fun relatedMangaListRequest(manga: SManga): Request { protected open fun relatedMangaListRequest(manga: SManga): Request {
@ -386,6 +379,7 @@ abstract class HttpSource : CatalogueSource {
* Parses the response from the site and returns a list of related mangas. * Parses the response from the site and returns a list of related mangas.
* If using this, must also: 'override val supportsRelatedMangas = true' * If using this, must also: 'override val supportsRelatedMangas = true'
* *
* @since komikku/extensions-lib 1.6
* @param response the response from the site. * @param response the response from the site.
*/ */
protected open fun relatedMangaListParse(response: Response): List<SManga> = popularMangaParse(response).mangas protected open fun relatedMangaListParse(response: Response): List<SManga> = popularMangaParse(response).mangas

View file

@ -150,6 +150,7 @@ abstract class ParsedHttpSource : HttpSource() {
* Parses the response from the site and returns a list of related mangas. * Parses the response from the site and returns a list of related mangas.
* If using this, must also: 'override val supportsRelatedMangas = true' * If using this, must also: 'override val supportsRelatedMangas = true'
* *
* @since komikku/extensions-lib 1.6
* @param response the response from the site. * @param response the response from the site.
*/ */
override fun relatedMangaListParse(response: Response): List<SManga> { override fun relatedMangaListParse(response: Response): List<SManga> {
@ -160,6 +161,8 @@ abstract class ParsedHttpSource : HttpSource() {
/** /**
* Returns the Jsoup selector that returns a list of [Element] corresponding to each related mangas. * Returns the Jsoup selector that returns a list of [Element] corresponding to each related mangas.
* If using this, must also: 'override val supportsRelatedMangas = true' * If using this, must also: 'override val supportsRelatedMangas = true'
*
* @since komikku/extensions-lib 1.6
*/ */
protected open fun relatedMangaListSelector(): String = popularMangaSelector() protected open fun relatedMangaListSelector(): String = popularMangaSelector()
@ -167,6 +170,7 @@ abstract class ParsedHttpSource : HttpSource() {
* Returns a manga from the given element. * Returns a manga from the given element.
* If using this, must also: 'override val supportsRelatedMangas = true' * If using this, must also: 'override val supportsRelatedMangas = true'
* *
* @since komikku/extensions-lib 1.6
* @param element an element obtained from [relatedMangaListSelector]. * @param element an element obtained from [relatedMangaListSelector].
*/ */
protected open fun relatedMangaFromElement(element: Element): SManga = popularMangaFromElement(element) protected open fun relatedMangaFromElement(element: Element): SManga = popularMangaFromElement(element)