Skip to content

Commit

Permalink
SlimeReadTheme: Fix pagination and add scan id (#7152)
Browse files Browse the repository at this point in the history
Fix pagination and add scan id
  • Loading branch information
choppeh authored Jan 13, 2025
1 parent d541465 commit ef4b9fb
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 28 deletions.
2 changes: 1 addition & 1 deletion lib-multisrc/slimereadtheme/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ plugins {
id("lib-multisrc")
}

baseVersionCode = 2
baseVersionCode = 3
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ abstract class SlimeReadTheme(
override val name: String,
override val baseUrl: String,
override val lang: String,
private val scanId: String = "",
) : HttpSource() {

protected open val apiUrl: String by lazy { getApiUrlFromPage() }
Expand Down Expand Up @@ -72,35 +73,19 @@ abstract class SlimeReadTheme(
}

// ============================== Popular ===============================
private var currentSlice = 0
private var popularMangeCache: MangasPage? = null

override fun popularMangaRequest(page: Int) =
GET("$apiUrl/book_search?order=1&status=0", headers)
override fun popularMangaRequest(page: Int): Request {
val url = "$apiUrl/book_search?order=1&status=0".toHttpUrl().newBuilder()
.addIfNotBlank("scan_id", scanId)
.build()
return GET(url, headers)
}

// Returns a large JSON, so the app can't handle the list without pagination
override fun fetchPopularManga(page: Int): Observable<MangasPage> {
if (page == 1 || popularMangeCache == null) {
popularMangeCache = super.fetchPopularManga(page)
.toBlocking()
.last()
}

// Handling a large manga list
return Observable.just(popularMangeCache!!)
.map { mangaPage ->
val mangas = mangaPage.mangas
val pageSize = 15

currentSlice = (page - 1) * pageSize

val startIndex = min(mangas.size - 1, currentSlice)
val endIndex = min(mangas.size, currentSlice + pageSize)

val slice = mangas.subList(startIndex, endIndex)

MangasPage(slice, slice.isNotEmpty())
}
popularMangeCache = popularMangeCache?.takeIf { page != 1 }
?: super.fetchPopularManga(page).toBlocking().last()
return pageableOf(page, popularMangeCache!!)
}

override fun popularMangaParse(response: Response): MangasPage {
Expand All @@ -110,7 +95,13 @@ abstract class SlimeReadTheme(
}

// =============================== Latest ===============================
override fun latestUpdatesRequest(page: Int) = GET("$apiUrl/books?page=$page", headers)

override fun latestUpdatesRequest(page: Int): Request {
val url = "$apiUrl/books?page=$page".toHttpUrl().newBuilder()
.addIfNotBlank("scan_id", scanId)
.build()
return GET(url, headers)
}

override fun latestUpdatesParse(response: Response): MangasPage {
val dto = response.parseAs<LatestResponseDto>()
Expand All @@ -120,14 +111,19 @@ abstract class SlimeReadTheme(
}

// =============================== Search ===============================

private var searchMangaCache: MangasPage? = null

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("$apiUrl/book/$id", headers))
.asObservableSuccess()
.map(::searchMangaByIdParse)
} else {
super.fetchSearchManga(page, query, filters)
searchMangaCache = searchMangaCache?.takeIf { page != 1 }
?: super.fetchSearchManga(page, query, filters).toBlocking().last()
pageableOf(page, searchMangaCache!!)
}
}

Expand All @@ -146,6 +142,7 @@ abstract class SlimeReadTheme(
.addIfNotBlank("genre[]", params.genre)
.addIfNotBlank("status", params.status)
.addIfNotBlank("searchMethod", params.searchMethod)
.addIfNotBlank("scan_id", scanId)
.apply {
params.categories.forEach {
addQueryParameter("categories[]", it)
Expand Down Expand Up @@ -237,6 +234,28 @@ abstract class SlimeReadTheme(
}

// ============================= Utilities ==============================

/**
* Handles a large manga list and returns a paginated response.
* The app can't handle the large JSON list without pagination.
*
* @param page The page number to retrieve.
* @param cache The cached manga page containing the full list of mangas.
*/
private fun pageableOf(page: Int, cache: MangasPage) = Observable.just(cache).map { mangaPage ->
val mangas = mangaPage.mangas
val pageSize = 15

val currentSlice = (page - 1) * pageSize

val startIndex = min(mangas.size, currentSlice)
val endIndex = min(mangas.size, currentSlice + pageSize)

val slice = mangas.subList(startIndex, endIndex)

MangasPage(slice, hasNextPage = endIndex < mangas.size)
}

private inline fun <reified T> Response.parseAs(): T = use {
json.decodeFromStream(it.body.byteStream())
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ class MahouScan : SlimeReadTheme(
"MahouScan",
"https://mahouscan.com",
"pt-BR",
scanId = "1292193100",
) {
override val client = super.client.newBuilder()
.rateLimit(2)
Expand Down

0 comments on commit ef4b9fb

Please sign in to comment.