ExtensionPresenter: Fix crash on first launch (#7685)

* Revert "Use SharedFlow for available extensions to always emit the value (#7609)"

This reverts commit 73901f50c0.

* ExtensionPresenter: Explicitly set refreshing status

* Scope coroutines job to presenter

* cleanup

* fix toast
This commit is contained in:
Ivan Iskandar 2022-08-05 02:44:37 +07:00 committed by GitHub
parent afceac15c8
commit b3426f37e7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 33 additions and 35 deletions

View file

@ -15,15 +15,13 @@ import eu.kanade.tachiyomi.extension.util.ExtensionInstaller
import eu.kanade.tachiyomi.extension.util.ExtensionLoader
import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.util.lang.launchNow
import eu.kanade.tachiyomi.util.lang.withUIContext
import eu.kanade.tachiyomi.util.preference.plusAssign
import eu.kanade.tachiyomi.util.system.logcat
import eu.kanade.tachiyomi.util.system.toast
import kotlinx.coroutines.async
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.asStateFlow
import logcat.LogPriority
import rx.Observable
@ -96,15 +94,15 @@ class ExtensionManager(
var availableExtensions = emptyList<Extension.Available>()
private set(value) {
field = value
availableExtensionsFlow.tryEmit(field)
availableExtensionsFlow.value = field
updatedInstalledExtensionsStatuses(value)
setupAvailableExtensionsSourcesDataMap(value)
}
private val availableExtensionsFlow = MutableSharedFlow<List<Extension.Available>>(replay = 1)
private val availableExtensionsFlow = MutableStateFlow(availableExtensions)
fun getAvailableExtensionsFlow(): Flow<List<Extension.Available>> {
return availableExtensionsFlow.asSharedFlow()
fun getAvailableExtensionsFlow(): StateFlow<List<Extension.Available>> {
return availableExtensionsFlow.asStateFlow()
}
private var availableExtensionsSourcesData: Map<Long, SourceData> = mapOf()
@ -156,19 +154,17 @@ class ExtensionManager(
/**
* Finds the available extensions in the [api] and updates [availableExtensions].
*/
fun findAvailableExtensions() {
launchNow {
suspend fun findAvailableExtensions() {
val extensions: List<Extension.Available> = try {
api.findExtensions()
} catch (e: Exception) {
logcat(LogPriority.ERROR, e)
context.toast(R.string.extension_api_error)
withUIContext { context.toast(R.string.extension_api_error) }
emptyList()
}
availableExtensions = extensions
}
}
/**
* Sets the update field of the installed extensions with the given [availableExtensions].

View file

@ -36,8 +36,6 @@ class ExtensionsPresenter(
override fun onCreate(savedState: Bundle?) {
super.onCreate(savedState)
extensionManager.findAvailableExtensions()
val context = Injekt.get<Application>()
val extensionMapper: (Map<String, InstallStep>) -> ((Extension) -> ExtensionUiModel) = { map ->
{
@ -71,13 +69,13 @@ class ExtensionsPresenter(
}
}
launchIO {
presenterScope.launchIO {
combine(
_query,
getExtensions.subscribe(),
_currentDownloads,
) { query, (updates, installed, available, untrusted), downloads ->
val languagesWithExtensions = available
) { query, (_updates, _installed, _available, _untrusted), downloads ->
val languagesWithExtensions = _available
.filter(queryFilter(query))
.groupBy { LocaleHelper.getSourceDisplayName(it.lang, context) }
.toSortedMap()
@ -90,14 +88,14 @@ class ExtensionsPresenter(
val items = mutableListOf<ExtensionUiModel>()
val updates = updates.filter(queryFilter(query)).map(extensionMapper(downloads))
val updates = _updates.filter(queryFilter(query)).map(extensionMapper(downloads))
if (updates.isNotEmpty()) {
items.add(ExtensionUiModel.Header.Resource(R.string.ext_updates_pending))
items.addAll(updates)
}
val installed = installed.filter(queryFilter(query)).map(extensionMapper(downloads))
val untrusted = untrusted.filter(queryFilter(query)).map(extensionMapper(downloads))
val installed = _installed.filter(queryFilter(query)).map(extensionMapper(downloads))
val untrusted = _untrusted.filter(queryFilter(query)).map(extensionMapper(downloads))
if (installed.isNotEmpty() || untrusted.isNotEmpty()) {
items.add(ExtensionUiModel.Header.Resource(R.string.ext_installed))
items.addAll(installed)
@ -110,21 +108,22 @@ class ExtensionsPresenter(
items
}.collectLatest {
state.isRefreshing = false
state.isLoading = false
state.items = it
}
}
presenterScope.launchIO { findAvailableExtensions() }
}
fun search(query: String) {
launchIO {
presenterScope.launchIO {
_query.emit(query)
}
}
fun updateAllExtensions() {
launchIO {
presenterScope.launchIO {
if (state.isEmpty) return@launchIO
val items = state.items
items.mapNotNull {
@ -151,16 +150,16 @@ class ExtensionsPresenter(
}
private fun removeDownloadState(extension: Extension) {
_currentDownloads.update { map ->
val map = map.toMutableMap()
_currentDownloads.update { _map ->
val map = _map.toMutableMap()
map.remove(extension.pkgName)
map
}
}
private fun addDownloadState(extension: Extension, installStep: InstallStep) {
_currentDownloads.update { map ->
val map = map.toMutableMap()
_currentDownloads.update { _map ->
val map = _map.toMutableMap()
map[extension.pkgName] = installStep
map
}
@ -180,8 +179,11 @@ class ExtensionsPresenter(
}
fun findAvailableExtensions() {
presenterScope.launchIO {
state.isRefreshing = true
extensionManager.findAvailableExtensions()
state.isRefreshing = false
}
}
fun trustSignature(signatureHash: String) {