From c92fdb52316ec3812f7944d90da7e24bab46e303 Mon Sep 17 00:00:00 2001 From: Cuong-Tran Date: Mon, 1 Jul 2024 18:25:54 +0700 Subject: [PATCH] improve: retry to load source in some case it's late --- .../eu/kanade/presentation/util/Navigator.kt | 2 +- .../source/browse/BrowseSourceScreen.kt | 16 ++-- .../source/browse/BrowseSourceScreenModel.kt | 75 +++++++++++++------ .../ui/browse/source/feed/SourceFeedScreen.kt | 14 +++- .../source/feed/SourceFeedScreenModel.kt | 30 +++++++- 5 files changed, 101 insertions(+), 36 deletions(-) diff --git a/app/src/main/java/eu/kanade/presentation/util/Navigator.kt b/app/src/main/java/eu/kanade/presentation/util/Navigator.kt index 2d6bb4643..cb43bf268 100644 --- a/app/src/main/java/eu/kanade/presentation/util/Navigator.kt +++ b/app/src/main/java/eu/kanade/presentation/util/Navigator.kt @@ -45,7 +45,7 @@ interface Tab : cafe.adriel.voyager.navigator.tab.Tab { abstract class Screen : Screen { // known bug: https://github.com/mihonapp/mihon/issues/712 // This is where it create a key Screen#uuid:transition which causes exception Key ... was used multiple times - override val key: ScreenKey = "${this::class.simpleName}#$uniqueScreenKey" + override val key: ScreenKey = "$uniqueScreenKey#${this::class.simpleName}" } /** diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreen.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreen.kt index ebacc16d5..57508cf82 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreen.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreen.kt @@ -127,12 +127,16 @@ data class BrowseSourceScreen( val context = LocalContext.current // SY <-- - if (screenModel.source is StubSource) { - MissingSourceScreen( - source = screenModel.source, - navigateUp = navigateUp, - ) - return + // KMK --> + screenModel.source.let { + // KMK <-- + if (it is StubSource) { + MissingSourceScreen( + source = it, + navigateUp = navigateUp, + ) + return + } } val scope = rememberCoroutineScope() diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreenModel.kt index c61081ad2..4c25cce85 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreenModel.kt @@ -35,6 +35,7 @@ import exh.source.mangaDexSourceIds import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList +import kotlinx.coroutines.delay import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.distinctUntilChanged @@ -118,7 +119,7 @@ open class BrowseSourceScreenModel( var displayMode by sourcePreferences.sourceDisplayMode().asState(screenModelScope) - val source = sourceManager.getOrStub(sourceId) + var source = sourceManager.getOrStub(sourceId) // SY --> val ehentaiBrowseDisplayMode by unsortedPreferences.enhancedEHentaiView().asState(screenModelScope) @@ -131,7 +132,18 @@ open class BrowseSourceScreenModel( // SY <-- init { - if (source is CatalogueSource) { + // KMK --> + screenModelScope.launchIO { + var retry = 10 + while (source !is CatalogueSource && retry-- > 0) { + // Sometime source is late to load, so we need to wait a bit + delay(100) + source = sourceManager.getOrStub(sourceId) + } + val source = source + if (source !is CatalogueSource) return@launchIO + // KMK <-- + mutableState.update { var query: String? = null var listing = it.listing @@ -147,38 +159,36 @@ open class BrowseSourceScreenModel( toolbarQuery = query, ) } - } - if (!basePreferences.incognitoMode().get()) { - sourcePreferences.lastUsedSource().set(source.id) - } - - // SY --> - val savedSearchFilters = savedSearch - val jsonFilters = filtersJson - val filters = state.value.filters - if (savedSearchFilters != null) { - val savedSearch = runBlocking { getExhSavedSearch.awaitOne(savedSearchFilters) { filters } } - if (savedSearch != null) { - search(query = savedSearch.query, filters = savedSearch.filterList) + if (!basePreferences.incognitoMode().get()) { + sourcePreferences.lastUsedSource().set(source.id) + } + + // SY --> + val savedSearchFilters = savedSearch + val jsonFilters = filtersJson + val filters = state.value.filters + if (savedSearchFilters != null) { + val savedSearch = runBlocking { getExhSavedSearch.awaitOne(savedSearchFilters) { filters } } + if (savedSearch != null) { + search(query = savedSearch.query, filters = savedSearch.filterList) + } + } else if (jsonFilters != null) { + runCatching { + val filtersJson = Json.decodeFromString(jsonFilters) + filterSerializer.deserialize(filters, filtersJson) + search(filters = filters) + } } - } else if (jsonFilters != null) { - runCatching { - val filtersJson = Json.decodeFromString(jsonFilters) - filterSerializer.deserialize(filters, filtersJson) - search(filters = filters) - } - } - if (source is CatalogueSource) { getExhSavedSearch.subscribe(source.id, source::getFilterList) .map { it.sortedWith(compareBy(String.CASE_INSENSITIVE_ORDER, EXHSavedSearch::name)) } .onEach { savedSearches -> mutableState.update { it.copy(savedSearches = savedSearches.toImmutableList()) } } .launchIn(screenModelScope) + // SY <-- } - // SY <-- } /** @@ -235,6 +245,9 @@ open class BrowseSourceScreenModel( // SY <-- fun resetFilters() { + // KMK --> + val source = source + // KMK <-- if (source !is CatalogueSource) return mutableState.update { it.copy(filters = source.getFilterList()) } @@ -255,6 +268,10 @@ open class BrowseSourceScreenModel( } fun search(query: String? = null, filters: FilterList? = null) { + // KMK --> + val source = source + // KMK <-- + if (source !is CatalogueSource) return // SY --> if (filters != null && filters !== state.value.filters) { @@ -276,6 +293,10 @@ open class BrowseSourceScreenModel( } fun searchGenre(genreName: String) { + // KMK --> + val source = source + // KMK <-- + if (source !is CatalogueSource) return val defaultFilters = source.getFilterList() @@ -493,6 +514,9 @@ open class BrowseSourceScreenModel( onToast: (StringResource) -> Unit, ) { screenModelScope.launchIO { + // KMK --> + val source = source + // KMK <-- if (source !is CatalogueSource) return@launchIO if (search.filterList == null && state.value.filters.isNotEmpty()) { @@ -529,6 +553,9 @@ open class BrowseSourceScreenModel( fun saveSearch( name: String, ) { + // KMK --> + val source = source + // KMK <-- if (source !is CatalogueSource) return screenModelScope.launchNonCancellable { val query = state.value.toolbarQuery?.takeUnless { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/feed/SourceFeedScreen.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/feed/SourceFeedScreen.kt index 0a7ed88b1..020b388aa 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/feed/SourceFeedScreen.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/feed/SourceFeedScreen.kt @@ -10,6 +10,7 @@ import cafe.adriel.voyager.core.model.rememberScreenModel import cafe.adriel.voyager.navigator.LocalNavigator import cafe.adriel.voyager.navigator.Navigator import cafe.adriel.voyager.navigator.currentOrThrow +import eu.kanade.presentation.browse.MissingSourceScreen import eu.kanade.presentation.browse.SourceFeedScreen import eu.kanade.presentation.browse.components.SourceFeedAddDialog import eu.kanade.presentation.browse.components.SourceFeedDeleteDialog @@ -33,6 +34,7 @@ import exh.util.nullIfBlank import tachiyomi.domain.manga.model.Manga import tachiyomi.domain.source.interactor.GetRemoteManga import tachiyomi.domain.source.model.SavedSearch +import tachiyomi.domain.source.model.StubSource import tachiyomi.presentation.core.screens.LoadingScreen class SourceFeedScreen(val sourceId: Long) : Screen() { @@ -50,6 +52,16 @@ class SourceFeedScreen(val sourceId: Long) : Screen() { val context = LocalContext.current // KMK --> + screenModel.source.let { + if (it is StubSource) { + MissingSourceScreen( + source = it, + navigateUp = navigator::pop, + ) + return + } + } + val bulkFavoriteScreenModel = rememberScreenModel { BulkFavoriteScreenModel() } val bulkFavoriteState by bulkFavoriteScreenModel.state.collectAsState() @@ -169,7 +181,7 @@ class SourceFeedScreen(val sourceId: Long) : Screen() { // KMK --> // navigator.replace( navigator.push( - // KMK <-- + // KMK <-- BrowseSourceScreen( sourceId, "id:$it", diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/feed/SourceFeedScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/feed/SourceFeedScreenModel.kt index 9adb28b0e..87de7cea8 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/feed/SourceFeedScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/feed/SourceFeedScreenModel.kt @@ -27,6 +27,7 @@ import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.asCoroutineDispatcher import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll +import kotlinx.coroutines.delay import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach @@ -73,7 +74,7 @@ open class SourceFeedScreenModel( private val getExhSavedSearch: GetExhSavedSearch = Injekt.get(), ) : StateScreenModel(SourceFeedState()) { - val source = sourceManager.getOrStub(sourceId) + var source = sourceManager.getOrStub(sourceId) val sourceIsMangaDex = sourceId in mangaDexSourceIds @@ -82,14 +83,23 @@ open class SourceFeedScreenModel( val startExpanded by uiPreferences.expandFilters().asState(screenModelScope) init { - if (source is CatalogueSource) { - setFilters(source.getFilterList()) + // KMK --> + screenModelScope.launchIO { + var retry = 10 + while (source !is CatalogueSource && retry-- > 0) { + // Sometime source is late to load, so we need to wait a bit + delay(100) + source = sourceManager.getOrStub(sourceId) + } + val source = source + if (source !is CatalogueSource) return@launchIO + // KMK <-- + setFilters(source.getFilterList()) screenModelScope.launchIO { val searches = loadSearches() mutableState.update { it.copy(savedSearches = searches) } } - getFeedSavedSearchBySourceId.subscribe(source.id) .onEach { val items = getSourcesToGetFeed(it) @@ -132,6 +142,9 @@ open class SourceFeedScreenModel( } private suspend fun getSourcesToGetFeed(feedSavedSearch: List): ImmutableList { + // KMK --> + val source = source + // KMK <-- if (source !is CatalogueSource) return persistentListOf() val savedSearches = getSavedSearchBySourceIdFeed.await(source.id) .associateBy { it.id } @@ -154,6 +167,9 @@ open class SourceFeedScreenModel( * Initiates get manga per feed. */ private fun getFeed(feedSavedSearch: List) { + // KMK --> + val source = source + // KMK <-- if (source !is CatalogueSource) return screenModelScope.launch { feedSavedSearch.map { sourceFeed -> @@ -222,6 +238,9 @@ open class SourceFeedScreenModel( .toImmutableList() fun onFilter(onBrowseClick: (query: String?, filters: String?) -> Unit) { + // KMK --> + val source = source + // KMK <-- if (source !is CatalogueSource) return screenModelScope.launchIO { val allDefault = state.value.filters == source.getFilterList() @@ -245,6 +264,9 @@ open class SourceFeedScreenModel( onBrowseClick: (query: String?, searchId: Long) -> Unit, onToast: (StringResource) -> Unit, ) { + // KMK --> + val source = source + // KMK <-- if (source !is CatalogueSource) return screenModelScope.launchIO { if (search.filterList == null && state.value.filters.isNotEmpty()) {