Remove redundancy in ExtensionManager

(cherry picked from commit 93925a72866892358b7f46645e1f189b2cf3bc1d)

# Conflicts:
#	app/src/main/java/eu/kanade/tachiyomi/extension/ExtensionManager.kt
#	app/src/main/java/eu/kanade/tachiyomi/source/SourceManager.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchPresenter.kt
This commit is contained in:
arkon 2022-10-21 14:42:21 -04:00 committed by Jobobby04
parent 893443222d
commit 9fafe15081
8 changed files with 49 additions and 94 deletions

View File

@ -13,7 +13,7 @@ class GetExtensionLanguages(
fun subscribe(): Flow<List<String>> { fun subscribe(): Flow<List<String>> {
return combine( return combine(
preferences.enabledLanguages().changes(), preferences.enabledLanguages().changes(),
extensionManager.getAvailableExtensionsFlow(), extensionManager.availableExtensionsFlow,
) { enabledLanguage, availableExtensions -> ) { enabledLanguage, availableExtensions ->
availableExtensions availableExtensions
.flatMap { ext -> .flatMap { ext ->

View File

@ -17,9 +17,9 @@ class GetExtensionsByType(
return combine( return combine(
preferences.enabledLanguages().changes(), preferences.enabledLanguages().changes(),
extensionManager.getInstalledExtensionsFlow(), extensionManager.installedExtensionsFlow,
extensionManager.getUntrustedExtensionsFlow(), extensionManager.untrustedExtensionsFlow,
extensionManager.getAvailableExtensionsFlow(), extensionManager.availableExtensionsFlow,
) { _activeLanguages, _installed, _untrusted, _available -> ) { _activeLanguages, _installed, _untrusted, _available ->
val (updates, installed) = _installed val (updates, installed) = _installed
.filter { (showNsfwSources || it.isNsfw.not()) } .filter { (showNsfwSources || it.isNsfw.not()) }

View File

@ -3,7 +3,6 @@ package eu.kanade.tachiyomi.extension
import android.content.Context import android.content.Context
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import com.jakewharton.rxrelay.BehaviorRelay
import eu.kanade.domain.source.model.SourceData import eu.kanade.domain.source.model.SourceData
import eu.kanade.domain.source.service.SourcePreferences import eu.kanade.domain.source.service.SourcePreferences
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
@ -15,7 +14,6 @@ import eu.kanade.tachiyomi.extension.model.LoadResult
import eu.kanade.tachiyomi.extension.util.ExtensionInstallReceiver import eu.kanade.tachiyomi.extension.util.ExtensionInstallReceiver
import eu.kanade.tachiyomi.extension.util.ExtensionInstaller 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.util.lang.launchNow import eu.kanade.tachiyomi.util.lang.launchNow
import eu.kanade.tachiyomi.util.lang.withUIContext import eu.kanade.tachiyomi.util.lang.withUIContext
import eu.kanade.tachiyomi.util.preference.plusAssign import eu.kanade.tachiyomi.util.preference.plusAssign
@ -26,10 +24,14 @@ import exh.source.BlacklistedSources
import exh.source.EH_SOURCE_ID import exh.source.EH_SOURCE_ID
import exh.source.EXH_SOURCE_ID import exh.source.EXH_SOURCE_ID
import exh.source.MERGED_SOURCE_ID import exh.source.MERGED_SOURCE_ID
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.async import kotlinx.coroutines.async
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
import logcat.LogPriority import logcat.LogPriority
import rx.Observable import rx.Observable
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
@ -61,37 +63,15 @@ class ExtensionManager(
*/ */
private val installer by lazy { ExtensionInstaller(context) } private val installer by lazy { ExtensionInstaller(context) }
/**
* Relay used to notify the installed extensions.
*/
private val installedExtensionsRelay = BehaviorRelay.create<List<Extension.Installed>>()
private val iconMap = mutableMapOf<String, Drawable>() private val iconMap = mutableMapOf<String, Drawable>()
/** private val _installedExtensionsFlow = MutableStateFlow(emptyList<Extension.Installed>())
* List of the currently installed extensions. val installedExtensionsFlow = _installedExtensionsFlow.asStateFlow()
*/
var installedExtensions = emptyList<Extension.Installed>()
private set(value) {
field = value
installedExtensionsFlow.value = field
installedExtensionsRelay.call(value)
}
private val installedExtensionsFlow = MutableStateFlow(installedExtensions)
private var subLanguagesEnabledOnFirstRun = preferences.enabledLanguages().isSet() private var subLanguagesEnabledOnFirstRun = preferences.enabledLanguages().isSet()
fun getInstalledExtensionsFlow(): StateFlow<List<Extension.Installed>> {
return installedExtensionsFlow.asStateFlow()
}
fun getAppIconForSource(source: Source): Drawable? {
return getAppIconForSource(source.id)
}
fun getAppIconForSource(sourceId: Long): Drawable? { fun getAppIconForSource(sourceId: Long): Drawable? {
val pkgName = installedExtensions.find { ext -> ext.sources.any { it.id == sourceId } }?.pkgName val pkgName = _installedExtensionsFlow.value.find { ext -> ext.sources.any { it.id == sourceId } }?.pkgName
if (pkgName != null) { if (pkgName != null) {
return iconMap[pkgName] ?: iconMap.getOrPut(pkgName) { context.packageManager.getApplicationIcon(pkgName) } return iconMap[pkgName] ?: iconMap.getOrPut(pkgName) { context.packageManager.getApplicationIcon(pkgName) }
} }
@ -106,22 +86,14 @@ class ExtensionManager(
// SY <-- // SY <--
} }
/** private val _availableExtensionsFlow = MutableStateFlow(emptyList<Extension.Available>())
* List of the currently available extensions.
*/
var availableExtensions = emptyList<Extension.Available>()
private set(value) {
field = value
availableExtensionsFlow.value = field
updatedInstalledExtensionsStatuses(value)
setupAvailableExtensionsSourcesDataMap(value)
}
private val availableExtensionsFlow = MutableStateFlow(availableExtensions) // SY -->
@OptIn(DelicateCoroutinesApi::class)
fun getAvailableExtensionsFlow(): StateFlow<List<Extension.Available>> { val availableExtensionsFlow = _availableExtensionsFlow
return availableExtensionsFlow.asStateFlow() .map { it.filterNotBlacklisted() }
} .stateIn(GlobalScope, SharingStarted.Eagerly, emptyList())
// SY <--
private var availableExtensionsSourcesData: Map<Long, SourceData> = mapOf() private var availableExtensionsSourcesData: Map<Long, SourceData> = mapOf()
@ -134,24 +106,8 @@ class ExtensionManager(
fun getSourceData(id: Long) = availableExtensionsSourcesData[id] fun getSourceData(id: Long) = availableExtensionsSourcesData[id]
// SY --> private val _untrustedExtensionsFlow = MutableStateFlow(emptyList<Extension.Untrusted>())
var unalteredAvailableExtensions = emptyList<Extension.Available>() val untrustedExtensionsFlow = _untrustedExtensionsFlow.asStateFlow()
// SY <--
/**
* List of the currently untrusted extensions.
*/
var untrustedExtensions = emptyList<Extension.Untrusted>()
private set(value) {
field = value
untrustedExtensionsFlow.value = field
}
private val untrustedExtensionsFlow = MutableStateFlow(untrustedExtensions)
fun getUntrustedExtensionsFlow(): StateFlow<List<Extension.Untrusted>> {
return untrustedExtensionsFlow.asStateFlow()
}
init { init {
initExtensions() initExtensions()
@ -164,11 +120,11 @@ class ExtensionManager(
private fun initExtensions() { private fun initExtensions() {
val extensions = ExtensionLoader.loadExtensions(context) val extensions = ExtensionLoader.loadExtensions(context)
installedExtensions = extensions _installedExtensionsFlow.value = extensions
.filterIsInstance<LoadResult.Success>() .filterIsInstance<LoadResult.Success>()
.map { it.extension } .map { it.extension }
untrustedExtensions = extensions _untrustedExtensionsFlow.value = extensions
.filterIsInstance<LoadResult.Untrusted>() .filterIsInstance<LoadResult.Untrusted>()
.map { it.extension } .map { it.extension }
// SY --> // SY -->
@ -206,10 +162,9 @@ class ExtensionManager(
enableAdditionalSubLanguages(extensions) enableAdditionalSubLanguages(extensions)
// SY --> _availableExtensionsFlow.value = extensions
unalteredAvailableExtensions = extensions updatedInstalledExtensionsStatuses(extensions)
availableExtensions = extensions.filterNotBlacklisted() setupAvailableExtensionsSourcesDataMap(extensions)
// SY <--
} }
/** /**
@ -253,13 +208,13 @@ class ExtensionManager(
return return
} }
val mutInstalledExtensions = installedExtensions.toMutableList() val mutInstalledExtensions = _installedExtensionsFlow.value.toMutableList()
var changed = false var changed = false
for ((index, installedExt) in mutInstalledExtensions.withIndex()) { for ((index, installedExt) in mutInstalledExtensions.withIndex()) {
val pkgName = installedExt.pkgName val pkgName = installedExt.pkgName
// SY --> // SY -->
val availableExt = unalteredAvailableExtensions.find { it.pkgName == pkgName } val availableExt = _availableExtensionsFlow.value.find { it.pkgName == pkgName }
// SY <-- // SY <--
if (!installedExt.isUnofficial && availableExt == null && !installedExt.isObsolete) { if (!installedExt.isUnofficial && availableExt == null && !installedExt.isObsolete) {
@ -286,7 +241,7 @@ class ExtensionManager(
} }
} }
if (changed) { if (changed) {
installedExtensions = mutInstalledExtensions _installedExtensionsFlow.value = mutInstalledExtensions
} }
updatePendingUpdatesCount() updatePendingUpdatesCount()
} }
@ -310,7 +265,7 @@ class ExtensionManager(
* @param extension The extension to be updated. * @param extension The extension to be updated.
*/ */
fun updateExtension(extension: Extension.Installed): Observable<InstallStep> { fun updateExtension(extension: Extension.Installed): Observable<InstallStep> {
val availableExt = availableExtensions.find { it.pkgName == extension.pkgName } val availableExt = _availableExtensionsFlow.value.find { it.pkgName == extension.pkgName }
?: return Observable.empty() ?: return Observable.empty()
return installExtension(availableExt) return installExtension(availableExt)
} }
@ -348,14 +303,14 @@ class ExtensionManager(
* @param signature The signature to whitelist. * @param signature The signature to whitelist.
*/ */
fun trustSignature(signature: String) { fun trustSignature(signature: String) {
val untrustedSignatures = untrustedExtensions.map { it.signatureHash }.toSet() val untrustedSignatures = _untrustedExtensionsFlow.value.map { it.signatureHash }.toSet()
if (signature !in untrustedSignatures) return if (signature !in untrustedSignatures) return
ExtensionLoader.trustedSignatures += signature ExtensionLoader.trustedSignatures += signature
preferences.trustedSignatures() += signature preferences.trustedSignatures() += signature
val nowTrustedExtensions = untrustedExtensions.filter { it.signatureHash == signature } val nowTrustedExtensions = _untrustedExtensionsFlow.value.filter { it.signatureHash == signature }
untrustedExtensions -= nowTrustedExtensions _untrustedExtensionsFlow.value -= nowTrustedExtensions
val ctx = context val ctx = context
launchNow { launchNow {
@ -385,7 +340,7 @@ class ExtensionManager(
} }
// SY <-- // SY <--
installedExtensions += extension _installedExtensionsFlow.value += extension
} }
/** /**
@ -402,13 +357,13 @@ class ExtensionManager(
} }
// SY <-- // SY <--
val mutInstalledExtensions = installedExtensions.toMutableList() val mutInstalledExtensions = _installedExtensionsFlow.value.toMutableList()
val oldExtension = mutInstalledExtensions.find { it.pkgName == extension.pkgName } val oldExtension = mutInstalledExtensions.find { it.pkgName == extension.pkgName }
if (oldExtension != null) { if (oldExtension != null) {
mutInstalledExtensions -= oldExtension mutInstalledExtensions -= oldExtension
} }
mutInstalledExtensions += extension mutInstalledExtensions += extension
installedExtensions = mutInstalledExtensions _installedExtensionsFlow.value = mutInstalledExtensions
} }
/** /**
@ -418,13 +373,13 @@ class ExtensionManager(
* @param pkgName The package name of the uninstalled application. * @param pkgName The package name of the uninstalled application.
*/ */
private fun unregisterExtension(pkgName: String) { private fun unregisterExtension(pkgName: String) {
val installedExtension = installedExtensions.find { it.pkgName == pkgName } val installedExtension = _installedExtensionsFlow.value.find { it.pkgName == pkgName }
if (installedExtension != null) { if (installedExtension != null) {
installedExtensions -= installedExtension _installedExtensionsFlow.value -= installedExtension
} }
val untrustedExtension = untrustedExtensions.find { it.pkgName == pkgName } val untrustedExtension = _untrustedExtensionsFlow.value.find { it.pkgName == pkgName }
if (untrustedExtension != null) { if (untrustedExtension != null) {
untrustedExtensions -= untrustedExtension _untrustedExtensionsFlow.value -= untrustedExtension
} }
} }
@ -444,7 +399,7 @@ class ExtensionManager(
} }
override fun onExtensionUntrusted(extension: Extension.Untrusted) { override fun onExtensionUntrusted(extension: Extension.Untrusted) {
untrustedExtensions += extension _untrustedExtensionsFlow.value += extension
} }
override fun onPackageUninstalled(pkgName: String) { override fun onPackageUninstalled(pkgName: String) {
@ -457,14 +412,14 @@ class ExtensionManager(
* Extension method to set the update field of an installed extension. * Extension method to set the update field of an installed extension.
*/ */
private fun Extension.Installed.withUpdateCheck(): Extension.Installed { private fun Extension.Installed.withUpdateCheck(): Extension.Installed {
val availableExt = availableExtensions.find { it.pkgName == pkgName } val availableExt = _availableExtensionsFlow.value.find { it.pkgName == pkgName }
if ((isUnofficial.not() || availableExt?.isRepoSource == true) && availableExt != null && availableExt.versionCode > versionCode) { if ((!isUnofficial || availableExt?.isRepoSource == true) && availableExt != null && availableExt.versionCode > versionCode) {
return copy(hasUpdate = true) return copy(hasUpdate = true)
} }
return this return this
} }
private fun updatePendingUpdatesCount() { private fun updatePendingUpdatesCount() {
preferences.extensionUpdatesCount().set(installedExtensions.count { it.hasUpdate }) preferences.extensionUpdatesCount().set(_installedExtensionsFlow.value.count { it.hasUpdate })
} }
} }

View File

@ -96,7 +96,7 @@ internal class ExtensionGithubApi {
} }
val extensions = if (fromAvailableExtensionList) { val extensions = if (fromAvailableExtensionList) {
extensionManager.availableExtensions extensionManager.availableExtensionsFlow.value
} else { } else {
findExtensions().also { lastExtCheck.set(Date().time) } findExtensions().also { lastExtCheck.set(Date().time) }
} }

View File

@ -7,7 +7,7 @@ import eu.kanade.tachiyomi.extension.ExtensionManager
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
fun Source.icon(): Drawable? = Injekt.get<ExtensionManager>().getAppIconForSource(this) fun Source.icon(): Drawable? = Injekt.get<ExtensionManager>().getAppIconForSource(this.id)
fun Source.getPreferenceKey(): String = "source_$id" fun Source.getPreferenceKey(): String = "source_$id"

View File

@ -73,7 +73,7 @@ class SourceManager(
init { init {
scope.launch { scope.launch {
extensionManager.getInstalledExtensionsFlow() extensionManager.installedExtensionsFlow
// SY --> // SY -->
.combine(preferences.enableExhentai().changes()) { extensions, enableExhentai -> .combine(preferences.enableExhentai().changes()) { extensions, enableExhentai ->
extensions to enableExhentai extensions to enableExhentai

View File

@ -36,7 +36,7 @@ class ExtensionDetailsPresenter(
super.onCreate(savedState) super.onCreate(savedState)
presenterScope.launchIO { presenterScope.launchIO {
extensionManager.getInstalledExtensionsFlow() extensionManager.installedExtensionsFlow
.map { it.firstOrNull { pkg -> pkg.pkgName == pkgName } } .map { it.firstOrNull { pkg -> pkg.pkgName == pkgName } }
.collectLatest { extension -> .collectLatest { extension ->
// If extension is null it's most likely uninstalled // If extension is null it's most likely uninstalled

View File

@ -117,7 +117,7 @@ open class GlobalSearchPresenter(
if (!filter.isNullOrEmpty()) { if (!filter.isNullOrEmpty()) {
// SY --> // SY -->
val filteredSourceIds = extensionManager.installedExtensions val filteredSourceIds = extensionManager.installedExtensionsFlow.value
.filter { it.pkgName == filter } .filter { it.pkgName == filter }
.flatMap { it.sources } .flatMap { it.sources }
.map { it.id } .map { it.id }