Minor optimizations for local source dir lookups

This commit is contained in:
arkon 2020-07-25 14:20:47 -04:00
parent e4d075fb91
commit d749e309f8

View File

@ -28,13 +28,15 @@ import timber.log.Timber
class LocalSource(private val context: Context) : CatalogueSource { class LocalSource(private val context: Context) : CatalogueSource {
companion object { companion object {
const val ID = 0L
const val HELP_URL = "https://tachiyomi.org/help/guides/reading-local-manga/" const val HELP_URL = "https://tachiyomi.org/help/guides/reading-local-manga/"
private const val COVER_NAME = "cover.jpg" private const val COVER_NAME = "cover.jpg"
private val SUPPORTED_ARCHIVE_TYPES = setOf("zip", "rar", "cbr", "cbz", "epub")
private val POPULAR_FILTERS = FilterList(OrderBy()) private val POPULAR_FILTERS = FilterList(OrderBy())
private val LATEST_FILTERS = FilterList(OrderBy().apply { state = Filter.Sort.Selection(1, false) }) private val LATEST_FILTERS = FilterList(OrderBy().apply { state = Filter.Sort.Selection(1, false) })
private val LATEST_THRESHOLD = TimeUnit.MILLISECONDS.convert(7, TimeUnit.DAYS) private val LATEST_THRESHOLD = TimeUnit.MILLISECONDS.convert(7, TimeUnit.DAYS)
const val ID = 0L
fun updateCover(context: Context, manga: SManga, input: InputStream): File? { fun updateCover(context: Context, manga: SManga, input: InputStream): File? {
val dir = getBaseDirectories(context).firstOrNull() val dir = getBaseDirectories(context).firstOrNull()
@ -73,9 +75,12 @@ class LocalSource(private val context: Context) : CatalogueSource {
val baseDirs = getBaseDirectories(context) val baseDirs = getBaseDirectories(context)
val time = if (filters === LATEST_FILTERS) System.currentTimeMillis() - LATEST_THRESHOLD else 0L val time = if (filters === LATEST_FILTERS) System.currentTimeMillis() - LATEST_THRESHOLD else 0L
var mangaDirs = baseDirs.mapNotNull { it.listFiles()?.toList() } var mangaDirs = baseDirs
.asSequence()
.mapNotNull { it.listFiles()?.toList() }
.flatten() .flatten()
.filter { it.isDirectory && if (time == 0L) it.name.contains(query, ignoreCase = true) else it.lastModified() >= time } .filter { it.isDirectory }
.filter { if (time == 0L) it.name.contains(query, ignoreCase = true) else it.lastModified() >= time }
.distinctBy { it.name } .distinctBy { it.name }
val state = ((if (filters.isEmpty()) POPULAR_FILTERS else filters)[0] as OrderBy).state val state = ((if (filters.isEmpty()) POPULAR_FILTERS else filters)[0] as OrderBy).state
@ -132,13 +137,15 @@ class LocalSource(private val context: Context) : CatalogueSource {
} }
} }
} }
return Observable.just(MangasPage(mangas, false))
return Observable.just(MangasPage(mangas.toList(), false))
} }
override fun fetchLatestUpdates(page: Int) = fetchSearchManga(page, "", LATEST_FILTERS) override fun fetchLatestUpdates(page: Int) = fetchSearchManga(page, "", LATEST_FILTERS)
override fun fetchMangaDetails(manga: SManga): Observable<SManga> { override fun fetchMangaDetails(manga: SManga): Observable<SManga> {
getBaseDirectories(context) getBaseDirectories(context)
.asSequence()
.mapNotNull { File(it, manga.url).listFiles()?.toList() } .mapNotNull { File(it, manga.url).listFiles()?.toList() }
.flatten() .flatten()
.firstOrNull { it.extension == "json" } .firstOrNull { it.extension == "json" }
@ -154,6 +161,7 @@ class LocalSource(private val context: Context) : CatalogueSource {
?: manga.genre ?: manga.genre
manga.status = json["status"]?.asInt ?: manga.status manga.status = json["status"]?.asInt ?: manga.status
} }
return Observable.just(manga) return Observable.just(manga)
} }
@ -204,8 +212,8 @@ class LocalSource(private val context: Context) : CatalogueSource {
var chapterNameIndex = 0 var chapterNameIndex = 0
var mangaTitleIndex = 0 var mangaTitleIndex = 0
while (chapterNameIndex < chapterName.length && mangaTitleIndex < mangaTitle.length) { while (chapterNameIndex < chapterName.length && mangaTitleIndex < mangaTitle.length) {
val chapterChar = chapterName.get(chapterNameIndex) val chapterChar = chapterName[chapterNameIndex]
val mangaChar = mangaTitle.get(mangaTitleIndex) val mangaChar = mangaTitle[mangaTitleIndex]
if (!chapterChar.equals(mangaChar, true)) { if (!chapterChar.equals(mangaChar, true)) {
val invalidChapterChar = !chapterChar.isLetterOrDigit() && !chapterChar.isWhitespace() val invalidChapterChar = !chapterChar.isLetterOrDigit() && !chapterChar.isWhitespace()
val invalidMangaChar = !mangaChar.isLetterOrDigit() && !mangaChar.isWhitespace() val invalidMangaChar = !mangaChar.isLetterOrDigit() && !mangaChar.isWhitespace()
@ -235,7 +243,7 @@ class LocalSource(private val context: Context) : CatalogueSource {
} }
private fun isSupportedFile(extension: String): Boolean { private fun isSupportedFile(extension: String): Boolean {
return extension.toLowerCase() in setOf("zip", "rar", "cbr", "cbz", "epub") return extension.toLowerCase() in SUPPORTED_ARCHIVE_TYPES
} }
fun getFormat(chapter: SChapter): Format { fun getFormat(chapter: SChapter): Format {
@ -269,8 +277,8 @@ class LocalSource(private val context: Context) : CatalogueSource {
return when (val format = getFormat(chapter)) { return when (val format = getFormat(chapter)) {
is Format.Directory -> { is Format.Directory -> {
val entry = format.file.listFiles() val entry = format.file.listFiles()
.sortedWith(Comparator<File> { f1, f2 -> f1.name.compareToCaseInsensitiveNaturalOrder(f2.name) }) ?.sortedWith(Comparator<File> { f1, f2 -> f1.name.compareToCaseInsensitiveNaturalOrder(f2.name) })
.find { !it.isDirectory && ImageUtil.isImage(it.name) { FileInputStream(it) } } ?.find { !it.isDirectory && ImageUtil.isImage(it.name) { FileInputStream(it) } }
entry?.let { updateCover(context, manga, it.inputStream()) } entry?.let { updateCover(context, manga, it.inputStream()) }
} }