Fix multiple issues regarding sources loading too late

Co-authored-by: jobobby04 <17078382+jobobby04@users.noreply.github.com>
Co-authored-by: AntsyLich <59261191+AntsyLich@users.noreply.github.com>
This commit is contained in:
Secozzi 2024-07-02 13:19:38 +02:00
parent 94730b153e
commit fd5d568a10
No known key found for this signature in database
GPG key ID: 71E9C97D8DDC2662
23 changed files with 141 additions and 29 deletions

View file

@ -0,0 +1,13 @@
package eu.kanade.core.util
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.remember
import tachiyomi.domain.source.anime.service.AnimeSourceManager
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
@Composable
fun ifAnimeSourcesLoaded(): Boolean {
return remember { Injekt.get<AnimeSourceManager>().isInitialized }.collectAsState().value
}

View file

@ -0,0 +1,13 @@
package eu.kanade.core.util
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.remember
import tachiyomi.domain.source.manga.service.MangaSourceManager
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
@Composable
fun ifMangaSourcesLoaded(): Boolean {
return remember { Injekt.get<MangaSourceManager>().isInitialized }.collectAsState().value
}

View file

@ -16,6 +16,7 @@ import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.debounce import kotlinx.coroutines.flow.debounce
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.flow.onStart
@ -318,19 +319,13 @@ class AnimeDownloadCache(
} }
// Try to wait until extensions and sources have loaded // Try to wait until extensions and sources have loaded
var sources = getSources() var sources = emptyList<AnimeSource>()
if (sources.isEmpty()) {
withTimeoutOrNull(30.seconds) { withTimeoutOrNull(30.seconds) {
while (!extensionManager.isInitialized) { extensionManager.isInitialized.first { it }
delay(2.seconds) sourceManager.isInitialized.first { it }
}
while (extensionManager.availableExtensionsFlow.value.isNotEmpty() && sources.isEmpty()) {
delay(2.seconds)
sources = getSources() sources = getSources()
} }
}
}
val sourceMap = sources.associate { val sourceMap = sources.associate {
provider.getSourceDirName(it).lowercase() to it.id provider.getSourceDirName(it).lowercase() to it.id

View file

@ -19,6 +19,7 @@ import kotlinx.coroutines.ensureActive
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.debounce import kotlinx.coroutines.flow.debounce
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.flow.onStart
@ -342,19 +343,13 @@ class MangaDownloadCache(
} }
// Try to wait until extensions and sources have loaded // Try to wait until extensions and sources have loaded
var sources = getSources() var sources = emptyList<MangaSource>()
if (sources.isEmpty()) {
withTimeoutOrNull(30.seconds) { withTimeoutOrNull(30.seconds) {
while (!extensionManager.isInitialized) { extensionManager.isInitialized.first { it }
delay(2.seconds) sourceManager.isInitialized.first { it }
}
while (extensionManager.availableExtensionsFlow.value.isNotEmpty() && sources.isEmpty()) {
delay(2.seconds)
sources = getSources() sources = getSources()
} }
}
}
val sourceMap = sources.associate { provider.getSourceDirName(it).lowercase() to it.id } val sourceMap = sources.associate { provider.getSourceDirName(it).lowercase() to it.id }

View file

@ -16,6 +16,7 @@ import eu.kanade.tachiyomi.util.system.toast
import kotlinx.coroutines.async import kotlinx.coroutines.async
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.emptyFlow import kotlinx.coroutines.flow.emptyFlow
import logcat.LogPriority import logcat.LogPriority
@ -44,8 +45,8 @@ class AnimeExtensionManager(
private val trustExtension: TrustAnimeExtension = Injekt.get(), private val trustExtension: TrustAnimeExtension = Injekt.get(),
) { ) {
var isInitialized = false private val _isInitialized = MutableStateFlow(false)
private set val isInitialized: StateFlow<Boolean> = _isInitialized.asStateFlow()
/** /**
* API where all the available anime extensions can be found. * API where all the available anime extensions can be found.
@ -119,7 +120,7 @@ class AnimeExtensionManager(
.filterIsInstance<AnimeLoadResult.Untrusted>() .filterIsInstance<AnimeLoadResult.Untrusted>()
.map { it.extension } .map { it.extension }
isInitialized = true _isInitialized.value = true
} }
/** /**

View file

@ -16,10 +16,10 @@ import eu.kanade.tachiyomi.util.system.toast
import kotlinx.coroutines.async import kotlinx.coroutines.async
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.emptyFlow import kotlinx.coroutines.flow.emptyFlow
import logcat.LogPriority import logcat.LogPriority
import tachiyomi.core.common.preference.plusAssign
import tachiyomi.core.common.util.lang.launchNow import tachiyomi.core.common.util.lang.launchNow
import tachiyomi.core.common.util.lang.withUIContext import tachiyomi.core.common.util.lang.withUIContext
import tachiyomi.core.common.util.system.logcat import tachiyomi.core.common.util.system.logcat
@ -42,8 +42,8 @@ class MangaExtensionManager(
private val trustExtension: TrustMangaExtension = Injekt.get(), private val trustExtension: TrustMangaExtension = Injekt.get(),
) { ) {
var isInitialized = false private val _isInitialized = MutableStateFlow(false)
private set val isInitialized: StateFlow<Boolean> = _isInitialized.asStateFlow()
/** /**
* API where all the available extensions can be found. * API where all the available extensions can be found.
@ -109,7 +109,7 @@ class MangaExtensionManager(
.filterIsInstance<MangaLoadResult.Untrusted>() .filterIsInstance<MangaLoadResult.Untrusted>()
.map { it.extension } .map { it.extension }
isInitialized = true _isInitialized.value = true
} }
/** /**

View file

@ -11,6 +11,8 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -29,6 +31,10 @@ class AndroidAnimeSourceManager(
private val extensionManager: AnimeExtensionManager, private val extensionManager: AnimeExtensionManager,
private val sourceRepository: AnimeStubSourceRepository, private val sourceRepository: AnimeStubSourceRepository,
) : AnimeSourceManager { ) : AnimeSourceManager {
private val _isInitialized = MutableStateFlow(false)
override val isInitialized: StateFlow<Boolean> = _isInitialized.asStateFlow()
private val downloadManager: AnimeDownloadManager by injectLazy() private val downloadManager: AnimeDownloadManager by injectLazy()
private val scope = CoroutineScope(Job() + Dispatchers.IO) private val scope = CoroutineScope(Job() + Dispatchers.IO)
@ -61,6 +67,7 @@ class AndroidAnimeSourceManager(
} }
} }
sourcesMapFlow.value = mutableMap sourcesMapFlow.value = mutableMap
_isInitialized.value = true
} }
} }

View file

@ -11,6 +11,8 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -29,6 +31,10 @@ class AndroidMangaSourceManager(
private val extensionManager: MangaExtensionManager, private val extensionManager: MangaExtensionManager,
private val sourceRepository: MangaStubSourceRepository, private val sourceRepository: MangaStubSourceRepository,
) : MangaSourceManager { ) : MangaSourceManager {
private val _isInitialized = MutableStateFlow(false)
override val isInitialized: StateFlow<Boolean> = _isInitialized.asStateFlow()
private val downloadManager: MangaDownloadManager by injectLazy() private val downloadManager: MangaDownloadManager by injectLazy()
private val scope = CoroutineScope(Job() + Dispatchers.IO) private val scope = CoroutineScope(Job() + Dispatchers.IO)
@ -61,6 +67,7 @@ class AndroidMangaSourceManager(
} }
} }
sourcesMapFlow.value = mutableMap sourcesMapFlow.value = mutableMap
_isInitialized.value = true
} }
} }

View file

@ -31,6 +31,7 @@ import androidx.preference.forEach
import androidx.preference.getOnBindEditTextListener import androidx.preference.getOnBindEditTextListener
import cafe.adriel.voyager.navigator.LocalNavigator import cafe.adriel.voyager.navigator.LocalNavigator
import cafe.adriel.voyager.navigator.currentOrThrow import cafe.adriel.voyager.navigator.currentOrThrow
import eu.kanade.core.util.ifAnimeSourcesLoaded
import eu.kanade.presentation.components.AppBar import eu.kanade.presentation.components.AppBar
import eu.kanade.presentation.util.Screen import eu.kanade.presentation.util.Screen
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
@ -40,6 +41,7 @@ import eu.kanade.tachiyomi.data.preference.SharedPreferencesDataStore
import eu.kanade.tachiyomi.widget.TachiyomiTextInputEditText.Companion.setIncognito import eu.kanade.tachiyomi.widget.TachiyomiTextInputEditText.Companion.setIncognito
import tachiyomi.domain.source.anime.service.AnimeSourceManager import tachiyomi.domain.source.anime.service.AnimeSourceManager
import tachiyomi.presentation.core.components.material.Scaffold import tachiyomi.presentation.core.components.material.Scaffold
import tachiyomi.presentation.core.screens.LoadingScreen
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
@ -47,6 +49,11 @@ class AnimeSourcePreferencesScreen(val sourceId: Long) : Screen() {
@Composable @Composable
override fun Content() { override fun Content() {
if (!ifAnimeSourcesLoaded()) {
LoadingScreen()
return
}
val context = LocalContext.current val context = LocalContext.current
val navigator = LocalNavigator.currentOrThrow val navigator = LocalNavigator.currentOrThrow

View file

@ -18,6 +18,7 @@ import androidx.paging.compose.collectAsLazyPagingItems
import cafe.adriel.voyager.core.model.rememberScreenModel import cafe.adriel.voyager.core.model.rememberScreenModel
import cafe.adriel.voyager.navigator.LocalNavigator import cafe.adriel.voyager.navigator.LocalNavigator
import cafe.adriel.voyager.navigator.currentOrThrow import cafe.adriel.voyager.navigator.currentOrThrow
import eu.kanade.core.util.ifAnimeSourcesLoaded
import eu.kanade.presentation.browse.anime.BrowseAnimeSourceContent import eu.kanade.presentation.browse.anime.BrowseAnimeSourceContent
import eu.kanade.presentation.components.SearchToolbar import eu.kanade.presentation.components.SearchToolbar
import eu.kanade.presentation.util.Screen import eu.kanade.presentation.util.Screen
@ -34,6 +35,7 @@ import tachiyomi.i18n.MR
import tachiyomi.presentation.core.components.material.ExtendedFloatingActionButton import tachiyomi.presentation.core.components.material.ExtendedFloatingActionButton
import tachiyomi.presentation.core.components.material.Scaffold import tachiyomi.presentation.core.components.material.Scaffold
import tachiyomi.presentation.core.i18n.stringResource import tachiyomi.presentation.core.i18n.stringResource
import tachiyomi.presentation.core.screens.LoadingScreen
import tachiyomi.source.local.entries.anime.LocalAnimeSource import tachiyomi.source.local.entries.anime.LocalAnimeSource
data class AnimeSourceSearchScreen( data class AnimeSourceSearchScreen(
@ -44,6 +46,11 @@ data class AnimeSourceSearchScreen(
@Composable @Composable
override fun Content() { override fun Content() {
if (!ifAnimeSourcesLoaded()) {
LoadingScreen()
return
}
val uriHandler = LocalUriHandler.current val uriHandler = LocalUriHandler.current
val navigator = LocalNavigator.currentOrThrow val navigator = LocalNavigator.currentOrThrow
val scope = rememberCoroutineScope() val scope = rememberCoroutineScope()

View file

@ -35,6 +35,7 @@ import androidx.paging.compose.collectAsLazyPagingItems
import cafe.adriel.voyager.core.model.rememberScreenModel import cafe.adriel.voyager.core.model.rememberScreenModel
import cafe.adriel.voyager.navigator.LocalNavigator import cafe.adriel.voyager.navigator.LocalNavigator
import cafe.adriel.voyager.navigator.currentOrThrow import cafe.adriel.voyager.navigator.currentOrThrow
import eu.kanade.core.util.ifAnimeSourcesLoaded
import eu.kanade.presentation.browse.anime.BrowseAnimeSourceContent import eu.kanade.presentation.browse.anime.BrowseAnimeSourceContent
import eu.kanade.presentation.browse.anime.MissingSourceScreen import eu.kanade.presentation.browse.anime.MissingSourceScreen
import eu.kanade.presentation.browse.anime.components.BrowseAnimeSourceToolbar import eu.kanade.presentation.browse.anime.components.BrowseAnimeSourceToolbar
@ -60,6 +61,7 @@ import tachiyomi.i18n.MR
import tachiyomi.presentation.core.components.material.Scaffold import tachiyomi.presentation.core.components.material.Scaffold
import tachiyomi.presentation.core.components.material.padding import tachiyomi.presentation.core.components.material.padding
import tachiyomi.presentation.core.i18n.stringResource import tachiyomi.presentation.core.i18n.stringResource
import tachiyomi.presentation.core.screens.LoadingScreen
import tachiyomi.source.local.entries.anime.LocalAnimeSource import tachiyomi.source.local.entries.anime.LocalAnimeSource
data class BrowseAnimeSourceScreen( data class BrowseAnimeSourceScreen(
@ -73,6 +75,11 @@ data class BrowseAnimeSourceScreen(
@Composable @Composable
override fun Content() { override fun Content() {
if (!ifAnimeSourcesLoaded()) {
LoadingScreen()
return
}
val screenModel = rememberScreenModel { BrowseAnimeSourceScreenModel(sourceId, listingQuery) } val screenModel = rememberScreenModel { BrowseAnimeSourceScreenModel(sourceId, listingQuery) }
val state by screenModel.state.collectAsState() val state by screenModel.state.collectAsState()

View file

@ -10,6 +10,7 @@ import androidx.compose.runtime.setValue
import cafe.adriel.voyager.core.model.rememberScreenModel import cafe.adriel.voyager.core.model.rememberScreenModel
import cafe.adriel.voyager.navigator.LocalNavigator import cafe.adriel.voyager.navigator.LocalNavigator
import cafe.adriel.voyager.navigator.currentOrThrow import cafe.adriel.voyager.navigator.currentOrThrow
import eu.kanade.core.util.ifAnimeSourcesLoaded
import eu.kanade.presentation.browse.anime.GlobalAnimeSearchScreen import eu.kanade.presentation.browse.anime.GlobalAnimeSearchScreen
import eu.kanade.presentation.util.Screen import eu.kanade.presentation.util.Screen
import eu.kanade.tachiyomi.ui.browse.anime.source.browse.BrowseAnimeSourceScreen import eu.kanade.tachiyomi.ui.browse.anime.source.browse.BrowseAnimeSourceScreen
@ -23,6 +24,11 @@ class GlobalAnimeSearchScreen(
@Composable @Composable
override fun Content() { override fun Content() {
if (!ifAnimeSourcesLoaded()) {
LoadingScreen()
return
}
val navigator = LocalNavigator.currentOrThrow val navigator = LocalNavigator.currentOrThrow
val screenModel = rememberScreenModel { val screenModel = rememberScreenModel {

View file

@ -31,6 +31,7 @@ import androidx.preference.forEach
import androidx.preference.getOnBindEditTextListener import androidx.preference.getOnBindEditTextListener
import cafe.adriel.voyager.navigator.LocalNavigator import cafe.adriel.voyager.navigator.LocalNavigator
import cafe.adriel.voyager.navigator.currentOrThrow import cafe.adriel.voyager.navigator.currentOrThrow
import eu.kanade.core.util.ifMangaSourcesLoaded
import eu.kanade.presentation.components.AppBar import eu.kanade.presentation.components.AppBar
import eu.kanade.presentation.util.Screen import eu.kanade.presentation.util.Screen
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
@ -40,6 +41,7 @@ import eu.kanade.tachiyomi.source.sourcePreferences
import eu.kanade.tachiyomi.widget.TachiyomiTextInputEditText.Companion.setIncognito import eu.kanade.tachiyomi.widget.TachiyomiTextInputEditText.Companion.setIncognito
import tachiyomi.domain.source.manga.service.MangaSourceManager import tachiyomi.domain.source.manga.service.MangaSourceManager
import tachiyomi.presentation.core.components.material.Scaffold import tachiyomi.presentation.core.components.material.Scaffold
import tachiyomi.presentation.core.screens.LoadingScreen
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
@ -47,6 +49,11 @@ class MangaSourcePreferencesScreen(val sourceId: Long) : Screen() {
@Composable @Composable
override fun Content() { override fun Content() {
if (!ifMangaSourcesLoaded()) {
LoadingScreen()
return
}
val context = LocalContext.current val context = LocalContext.current
val navigator = LocalNavigator.currentOrThrow val navigator = LocalNavigator.currentOrThrow

View file

@ -18,6 +18,7 @@ import androidx.paging.compose.collectAsLazyPagingItems
import cafe.adriel.voyager.core.model.rememberScreenModel import cafe.adriel.voyager.core.model.rememberScreenModel
import cafe.adriel.voyager.navigator.LocalNavigator import cafe.adriel.voyager.navigator.LocalNavigator
import cafe.adriel.voyager.navigator.currentOrThrow import cafe.adriel.voyager.navigator.currentOrThrow
import eu.kanade.core.util.ifMangaSourcesLoaded
import eu.kanade.presentation.browse.manga.BrowseSourceContent import eu.kanade.presentation.browse.manga.BrowseSourceContent
import eu.kanade.presentation.components.SearchToolbar import eu.kanade.presentation.components.SearchToolbar
import eu.kanade.presentation.util.Screen import eu.kanade.presentation.util.Screen
@ -34,6 +35,7 @@ import tachiyomi.i18n.MR
import tachiyomi.presentation.core.components.material.ExtendedFloatingActionButton import tachiyomi.presentation.core.components.material.ExtendedFloatingActionButton
import tachiyomi.presentation.core.components.material.Scaffold import tachiyomi.presentation.core.components.material.Scaffold
import tachiyomi.presentation.core.i18n.stringResource import tachiyomi.presentation.core.i18n.stringResource
import tachiyomi.presentation.core.screens.LoadingScreen
import tachiyomi.source.local.entries.manga.LocalMangaSource import tachiyomi.source.local.entries.manga.LocalMangaSource
data class MangaSourceSearchScreen( data class MangaSourceSearchScreen(
@ -44,6 +46,11 @@ data class MangaSourceSearchScreen(
@Composable @Composable
override fun Content() { override fun Content() {
if (!ifMangaSourcesLoaded()) {
LoadingScreen()
return
}
val uriHandler = LocalUriHandler.current val uriHandler = LocalUriHandler.current
val navigator = LocalNavigator.currentOrThrow val navigator = LocalNavigator.currentOrThrow
val scope = rememberCoroutineScope() val scope = rememberCoroutineScope()

View file

@ -35,6 +35,7 @@ import androidx.paging.compose.collectAsLazyPagingItems
import cafe.adriel.voyager.core.model.rememberScreenModel import cafe.adriel.voyager.core.model.rememberScreenModel
import cafe.adriel.voyager.navigator.LocalNavigator import cafe.adriel.voyager.navigator.LocalNavigator
import cafe.adriel.voyager.navigator.currentOrThrow import cafe.adriel.voyager.navigator.currentOrThrow
import eu.kanade.core.util.ifMangaSourcesLoaded
import eu.kanade.presentation.browse.anime.components.RemoveEntryDialog import eu.kanade.presentation.browse.anime.components.RemoveEntryDialog
import eu.kanade.presentation.browse.manga.BrowseSourceContent import eu.kanade.presentation.browse.manga.BrowseSourceContent
import eu.kanade.presentation.browse.manga.MissingSourceScreen import eu.kanade.presentation.browse.manga.MissingSourceScreen
@ -60,6 +61,7 @@ import tachiyomi.i18n.MR
import tachiyomi.presentation.core.components.material.Scaffold import tachiyomi.presentation.core.components.material.Scaffold
import tachiyomi.presentation.core.components.material.padding import tachiyomi.presentation.core.components.material.padding
import tachiyomi.presentation.core.i18n.stringResource import tachiyomi.presentation.core.i18n.stringResource
import tachiyomi.presentation.core.screens.LoadingScreen
import tachiyomi.source.local.entries.manga.LocalMangaSource import tachiyomi.source.local.entries.manga.LocalMangaSource
data class BrowseMangaSourceScreen( data class BrowseMangaSourceScreen(
@ -73,6 +75,11 @@ data class BrowseMangaSourceScreen(
@Composable @Composable
override fun Content() { override fun Content() {
if (!ifMangaSourcesLoaded()) {
LoadingScreen()
return
}
val screenModel = rememberScreenModel { BrowseMangaSourceScreenModel(sourceId, listingQuery) } val screenModel = rememberScreenModel { BrowseMangaSourceScreenModel(sourceId, listingQuery) }
val state by screenModel.state.collectAsState() val state by screenModel.state.collectAsState()

View file

@ -10,6 +10,7 @@ import androidx.compose.runtime.setValue
import cafe.adriel.voyager.core.model.rememberScreenModel import cafe.adriel.voyager.core.model.rememberScreenModel
import cafe.adriel.voyager.navigator.LocalNavigator import cafe.adriel.voyager.navigator.LocalNavigator
import cafe.adriel.voyager.navigator.currentOrThrow import cafe.adriel.voyager.navigator.currentOrThrow
import eu.kanade.core.util.ifMangaSourcesLoaded
import eu.kanade.presentation.browse.manga.GlobalMangaSearchScreen import eu.kanade.presentation.browse.manga.GlobalMangaSearchScreen
import eu.kanade.presentation.util.Screen import eu.kanade.presentation.util.Screen
import eu.kanade.tachiyomi.ui.browse.manga.source.browse.BrowseMangaSourceScreen import eu.kanade.tachiyomi.ui.browse.manga.source.browse.BrowseMangaSourceScreen
@ -23,6 +24,11 @@ class GlobalMangaSearchScreen(
@Composable @Composable
override fun Content() { override fun Content() {
if (!ifMangaSourcesLoaded()) {
LoadingScreen()
return
}
val navigator = LocalNavigator.currentOrThrow val navigator = LocalNavigator.currentOrThrow
val screenModel = rememberScreenModel { val screenModel = rememberScreenModel {

View file

@ -20,6 +20,7 @@ import cafe.adriel.voyager.core.model.rememberScreenModel
import cafe.adriel.voyager.navigator.LocalNavigator import cafe.adriel.voyager.navigator.LocalNavigator
import cafe.adriel.voyager.navigator.Navigator import cafe.adriel.voyager.navigator.Navigator
import cafe.adriel.voyager.navigator.currentOrThrow import cafe.adriel.voyager.navigator.currentOrThrow
import eu.kanade.core.util.ifAnimeSourcesLoaded
import eu.kanade.domain.entries.anime.model.hasCustomCover import eu.kanade.domain.entries.anime.model.hasCustomCover
import eu.kanade.domain.entries.anime.model.toSAnime import eu.kanade.domain.entries.anime.model.toSAnime
import eu.kanade.presentation.category.components.ChangeCategoryDialog import eu.kanade.presentation.category.components.ChangeCategoryDialog
@ -76,6 +77,11 @@ class AnimeScreen(
@Composable @Composable
override fun Content() { override fun Content() {
if (!ifAnimeSourcesLoaded()) {
LoadingScreen()
return
}
val navigator = LocalNavigator.currentOrThrow val navigator = LocalNavigator.currentOrThrow
val context = LocalContext.current val context = LocalContext.current
val haptic = LocalHapticFeedback.current val haptic = LocalHapticFeedback.current

View file

@ -22,6 +22,7 @@ import cafe.adriel.voyager.core.model.rememberScreenModel
import cafe.adriel.voyager.navigator.LocalNavigator import cafe.adriel.voyager.navigator.LocalNavigator
import cafe.adriel.voyager.navigator.Navigator import cafe.adriel.voyager.navigator.Navigator
import cafe.adriel.voyager.navigator.currentOrThrow import cafe.adriel.voyager.navigator.currentOrThrow
import eu.kanade.core.util.ifMangaSourcesLoaded
import eu.kanade.domain.entries.manga.model.hasCustomCover import eu.kanade.domain.entries.manga.model.hasCustomCover
import eu.kanade.domain.entries.manga.model.toSManga import eu.kanade.domain.entries.manga.model.toSManga
import eu.kanade.presentation.category.components.ChangeCategoryDialog import eu.kanade.presentation.category.components.ChangeCategoryDialog
@ -74,6 +75,11 @@ class MangaScreen(
@Composable @Composable
override fun Content() { override fun Content() {
if (!ifMangaSourcesLoaded()) {
LoadingScreen()
return
}
val navigator = LocalNavigator.currentOrThrow val navigator = LocalNavigator.currentOrThrow
val context = LocalContext.current val context = LocalContext.current
val haptic = LocalHapticFeedback.current val haptic = LocalHapticFeedback.current

View file

@ -44,6 +44,7 @@ import `is`.xyz.mpv.Utils
import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.receiveAsFlow import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.flow.update import kotlinx.coroutines.flow.update
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
@ -245,6 +246,7 @@ class PlayerViewModel @JvmOverloads constructor(
return try { return try {
val anime = getAnime.await(animeId) val anime = getAnime.await(animeId)
if (anime != null) { if (anime != null) {
sourceManager.isInitialized.first { it }
if (episodeId == -1L) episodeId = initialEpisodeId if (episodeId == -1L) episodeId = initialEpisodeId
checkTrackers(anime) checkTrackers(anime)

View file

@ -40,6 +40,7 @@ import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
import com.google.android.material.elevation.SurfaceColors import com.google.android.material.elevation.SurfaceColors
import com.google.android.material.transition.platform.MaterialContainerTransform import com.google.android.material.transition.platform.MaterialContainerTransform
import dev.chrisbanes.insetter.applyInsetter import dev.chrisbanes.insetter.applyInsetter
import eu.kanade.core.util.ifMangaSourcesLoaded
import eu.kanade.domain.base.BasePreferences import eu.kanade.domain.base.BasePreferences
import eu.kanade.presentation.reader.DisplayRefreshHost import eu.kanade.presentation.reader.DisplayRefreshHost
import eu.kanade.presentation.reader.OrientationSelectDialog import eu.kanade.presentation.reader.OrientationSelectDialog
@ -350,6 +351,10 @@ class ReaderActivity : BaseActivity() {
) )
} }
if (!ifMangaSourcesLoaded()) {
return@setComposeContent
}
val isHttpSource = viewModel.getSource() is HttpSource val isHttpSource = viewModel.getSource() is HttpSource
val isFullscreen by readerPreferences.fullscreen().collectAsState() val isFullscreen by readerPreferences.fullscreen().collectAsState()
val flashOnPageChange by readerPreferences.flashOnPageChange().collectAsState() val flashOnPageChange by readerPreferences.flashOnPageChange().collectAsState()

View file

@ -47,6 +47,7 @@ import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
@ -270,6 +271,7 @@ class ReaderViewModel @JvmOverloads constructor(
try { try {
val manga = getManga.await(mangaId) val manga = getManga.await(mangaId)
if (manga != null) { if (manga != null) {
sourceManager.isInitialized.first { it }
mutableState.update { it.copy(manga = manga) } mutableState.update { it.copy(manga = manga) }
if (chapterId == -1L) chapterId = initialChapterId if (chapterId == -1L) chapterId = initialChapterId

View file

@ -4,10 +4,13 @@ import eu.kanade.tachiyomi.animesource.AnimeCatalogueSource
import eu.kanade.tachiyomi.animesource.AnimeSource import eu.kanade.tachiyomi.animesource.AnimeSource
import eu.kanade.tachiyomi.animesource.online.AnimeHttpSource import eu.kanade.tachiyomi.animesource.online.AnimeHttpSource
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.StateFlow
import tachiyomi.domain.source.anime.model.StubAnimeSource import tachiyomi.domain.source.anime.model.StubAnimeSource
interface AnimeSourceManager { interface AnimeSourceManager {
val isInitialized: StateFlow<Boolean>
val catalogueSources: Flow<List<AnimeCatalogueSource>> val catalogueSources: Flow<List<AnimeCatalogueSource>>
fun get(sourceKey: Long): AnimeSource? fun get(sourceKey: Long): AnimeSource?

View file

@ -4,10 +4,13 @@ import eu.kanade.tachiyomi.source.CatalogueSource
import eu.kanade.tachiyomi.source.MangaSource import eu.kanade.tachiyomi.source.MangaSource
import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.source.online.HttpSource
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.StateFlow
import tachiyomi.domain.source.manga.model.StubMangaSource import tachiyomi.domain.source.manga.model.StubMangaSource
interface MangaSourceManager { interface MangaSourceManager {
val isInitialized: StateFlow<Boolean>
val catalogueSources: Flow<List<CatalogueSource>> val catalogueSources: Flow<List<CatalogueSource>>
fun get(sourceKey: Long): MangaSource? fun get(sourceKey: Long): MangaSource?