Clean up the reader filter logic (#444)

* move chapter filtering to its own class and injekt it.
Clean up the logic around the filter to prevent unneeded filtering and to make it more understandable

* switch to .not
This commit is contained in:
Carlos 2020-05-23 19:27:21 -04:00 committed by GitHub
parent 8f410ca864
commit 1d5fe4f775
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 89 additions and 57 deletions

View File

@ -12,6 +12,7 @@ import eu.kanade.tachiyomi.data.track.TrackManager
import eu.kanade.tachiyomi.extension.ExtensionManager import eu.kanade.tachiyomi.extension.ExtensionManager
import eu.kanade.tachiyomi.network.NetworkHelper import eu.kanade.tachiyomi.network.NetworkHelper
import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.ui.reader.ReaderChapterFilter
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import uy.kohesive.injekt.api.InjektModule import uy.kohesive.injekt.api.InjektModule
@ -48,6 +49,8 @@ class AppModule(val app: Application) : InjektModule {
addSingletonFactory { Gson() } addSingletonFactory { Gson() }
addSingletonFactory { ReaderChapterFilter() }
// Asynchronously init expensive components for a faster cold start // Asynchronously init expensive components for a faster cold start
GlobalScope.launch { get<PreferencesHelper>() } GlobalScope.launch { get<PreferencesHelper>() }

View File

@ -0,0 +1,66 @@
package eu.kanade.tachiyomi.ui.reader
import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.download.DownloadManager
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
/**
* This class filters chapters for the reader based on the user enabled preferences and filters
*/
class ReaderChapterFilter(
private val downloadManager: DownloadManager = Injekt.get(),
private val preferences: PreferencesHelper = Injekt.get()
) {
fun filterChapter(
dbChapters: List<Chapter>,
manga: Manga,
chapterId: Long,
selectedChapter: Chapter?
): List<Chapter> {
// if neither preference is enabled dont even filter
if (!preferences.skipRead() && !preferences.skipFiltered()) {
return dbChapters
}
var filteredChapters = dbChapters
if (preferences.skipRead()) {
filteredChapters = filteredChapters.filter { !it.read }
// add the selected chapter to the list in case it was read and user clicked it
if (chapterId != -1L) {
val find = filteredChapters.find { it.id == chapterId }
if (find == null) {
val mutableList = filteredChapters.toMutableList()
selectedChapter?.let { mutableList.add(it) }
filteredChapters = mutableList.toList()
}
}
}
if (preferences.skipFiltered()) {
val readEnabled = manga.readFilter == Manga.SHOW_READ
val unreadEnabled = manga.readFilter == Manga.SHOW_UNREAD
val downloadEnabled = manga.downloadedFilter == Manga.SHOW_DOWNLOADED
val bookmarkEnabled = manga.bookmarkedFilter == Manga.SHOW_BOOKMARKED
// if none of the filters are enabled skip the filtering of them
if (readEnabled || unreadEnabled || downloadEnabled || bookmarkEnabled) {
filteredChapters = filteredChapters.filter {
if (readEnabled && it.read.not() ||
(unreadEnabled && it.read) ||
(bookmarkEnabled && it.bookmark.not()) ||
(downloadEnabled && downloadManager.isChapterDownloaded(it, manga).not())
) {
return@filter false
}
return@filter true
}
}
}
return filteredChapters
}
}

View File

@ -27,7 +27,6 @@ import eu.kanade.tachiyomi.ui.reader.model.ReaderPage
import eu.kanade.tachiyomi.ui.reader.model.ViewerChapters import eu.kanade.tachiyomi.ui.reader.model.ViewerChapters
import eu.kanade.tachiyomi.util.storage.DiskUtil import eu.kanade.tachiyomi.util.storage.DiskUtil
import eu.kanade.tachiyomi.util.system.ImageUtil import eu.kanade.tachiyomi.util.system.ImageUtil
import eu.kanade.tachiyomi.util.system.executeOnIO
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -52,7 +51,8 @@ class ReaderPresenter(
private val sourceManager: SourceManager = Injekt.get(), private val sourceManager: SourceManager = Injekt.get(),
private val downloadManager: DownloadManager = Injekt.get(), private val downloadManager: DownloadManager = Injekt.get(),
private val coverCache: CoverCache = Injekt.get(), private val coverCache: CoverCache = Injekt.get(),
private val preferences: PreferencesHelper = Injekt.get() private val preferences: PreferencesHelper = Injekt.get(),
private val readerChapterFilter: ReaderChapterFilter = Injekt.get()
) : BasePresenter<ReaderActivity>() { ) : BasePresenter<ReaderActivity>() {
/** /**
@ -97,38 +97,8 @@ class ReaderPresenter(
val selectedChapter = dbChapters.find { it.id == chapterId } val selectedChapter = dbChapters.find { it.id == chapterId }
?: error("Requested chapter of id $chapterId not found in chapter list") ?: error("Requested chapter of id $chapterId not found in chapter list")
val chaptersForReader = val chaptersForReader = readerChapterFilter
if (preferences.skipRead() || preferences.skipFiltered()) { .filterChapter(dbChapters, manga, chapterId, selectedChapter)
val list = dbChapters
.filter {
if (preferences.skipRead() && it.read) {
return@filter false
} else if (preferences.skipFiltered()) {
if (
(manga.readFilter == Manga.SHOW_READ && !it.read) ||
(manga.readFilter == Manga.SHOW_UNREAD && it.read) ||
(
manga.downloadedFilter == Manga.SHOW_DOWNLOADED &&
!downloadManager.isChapterDownloaded(it, manga)
) ||
(manga.bookmarkedFilter == Manga.SHOW_BOOKMARKED && !it.bookmark)
) {
return@filter false
}
}
true
}
.toMutableList()
val find = list.find { it.id == chapterId }
if (find == null) {
list.add(selectedChapter)
}
list
} else {
dbChapters
}
when (manga.sorting) { when (manga.sorting) {
Manga.SORTING_SOURCE -> ChapterLoadBySource().get(chaptersForReader) Manga.SORTING_SOURCE -> ChapterLoadBySource().get(chaptersForReader)
@ -212,33 +182,26 @@ class ReaderPresenter(
suspend fun getChapters(): List<ReaderChapterItem> { suspend fun getChapters(): List<ReaderChapterItem> {
val manga = manga ?: return emptyList() val manga = manga ?: return emptyList()
chapterItems = withContext(Dispatchers.IO) { chapterItems = withContext(Dispatchers.IO) {
val list = db.getChapters(manga).executeOnIO().filter { val dbChapters = db.getChapters(manga).executeAsBlocking()
if (preferences.skipFiltered()) { val list = readerChapterFilter
if ((manga.readFilter == Manga.SHOW_READ && !it.read) || .filterChapter(dbChapters, manga, -1L, null)
(manga.readFilter == Manga.SHOW_UNREAD && it.read) || .sortedBy {
(manga.downloadedFilter == Manga.SHOW_DOWNLOADED && when (manga.sorting) {
!downloadManager.isChapterDownloaded(it, manga)) || Manga.SORTING_NUMBER -> it.chapter_number
(manga.bookmarkedFilter == Manga.SHOW_BOOKMARKED && !it.bookmark)) { else -> it.source_order.toFloat()
return@filter false
} }
true }.map {
} else { ReaderChapterItem(
true it, manga, it.id == getCurrentChapter()?.chapter?.id ?: chapterId
)
} }
}.sortedBy { if (!manga.sortDescending(preferences.chaptersDescAsDefault().getOrDefault())) {
when (manga.sorting) {
Manga.SORTING_NUMBER -> it.chapter_number
else -> it.source_order.toFloat()
}
}.map {
ReaderChapterItem(
it, manga, it.id == getCurrentChapter()?.chapter?.id ?: chapterId
)
}
if (!manga.sortDescending(preferences.chaptersDescAsDefault().getOrDefault()))
list.reversed() list.reversed()
else list } else {
list
}
} }
return chapterItems return chapterItems
} }