improve: retry to load source in some case it's late

This commit is contained in:
Cuong-Tran 2024-07-01 18:25:54 +07:00 committed by Tran M. Cuong
parent 19890ef4d4
commit c92fdb5231
5 changed files with 101 additions and 36 deletions

View file

@ -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}"
}
/**

View file

@ -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()

View file

@ -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<JsonArray>(jsonFilters)
filterSerializer.deserialize(filters, filtersJson)
search(filters = filters)
}
}
} else if (jsonFilters != null) {
runCatching {
val filtersJson = Json.decodeFromString<JsonArray>(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 {

View file

@ -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",

View file

@ -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>(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<FeedSavedSearch>): ImmutableList<SourceFeedUI> {
// 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<SourceFeedUI>) {
// 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()) {