Convert PageLoader.getPages to suspending function (#8917)

This commit is contained in:
Two-Ai 2023-01-14 19:45:15 -05:00 committed by GitHub
parent 992bab4f79
commit 58ebf14691
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 51 additions and 58 deletions

View file

@ -15,7 +15,6 @@ import eu.kanade.tachiyomi.util.lang.launchIO
import eu.kanade.tachiyomi.util.system.logcat import eu.kanade.tachiyomi.util.system.logcat
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import logcat.LogPriority import logcat.LogPriority
import rx.Observable
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
@ -165,23 +164,21 @@ class DownloadManager(
* @param source the source of the chapter. * @param source the source of the chapter.
* @param manga the manga of the chapter. * @param manga the manga of the chapter.
* @param chapter the downloaded chapter. * @param chapter the downloaded chapter.
* @return an observable containing the list of pages from the chapter. * @return the list of pages from the chapter.
*/ */
fun buildPageList(source: Source, manga: Manga, chapter: Chapter): Observable<List<Page>> { fun buildPageList(source: Source, manga: Manga, chapter: Chapter): List<Page> {
val chapterDir = provider.findChapterDir(chapter.name, chapter.scanlator, manga.title, source) val chapterDir = provider.findChapterDir(chapter.name, chapter.scanlator, manga.title, source)
return Observable.fromCallable { val files = chapterDir?.listFiles().orEmpty()
val files = chapterDir?.listFiles().orEmpty() .filter { "image" in it.type.orEmpty() }
.filter { "image" in it.type.orEmpty() }
if (files.isEmpty()) { if (files.isEmpty()) {
throw Exception(context.getString(R.string.page_list_empty_error)) throw Exception(context.getString(R.string.page_list_empty_error))
}
files.sortedBy { it.name }
.mapIndexed { i, file ->
Page(i, uri = file.uri).apply { status = Page.State.READY }
}
} }
return files.sortedBy { it.name }
.mapIndexed { i, file ->
Page(i, uri = file.uri).apply { status = Page.State.READY }
}
} }
/** /**

View file

@ -11,7 +11,6 @@ import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.source.online.HttpSource
import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter
import eu.kanade.tachiyomi.util.lang.awaitSingle
import eu.kanade.tachiyomi.util.lang.withIOContext import eu.kanade.tachiyomi.util.lang.withIOContext
import eu.kanade.tachiyomi.util.system.logcat import eu.kanade.tachiyomi.util.system.logcat
@ -42,7 +41,7 @@ class ChapterLoader(
val loader = getPageLoader(chapter) val loader = getPageLoader(chapter)
chapter.pageLoader = loader chapter.pageLoader = loader
val pages = loader.getPages().awaitSingle() val pages = loader.getPages()
.onEach { it.chapter = chapter } .onEach { it.chapter = chapter }
if (pages.isEmpty()) { if (pages.isEmpty()) {

View file

@ -14,10 +14,9 @@ import java.io.FileInputStream
class DirectoryPageLoader(val file: File) : PageLoader() { class DirectoryPageLoader(val file: File) : PageLoader() {
/** /**
* Returns an observable containing the pages found on this directory ordered with a natural * Returns the pages found on this directory ordered with a natural comparator.
* comparator.
*/ */
override fun getPages(): Observable<List<ReaderPage>> { override suspend fun getPages(): List<ReaderPage> {
return file.listFiles() return file.listFiles()
?.filter { !it.isDirectory && ImageUtil.isImage(it.name) { FileInputStream(it) } } ?.filter { !it.isDirectory && ImageUtil.isImage(it.name) { FileInputStream(it) } }
?.sortedWith { f1, f2 -> f1.name.compareToCaseInsensitiveNaturalOrder(f2.name) } ?.sortedWith { f1, f2 -> f1.name.compareToCaseInsensitiveNaturalOrder(f2.name) }
@ -27,8 +26,7 @@ class DirectoryPageLoader(val file: File) : PageLoader() {
stream = streamFn stream = streamFn
status = Page.State.READY status = Page.State.READY
} }
} } ?: emptyList()
.let { Observable.just(it) }
} }
/** /**

View file

@ -37,9 +37,9 @@ class DownloadPageLoader(
} }
/** /**
* Returns an observable containing the pages found on this downloaded chapter. * Returns the pages found on this downloaded chapter.
*/ */
override fun getPages(): Observable<List<ReaderPage>> { override suspend fun getPages(): List<ReaderPage> {
val dbChapter = chapter.chapter val dbChapter = chapter.chapter
val chapterPath = downloadProvider.findChapterDir(dbChapter.name, dbChapter.scanlator, manga.title, source) val chapterPath = downloadProvider.findChapterDir(dbChapter.name, dbChapter.scanlator, manga.title, source)
return if (chapterPath?.isFile == true) { return if (chapterPath?.isFile == true) {
@ -49,22 +49,20 @@ class DownloadPageLoader(
} }
} }
private fun getPagesFromArchive(chapterPath: UniFile): Observable<List<ReaderPage>> { private suspend fun getPagesFromArchive(chapterPath: UniFile): List<ReaderPage> {
val loader = ZipPageLoader(File(chapterPath.filePath!!)).also { zipPageLoader = it } val loader = ZipPageLoader(File(chapterPath.filePath!!)).also { zipPageLoader = it }
return loader.getPages() return loader.getPages()
} }
private fun getPagesFromDirectory(): Observable<List<ReaderPage>> { private fun getPagesFromDirectory(): List<ReaderPage> {
return downloadManager.buildPageList(source, manga, chapter.chapter.toDomainChapter()!!) val pages = downloadManager.buildPageList(source, manga, chapter.chapter.toDomainChapter()!!)
.map { pages -> return pages.map { page ->
pages.map { page -> ReaderPage(page.index, page.url, page.imageUrl) {
ReaderPage(page.index, page.url, page.imageUrl) { context.contentResolver.openInputStream(page.uri ?: Uri.EMPTY)!!
context.contentResolver.openInputStream(page.uri ?: Uri.EMPTY)!! }.apply {
}.apply { status = Page.State.READY
status = Page.State.READY
}
}
} }
}
} }
override fun getPage(page: ReaderPage): Observable<Page.State> { override fun getPage(page: ReaderPage): Observable<Page.State> {

View file

@ -25,10 +25,9 @@ class EpubPageLoader(file: File) : PageLoader() {
} }
/** /**
* Returns an observable containing the pages found on this zip archive ordered with a natural * Returns the pages found on this zip archive ordered with a natural comparator.
* comparator.
*/ */
override fun getPages(): Observable<List<ReaderPage>> { override suspend fun getPages(): List<ReaderPage> {
return epub.getImagesFromPages() return epub.getImagesFromPages()
.mapIndexed { i, path -> .mapIndexed { i, path ->
val streamFn = { epub.getInputStream(epub.getEntry(path)!!) } val streamFn = { epub.getInputStream(epub.getEntry(path)!!) }
@ -37,7 +36,6 @@ class EpubPageLoader(file: File) : PageLoader() {
status = Page.State.READY status = Page.State.READY
} }
} }
.let { Observable.just(it) }
} }
/** /**

View file

@ -8,6 +8,7 @@ import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter
import eu.kanade.tachiyomi.ui.reader.model.ReaderPage import eu.kanade.tachiyomi.ui.reader.model.ReaderPage
import eu.kanade.tachiyomi.util.lang.plusAssign import eu.kanade.tachiyomi.util.lang.plusAssign
import eu.kanade.tachiyomi.util.system.logcat import eu.kanade.tachiyomi.util.system.logcat
import kotlinx.coroutines.CancellationException
import logcat.LogPriority import logcat.LogPriority
import rx.Completable import rx.Completable
import rx.Observable import rx.Observable
@ -83,18 +84,22 @@ class HttpPageLoader(
} }
/** /**
* Returns an observable with the page list for a chapter. It tries to return the page list from * Returns the page list for a chapter. It tries to return the page list from the local cache,
* the local cache, otherwise fallbacks to network. * otherwise fallbacks to network.
*/ */
override fun getPages(): Observable<List<ReaderPage>> { override suspend fun getPages(): List<ReaderPage> {
return Observable.fromCallable { chapterCache.getPageListFromCache(chapter.chapter.toDomainChapter()!!) } val pages = try {
.onErrorResumeNext { source.fetchPageList(chapter.chapter) } chapterCache.getPageListFromCache(chapter.chapter.toDomainChapter()!!)
.map { pages -> } catch (e: Throwable) {
pages.mapIndexed { index, page -> if (e is CancellationException) {
// Don't trust sources and use our own indexing throw e
ReaderPage(index, page.url, page.imageUrl)
}
} }
source.getPageList(chapter.chapter)
}
return pages.mapIndexed { index, page ->
// Don't trust sources and use our own indexing
ReaderPage(index, page.url, page.imageUrl)
}
} }
/** /**

View file

@ -27,10 +27,9 @@ abstract class PageLoader {
} }
/** /**
* Returns an observable containing the list of pages of a chapter. Only the first emission * Returns the list of pages of a chapter.
* will be used.
*/ */
abstract fun getPages(): Observable<List<ReaderPage>> abstract suspend fun getPages(): List<ReaderPage>
/** /**
* Returns an observable that should inform of the progress of the page * Returns an observable that should inform of the progress of the page

View file

@ -38,10 +38,10 @@ class RarPageLoader(file: File) : PageLoader() {
} }
/** /**
* Returns an observable containing the pages found on this rar archive ordered with a natural * Returns an RxJava Single containing the pages found on this rar archive ordered with a natural
* comparator. * comparator.
*/ */
override fun getPages(): Observable<List<ReaderPage>> { override suspend fun getPages(): List<ReaderPage> {
return archive.fileHeaders.asSequence() return archive.fileHeaders.asSequence()
.filter { !it.isDirectory && ImageUtil.isImage(it.fileName) { archive.getInputStream(it) } } .filter { !it.isDirectory && ImageUtil.isImage(it.fileName) { archive.getInputStream(it) } }
.sortedWith { f1, f2 -> f1.fileName.compareToCaseInsensitiveNaturalOrder(f2.fileName) } .sortedWith { f1, f2 -> f1.fileName.compareToCaseInsensitiveNaturalOrder(f2.fileName) }
@ -51,7 +51,7 @@ class RarPageLoader(file: File) : PageLoader() {
status = Page.State.READY status = Page.State.READY
} }
} }
.let { Observable.just(it.toList()) } .toList()
} }
/** /**

View file

@ -33,10 +33,9 @@ class ZipPageLoader(file: File) : PageLoader() {
} }
/** /**
* Returns an observable containing the pages found on this zip archive ordered with a natural * Returns the pages found on this zip archive ordered with a natural comparator.
* comparator.
*/ */
override fun getPages(): Observable<List<ReaderPage>> { override suspend fun getPages(): List<ReaderPage> {
return zip.entries().asSequence() return zip.entries().asSequence()
.filter { !it.isDirectory && ImageUtil.isImage(it.name) { zip.getInputStream(it) } } .filter { !it.isDirectory && ImageUtil.isImage(it.name) { zip.getInputStream(it) } }
.sortedWith { f1, f2 -> f1.name.compareToCaseInsensitiveNaturalOrder(f2.name) } .sortedWith { f1, f2 -> f1.name.compareToCaseInsensitiveNaturalOrder(f2.name) }
@ -46,7 +45,7 @@ class ZipPageLoader(file: File) : PageLoader() {
status = Page.State.READY status = Page.State.READY
} }
} }
.let { Observable.just(it.toList()) } .toList()
} }
/** /**