Library's first load is now async + private scope in library presenter

pull/3117/head
Jay 5 years ago
parent 3cd74ce05e
commit ed3e819829

@ -60,6 +60,7 @@ import eu.kanade.tachiyomi.util.system.getResourceColor
import eu.kanade.tachiyomi.util.system.launchUI import eu.kanade.tachiyomi.util.system.launchUI
import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.system.toast
import eu.kanade.tachiyomi.util.view.applyWindowInsetsForRootController import eu.kanade.tachiyomi.util.view.applyWindowInsetsForRootController
import eu.kanade.tachiyomi.util.view.gone
import eu.kanade.tachiyomi.util.view.scrollViewWith import eu.kanade.tachiyomi.util.view.scrollViewWith
import eu.kanade.tachiyomi.util.view.setOnQueryTextChangeListener import eu.kanade.tachiyomi.util.view.setOnQueryTextChangeListener
import eu.kanade.tachiyomi.util.view.setStyle import eu.kanade.tachiyomi.util.view.setStyle
@ -326,11 +327,11 @@ class LibraryController(
recycler.updatePaddingRelative(bottom = height) recycler.updatePaddingRelative(bottom = height)
presenter.onRestore() presenter.onRestore()
if (presenter.libraryItems.isNotEmpty()) if (presenter.libraryItems.isNotEmpty()) {
onNextLibraryUpdate(presenter.libraryItems, true) onNextLibraryUpdate(presenter.libraryItems, true)
else { } else {
recycler_layout.alpha = 0f recycler_layout.alpha = 0f
presenter.getLibraryBlocking() presenter.getLibrary()
} }
} }
@ -452,6 +453,7 @@ class LibraryController(
if (recycler_layout.alpha == 0f) recycler_layout.animate().alpha(1f).setDuration(500) if (recycler_layout.alpha == 0f) recycler_layout.animate().alpha(1f).setDuration(500)
.start() .start()
} else if (justStarted && freshStart) { } else if (justStarted && freshStart) {
progress.gone()
scrollToHeader(activeCategory) scrollToHeader(activeCategory)
fast_scroller.translationX = 0f fast_scroller.translationX = 0f
view?.post { view?.post {

@ -18,14 +18,15 @@ import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.source.online.HttpSource
import eu.kanade.tachiyomi.ui.library.filter.FilterBottomSheet import eu.kanade.tachiyomi.ui.library.filter.FilterBottomSheet
import eu.kanade.tachiyomi.util.lang.removeArticles import eu.kanade.tachiyomi.util.lang.removeArticles
import eu.kanade.tachiyomi.util.system.executeOnIO
import eu.kanade.tachiyomi.util.system.launchUI import eu.kanade.tachiyomi.util.system.launchUI
import eu.kanade.tachiyomi.widget.ExtendedNavigationView.Item.TriStateGroup.Companion.STATE_EXCLUDE import eu.kanade.tachiyomi.widget.ExtendedNavigationView.Item.TriStateGroup.Companion.STATE_EXCLUDE
import eu.kanade.tachiyomi.widget.ExtendedNavigationView.Item.TriStateGroup.Companion.STATE_IGNORE import eu.kanade.tachiyomi.widget.ExtendedNavigationView.Item.TriStateGroup.Companion.STATE_IGNORE
import eu.kanade.tachiyomi.widget.ExtendedNavigationView.Item.TriStateGroup.Companion.STATE_INCLUDE import eu.kanade.tachiyomi.widget.ExtendedNavigationView.Item.TriStateGroup.Companion.STATE_INCLUDE
import eu.kanade.tachiyomi.widget.ExtendedNavigationView.Item.TriStateGroup.Companion.STATE_REALLY_EXCLUDE import eu.kanade.tachiyomi.widget.ExtendedNavigationView.Item.TriStateGroup.Companion.STATE_REALLY_EXCLUDE
import kotlinx.coroutines.CoroutineStart import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.Job
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
@ -46,6 +47,8 @@ class LibraryPresenter(
private val downloadManager: DownloadManager = Injekt.get() private val downloadManager: DownloadManager = Injekt.get()
) { ) {
private var scope = CoroutineScope(Job() + Dispatchers.Default)
private val context = preferences.context private val context = preferences.context
private val loggedServices by lazy { Injekt.get<TrackManager>().services.filter { it.isLogged } } private val loggedServices by lazy { Injekt.get<TrackManager>().services.filter { it.isLogged } }
@ -62,12 +65,9 @@ class LibraryPresenter(
/** /**
* List of all manga to update the * List of all manga to update the
*/ */
// private var rawMangaMap: LibraryMap? = null
var libraryItems: List<LibraryItem> = emptyList() var libraryItems: List<LibraryItem> = emptyList()
private var allLibraryItems: List<LibraryItem> = emptyList() private var allLibraryItems: List<LibraryItem> = emptyList()
// private var currentMangaMap: LibraryMap? = null
private var totalChapters: Map<Long, Int>? = null private var totalChapters: Map<Long, Int>? = null
fun onDestroy() { fun onDestroy() {
@ -94,30 +94,15 @@ class LibraryPresenter(
mangaMap = applySort(mangaMap) mangaMap = applySort(mangaMap)
mangaMap mangaMap
} }
val freshStart = libraryItems.isEmpty()
libraryItems = mangaMap libraryItems = mangaMap
view.onNextLibraryUpdate(libraryItems) view.onNextLibraryUpdate(libraryItems, freshStart)
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
setTotalChapters() setTotalChapters()
} }
} }
} }
fun getLibraryBlocking() {
val mangaMap = {
val library = getLibraryFromDB()
library.apply { setDownloadCount(library) }
allLibraryItems = library
var mangaMap = library
mangaMap = applyFilters(mangaMap)
mangaMap = applySort(mangaMap)
mangaMap
}()
libraryItems = mangaMap
launchUI {
view.onNextLibraryUpdate(libraryItems)
}
}
/** /**
* Applies library filters to the given map of manga. * Applies library filters to the given map of manga.
* *
@ -530,21 +515,21 @@ class LibraryPresenter(
* @param mangas the list of manga to delete. * @param mangas the list of manga to delete.
*/ */
fun removeMangaFromLibrary(mangas: List<Manga>) { fun removeMangaFromLibrary(mangas: List<Manga>) {
GlobalScope.launch(Dispatchers.IO, CoroutineStart.DEFAULT) { scope.launch {
// Create a set of the list // Create a set of the list
val mangaToDelete = mangas.distinctBy { it.id } val mangaToDelete = mangas.distinctBy { it.id }
mangaToDelete.forEach { it.favorite = false } mangaToDelete.forEach { it.favorite = false }
db.insertMangas(mangaToDelete).executeAsBlocking() db.insertMangas(mangaToDelete).executeOnIO()
getLibrary() getLibrary()
} }
} }
fun confirmDeletion(mangas: List<Manga>) { fun confirmDeletion(mangas: List<Manga>) {
GlobalScope.launch(Dispatchers.IO, CoroutineStart.DEFAULT) { scope.launch {
val mangaToDelete = mangas.distinctBy { it.id } val mangaToDelete = mangas.distinctBy { it.id }
mangaToDelete.forEach { manga -> mangaToDelete.forEach { manga ->
db.resetMangaInfo(manga).executeAsBlocking() db.resetMangaInfo(manga).executeOnIO()
coverCache.deleteFromCache(manga.thumbnail_url) coverCache.deleteFromCache(manga.thumbnail_url)
val source = sourceManager.get(manga.source) as? HttpSource val source = sourceManager.get(manga.source) as? HttpSource
if (source != null) if (source != null)
@ -554,11 +539,11 @@ class LibraryPresenter(
} }
fun updateManga(manga: LibraryManga) { fun updateManga(manga: LibraryManga) {
GlobalScope.launch(Dispatchers.IO, CoroutineStart.DEFAULT) { scope.launch {
val rawMap = allLibraryItems ?: return@launch val rawMap = allLibraryItems
val currentMap = libraryItems ?: return@launch val currentMap = libraryItems
val id = manga.id ?: return@launch val id = manga.id ?: return@launch
val dbManga = db.getLibraryManga(id).executeAsBlocking() ?: return@launch val dbManga = db.getLibraryManga(id).executeOnIO() ?: return@launch
arrayOf(rawMap, currentMap).forEach { map -> arrayOf(rawMap, currentMap).forEach { map ->
map.forEach { item -> map.forEach { item ->
if (item.manga.id == dbManga.id) { if (item.manga.id == dbManga.id) {
@ -572,10 +557,10 @@ class LibraryPresenter(
} }
fun reAddMangas(mangas: List<Manga>) { fun reAddMangas(mangas: List<Manga>) {
GlobalScope.launch(Dispatchers.IO, CoroutineStart.DEFAULT) { scope.launch {
val mangaToAdd = mangas.distinctBy { it.id } val mangaToAdd = mangas.distinctBy { it.id }
mangaToAdd.forEach { it.favorite = true } mangaToAdd.forEach { it.favorite = true }
db.insertMangas(mangaToAdd).executeAsBlocking() db.insertMangas(mangaToAdd).executeOnIO()
getLibrary() getLibrary()
mangaToAdd.forEach { db.insertManga(it).executeAsBlocking() } mangaToAdd.forEach { db.insertManga(it).executeAsBlocking() }
} }
@ -620,12 +605,12 @@ class LibraryPresenter(
} }
fun rearrangeCategory(catId: Int?, mangaIds: List<Long>) { fun rearrangeCategory(catId: Int?, mangaIds: List<Long>) {
GlobalScope.launch(Dispatchers.IO) { scope.launch {
val category = categories.find { catId == it.id } ?: return@launch val category = categories.find { catId == it.id } ?: return@launch
category.mangaSort = null category.mangaSort = null
category.mangaOrder = mangaIds category.mangaOrder = mangaIds
if (category.id == 0) preferences.defaultMangaOrder().set(mangaIds.joinToString("/")) if (category.id == 0) preferences.defaultMangaOrder().set(mangaIds.joinToString("/"))
else db.insertCategory(category).executeAsBlocking() else db.insertCategory(category).executeOnIO()
requestSortUpdate() requestSortUpdate()
} }
} }
@ -635,7 +620,7 @@ class LibraryPresenter(
catId: Int?, catId: Int?,
mangaIds: List<Long> mangaIds: List<Long>
) { ) {
GlobalScope.launch(Dispatchers.IO) { scope.launch {
val categoryId = catId ?: return@launch val categoryId = catId ?: return@launch
val category = categories.find { catId == it.id } ?: return@launch val category = categories.find { catId == it.id } ?: return@launch
@ -646,7 +631,7 @@ class LibraryPresenter(
val categories = val categories =
if (catId == 0) emptyList() if (catId == 0) emptyList()
else else
db.getCategoriesForManga(manga).executeAsBlocking() db.getCategoriesForManga(manga).executeOnIO()
.filter { it.id != oldCatId } + listOf(category) .filter { it.id != oldCatId } + listOf(category)
for (cat in categories) { for (cat in categories) {

@ -2,6 +2,7 @@ package eu.kanade.tachiyomi.util.system
import com.pushtorefresh.storio.sqlite.operations.get.PreparedGetListOfObjects import com.pushtorefresh.storio.sqlite.operations.get.PreparedGetListOfObjects
import com.pushtorefresh.storio.sqlite.operations.get.PreparedGetObject import com.pushtorefresh.storio.sqlite.operations.get.PreparedGetObject
import com.pushtorefresh.storio.sqlite.operations.put.PreparedPutCollectionOfObjects
import com.pushtorefresh.storio.sqlite.operations.put.PreparedPutObject import com.pushtorefresh.storio.sqlite.operations.put.PreparedPutObject
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
@ -17,3 +18,7 @@ suspend fun <T> PreparedGetObject<T>.executeOnIO(): T? {
suspend fun <T> PreparedPutObject<T>.executeOnIO() { suspend fun <T> PreparedPutObject<T>.executeOnIO() {
withContext(Dispatchers.IO) { executeAsBlocking() } withContext(Dispatchers.IO) { executeAsBlocking() }
} }
suspend fun <T> PreparedPutCollectionOfObjects<T>.executeOnIO() {
withContext(Dispatchers.IO) { executeAsBlocking() }
}

@ -6,6 +6,12 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<ProgressBar
android:id="@+id/progress"
android:layout_gravity="center"
android:layout_width="75dp"
android:layout_height="75dp"/>
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/swipe_refresh" android:id="@+id/swipe_refresh"
android:layout_width="match_parent" android:layout_width="match_parent"

Loading…
Cancel
Save