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:
parent
afceac15c8
commit
b3426f37e7
2 changed files with 33 additions and 35 deletions
|
@ -15,15 +15,13 @@ import eu.kanade.tachiyomi.extension.util.ExtensionInstaller
|
||||||
import eu.kanade.tachiyomi.extension.util.ExtensionLoader
|
import eu.kanade.tachiyomi.extension.util.ExtensionLoader
|
||||||
import eu.kanade.tachiyomi.source.Source
|
import eu.kanade.tachiyomi.source.Source
|
||||||
import eu.kanade.tachiyomi.util.lang.launchNow
|
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.preference.plusAssign
|
||||||
import eu.kanade.tachiyomi.util.system.logcat
|
import eu.kanade.tachiyomi.util.system.logcat
|
||||||
import eu.kanade.tachiyomi.util.system.toast
|
import eu.kanade.tachiyomi.util.system.toast
|
||||||
import kotlinx.coroutines.async
|
import kotlinx.coroutines.async
|
||||||
import kotlinx.coroutines.flow.Flow
|
|
||||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
import kotlinx.coroutines.flow.asSharedFlow
|
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
import logcat.LogPriority
|
import logcat.LogPriority
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
|
@ -96,15 +94,15 @@ class ExtensionManager(
|
||||||
var availableExtensions = emptyList<Extension.Available>()
|
var availableExtensions = emptyList<Extension.Available>()
|
||||||
private set(value) {
|
private set(value) {
|
||||||
field = value
|
field = value
|
||||||
availableExtensionsFlow.tryEmit(field)
|
availableExtensionsFlow.value = field
|
||||||
updatedInstalledExtensionsStatuses(value)
|
updatedInstalledExtensionsStatuses(value)
|
||||||
setupAvailableExtensionsSourcesDataMap(value)
|
setupAvailableExtensionsSourcesDataMap(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val availableExtensionsFlow = MutableSharedFlow<List<Extension.Available>>(replay = 1)
|
private val availableExtensionsFlow = MutableStateFlow(availableExtensions)
|
||||||
|
|
||||||
fun getAvailableExtensionsFlow(): Flow<List<Extension.Available>> {
|
fun getAvailableExtensionsFlow(): StateFlow<List<Extension.Available>> {
|
||||||
return availableExtensionsFlow.asSharedFlow()
|
return availableExtensionsFlow.asStateFlow()
|
||||||
}
|
}
|
||||||
|
|
||||||
private var availableExtensionsSourcesData: Map<Long, SourceData> = mapOf()
|
private var availableExtensionsSourcesData: Map<Long, SourceData> = mapOf()
|
||||||
|
@ -156,18 +154,16 @@ class ExtensionManager(
|
||||||
/**
|
/**
|
||||||
* Finds the available extensions in the [api] and updates [availableExtensions].
|
* Finds the available extensions in the [api] and updates [availableExtensions].
|
||||||
*/
|
*/
|
||||||
fun findAvailableExtensions() {
|
suspend fun findAvailableExtensions() {
|
||||||
launchNow {
|
val extensions: List<Extension.Available> = try {
|
||||||
val extensions: List<Extension.Available> = try {
|
api.findExtensions()
|
||||||
api.findExtensions()
|
} catch (e: Exception) {
|
||||||
} catch (e: Exception) {
|
logcat(LogPriority.ERROR, e)
|
||||||
logcat(LogPriority.ERROR, e)
|
withUIContext { context.toast(R.string.extension_api_error) }
|
||||||
context.toast(R.string.extension_api_error)
|
emptyList()
|
||||||
emptyList()
|
|
||||||
}
|
|
||||||
|
|
||||||
availableExtensions = extensions
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
availableExtensions = extensions
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -36,8 +36,6 @@ class ExtensionsPresenter(
|
||||||
override fun onCreate(savedState: Bundle?) {
|
override fun onCreate(savedState: Bundle?) {
|
||||||
super.onCreate(savedState)
|
super.onCreate(savedState)
|
||||||
|
|
||||||
extensionManager.findAvailableExtensions()
|
|
||||||
|
|
||||||
val context = Injekt.get<Application>()
|
val context = Injekt.get<Application>()
|
||||||
val extensionMapper: (Map<String, InstallStep>) -> ((Extension) -> ExtensionUiModel) = { map ->
|
val extensionMapper: (Map<String, InstallStep>) -> ((Extension) -> ExtensionUiModel) = { map ->
|
||||||
{
|
{
|
||||||
|
@ -71,13 +69,13 @@ class ExtensionsPresenter(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
launchIO {
|
presenterScope.launchIO {
|
||||||
combine(
|
combine(
|
||||||
_query,
|
_query,
|
||||||
getExtensions.subscribe(),
|
getExtensions.subscribe(),
|
||||||
_currentDownloads,
|
_currentDownloads,
|
||||||
) { query, (updates, installed, available, untrusted), downloads ->
|
) { query, (_updates, _installed, _available, _untrusted), downloads ->
|
||||||
val languagesWithExtensions = available
|
val languagesWithExtensions = _available
|
||||||
.filter(queryFilter(query))
|
.filter(queryFilter(query))
|
||||||
.groupBy { LocaleHelper.getSourceDisplayName(it.lang, context) }
|
.groupBy { LocaleHelper.getSourceDisplayName(it.lang, context) }
|
||||||
.toSortedMap()
|
.toSortedMap()
|
||||||
|
@ -90,14 +88,14 @@ class ExtensionsPresenter(
|
||||||
|
|
||||||
val items = mutableListOf<ExtensionUiModel>()
|
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()) {
|
if (updates.isNotEmpty()) {
|
||||||
items.add(ExtensionUiModel.Header.Resource(R.string.ext_updates_pending))
|
items.add(ExtensionUiModel.Header.Resource(R.string.ext_updates_pending))
|
||||||
items.addAll(updates)
|
items.addAll(updates)
|
||||||
}
|
}
|
||||||
|
|
||||||
val installed = installed.filter(queryFilter(query)).map(extensionMapper(downloads))
|
val installed = _installed.filter(queryFilter(query)).map(extensionMapper(downloads))
|
||||||
val untrusted = untrusted.filter(queryFilter(query)).map(extensionMapper(downloads))
|
val untrusted = _untrusted.filter(queryFilter(query)).map(extensionMapper(downloads))
|
||||||
if (installed.isNotEmpty() || untrusted.isNotEmpty()) {
|
if (installed.isNotEmpty() || untrusted.isNotEmpty()) {
|
||||||
items.add(ExtensionUiModel.Header.Resource(R.string.ext_installed))
|
items.add(ExtensionUiModel.Header.Resource(R.string.ext_installed))
|
||||||
items.addAll(installed)
|
items.addAll(installed)
|
||||||
|
@ -110,21 +108,22 @@ class ExtensionsPresenter(
|
||||||
|
|
||||||
items
|
items
|
||||||
}.collectLatest {
|
}.collectLatest {
|
||||||
state.isRefreshing = false
|
|
||||||
state.isLoading = false
|
state.isLoading = false
|
||||||
state.items = it
|
state.items = it
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
presenterScope.launchIO { findAvailableExtensions() }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun search(query: String) {
|
fun search(query: String) {
|
||||||
launchIO {
|
presenterScope.launchIO {
|
||||||
_query.emit(query)
|
_query.emit(query)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateAllExtensions() {
|
fun updateAllExtensions() {
|
||||||
launchIO {
|
presenterScope.launchIO {
|
||||||
if (state.isEmpty) return@launchIO
|
if (state.isEmpty) return@launchIO
|
||||||
val items = state.items
|
val items = state.items
|
||||||
items.mapNotNull {
|
items.mapNotNull {
|
||||||
|
@ -151,16 +150,16 @@ class ExtensionsPresenter(
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun removeDownloadState(extension: Extension) {
|
private fun removeDownloadState(extension: Extension) {
|
||||||
_currentDownloads.update { map ->
|
_currentDownloads.update { _map ->
|
||||||
val map = map.toMutableMap()
|
val map = _map.toMutableMap()
|
||||||
map.remove(extension.pkgName)
|
map.remove(extension.pkgName)
|
||||||
map
|
map
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addDownloadState(extension: Extension, installStep: InstallStep) {
|
private fun addDownloadState(extension: Extension, installStep: InstallStep) {
|
||||||
_currentDownloads.update { map ->
|
_currentDownloads.update { _map ->
|
||||||
val map = map.toMutableMap()
|
val map = _map.toMutableMap()
|
||||||
map[extension.pkgName] = installStep
|
map[extension.pkgName] = installStep
|
||||||
map
|
map
|
||||||
}
|
}
|
||||||
|
@ -180,8 +179,11 @@ class ExtensionsPresenter(
|
||||||
}
|
}
|
||||||
|
|
||||||
fun findAvailableExtensions() {
|
fun findAvailableExtensions() {
|
||||||
state.isRefreshing = true
|
presenterScope.launchIO {
|
||||||
extensionManager.findAvailableExtensions()
|
state.isRefreshing = true
|
||||||
|
extensionManager.findAvailableExtensions()
|
||||||
|
state.isRefreshing = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun trustSignature(signatureHash: String) {
|
fun trustSignature(signatureHash: String) {
|
||||||
|
|
Reference in a new issue