Handle async cache in updates and manga screens

- Also fix concurrent accesses to main cache map
- Also debounce sources and updates list updates to maybe avoid crashing due to dupe LazyColumn keys
This commit is contained in:
arkon
2022-10-22 10:50:44 -04:00
parent d558f9e1d6
commit 152eb5b951
7 changed files with 64 additions and 69 deletions
@@ -34,6 +34,7 @@ import eu.kanade.domain.track.model.toDomainTrack
import eu.kanade.domain.ui.UiPreferences
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.data.download.DownloadCache
import eu.kanade.tachiyomi.data.download.DownloadManager
import eu.kanade.tachiyomi.data.download.model.Download
import eu.kanade.tachiyomi.data.track.EnhancedTrackService
@@ -63,6 +64,7 @@ import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.launchIn
@@ -91,6 +93,7 @@ class MangaPresenter(
private val trackManager: TrackManager = Injekt.get(),
private val sourceManager: SourceManager = Injekt.get(),
private val downloadManager: DownloadManager = Injekt.get(),
private val downloadCache: DownloadCache = Injekt.get(),
private val getMangaAndChapters: GetMangaWithChapters = Injekt.get(),
private val getDuplicateLibraryManga: GetDuplicateLibraryManga = Injekt.get(),
private val setMangaChapterFlags: SetMangaChapterFlags = Injekt.get(),
@@ -113,9 +116,6 @@ class MangaPresenter(
private val successState: MangaScreenState.Success?
get() = state.value as? MangaScreenState.Success
private var observeDownloadsStatusJob: Job? = null
private var observeDownloadsPageJob: Job? = null
private var _trackList: List<TrackItem> = emptyList()
val trackList get() = _trackList
@@ -169,10 +169,11 @@ class MangaPresenter(
)
}
// For UI changes
presenterScope.launch {
getMangaAndChapters.subscribe(mangaId)
.distinctUntilChanged()
presenterScope.launchIO {
combine(
getMangaAndChapters.subscribe(mangaId).distinctUntilChanged(),
downloadCache.changes,
) { mangaAndChapters, _ -> mangaAndChapters }
.collectLatest { (manga, chapters) ->
val chapterItems = chapters.toChapterItemsParams(manga)
updateSuccessState {
@@ -181,20 +182,11 @@ class MangaPresenter(
chapters = chapterItems,
)
}
observeDownloads()
}
}
basePreferences.incognitoMode()
.asHotFlow { incognitoMode = it }
.launchIn(presenterScope)
observeDownloads()
basePreferences.downloadedOnly()
.asHotFlow { downloadedOnlyMode = it }
.launchIn(presenterScope)
// This block runs once on create
presenterScope.launchIO {
val manga = getMangaAndChapters.awaitManga(mangaId)
val chapters = getMangaAndChapters.awaitChapters(mangaId)
@@ -207,7 +199,7 @@ class MangaPresenter(
val needRefreshInfo = !manga.initialized
val needRefreshChapter = chapters.isEmpty()
// Show what we have earlier.
// Show what we have earlier
_state.update {
MangaScreenState.Success(
manga = manga,
@@ -238,6 +230,14 @@ class MangaPresenter(
// Initial loading finished
updateSuccessState { it.copy(isRefreshingData = false) }
}
basePreferences.incognitoMode()
.asHotFlow { incognitoMode = it }
.launchIn(presenterScope)
basePreferences.downloadedOnly()
.asHotFlow { downloadedOnlyMode = it }
.launchIn(presenterScope)
}
fun fetchAllFromSource(manualFetch: Boolean = true) {
@@ -467,9 +467,8 @@ class MangaPresenter(
// Chapters list - start
private fun observeDownloads() {
observeDownloadsStatusJob?.cancel()
observeDownloadsStatusJob = presenterScope.launchIO {
downloadManager.queue.getStatusAsFlow()
presenterScope.launchIO {
downloadManager.queue.statusFlow()
.filter { it.manga.id == successState?.manga?.id }
.catch { error -> logcat(LogPriority.ERROR, error) }
.collect {
@@ -479,9 +478,8 @@ class MangaPresenter(
}
}
observeDownloadsPageJob?.cancel()
observeDownloadsPageJob = presenterScope.launchIO {
downloadManager.queue.getProgressAsFlow()
presenterScope.launchIO {
downloadManager.queue.progressFlow()
.filter { it.manga.id == successState?.manga?.id }
.catch { error -> logcat(LogPriority.ERROR, error) }
.collect {