Extensions presenter now using less rx

This commit is contained in:
Jay 2020-03-24 02:06:29 -04:00
parent fde6506842
commit 66d62f5aa4
5 changed files with 86 additions and 31 deletions

View File

@ -15,7 +15,9 @@ import eu.kanade.tachiyomi.extension.util.ExtensionLoader
import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.util.system.launchNow import eu.kanade.tachiyomi.util.system.launchNow
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async import kotlinx.coroutines.async
import kotlinx.coroutines.withContext
import rx.Observable import rx.Observable
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
@ -57,12 +59,28 @@ class ExtensionManager(
private set(value) { private set(value) {
field = value field = value
installedExtensionsRelay.call(value) installedExtensionsRelay.call(value)
listener?.extensionsUpdated()
} }
private var listener: ExtensionsChangedListener? = null
fun setListener(listener: ExtensionsChangedListener) {
this.listener = listener
}
fun removeListener(listener: ExtensionsChangedListener) {
if (this.listener == listener)
this.listener = null
}
fun getAppIconForSource(source: Source): Drawable? { fun getAppIconForSource(source: Source): Drawable? {
val pkgName = val pkgName =
installedExtensions.find { ext -> ext.sources.any { it.id == source.id } }?.pkgName installedExtensions.find { ext -> ext.sources.any { it.id == source.id } }?.pkgName
return if (pkgName != null) context.packageManager.getApplicationIcon(pkgName) return if (pkgName != null) try {
context.packageManager.getApplicationIcon(pkgName)
} catch (e: Exception) {
null
}
else null else null
} }
@ -79,6 +97,7 @@ class ExtensionManager(
field = value field = value
availableExtensionsRelay.call(value) availableExtensionsRelay.call(value)
updatedInstalledExtensionsStatuses(value) updatedInstalledExtensionsStatuses(value)
listener?.extensionsUpdated()
} }
/** /**
@ -93,6 +112,7 @@ class ExtensionManager(
private set(value) { private set(value) {
field = value field = value
untrustedExtensionsRelay.call(value) untrustedExtensionsRelay.call(value)
listener?.extensionsUpdated()
} }
/** /**
@ -162,6 +182,19 @@ class ExtensionManager(
} }
} }
/**
* Finds the available extensions in the [api] and updates [availableExtensions].
*/
suspend fun findAvailableExtensionsAsync() {
withContext(Dispatchers.IO) {
availableExtensions = try {
api.findExtensions()
} catch (e: Exception) {
emptyList()
}
}
}
/** /**
* Sets the update field of the installed extensions with the given [availableExtensions]. * Sets the update field of the installed extensions with the given [availableExtensions].
* *
@ -352,3 +385,7 @@ class ExtensionManager(
return this return this
} }
} }
interface ExtensionsChangedListener {
fun extensionsUpdated()
}

View File

@ -1,6 +1,7 @@
package eu.kanade.tachiyomi.ui.catalogue package eu.kanade.tachiyomi.ui.catalogue
import android.Manifest.permission.WRITE_EXTERNAL_STORAGE import android.Manifest.permission.WRITE_EXTERNAL_STORAGE
import android.app.Activity
import android.os.Parcelable import android.os.Parcelable
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.Menu import android.view.Menu
@ -33,13 +34,13 @@ import eu.kanade.tachiyomi.util.view.applyWindowInsetsForRootController
import eu.kanade.tachiyomi.util.view.scrollViewWith import eu.kanade.tachiyomi.util.view.scrollViewWith
import eu.kanade.tachiyomi.util.view.setOnQueryTextChangeListener import eu.kanade.tachiyomi.util.view.setOnQueryTextChangeListener
import eu.kanade.tachiyomi.widget.preference.SourceLoginDialog import eu.kanade.tachiyomi.widget.preference.SourceLoginDialog
import kotlin.math.max
import kotlinx.android.parcel.Parcelize import kotlinx.android.parcel.Parcelize
import kotlinx.android.synthetic.main.catalogue_main_controller.* import kotlinx.android.synthetic.main.catalogue_main_controller.*
import kotlinx.android.synthetic.main.extensions_bottom_sheet.* import kotlinx.android.synthetic.main.extensions_bottom_sheet.*
import kotlinx.android.synthetic.main.main_activity.* import kotlinx.android.synthetic.main.main_activity.*
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import kotlin.math.max
/** /**
* This controller shows and manages the different catalogues enabled by the user. * This controller shows and manages the different catalogues enabled by the user.
@ -180,7 +181,6 @@ class CatalogueController : NucleusController<CataloguePresenter>(),
fun showExtensions() { fun showExtensions() {
ext_bottom_sheet.sheetBehavior?.state = BottomSheetBehavior.STATE_EXPANDED ext_bottom_sheet.sheetBehavior?.state = BottomSheetBehavior.STATE_EXPANDED
ext_bottom_sheet.fetchOnlineExtensionsIfNeeded()
} }
fun toggleExtensions() { fun toggleExtensions() {
@ -188,7 +188,6 @@ class CatalogueController : NucleusController<CataloguePresenter>(),
ext_bottom_sheet.sheetBehavior?.state = BottomSheetBehavior.STATE_COLLAPSED ext_bottom_sheet.sheetBehavior?.state = BottomSheetBehavior.STATE_COLLAPSED
} else { } else {
ext_bottom_sheet.sheetBehavior?.state = BottomSheetBehavior.STATE_EXPANDED ext_bottom_sheet.sheetBehavior?.state = BottomSheetBehavior.STATE_EXPANDED
ext_bottom_sheet.fetchOnlineExtensionsIfNeeded()
} }
} }
@ -209,10 +208,15 @@ class CatalogueController : NucleusController<CataloguePresenter>(),
super.onChangeStarted(handler, type) super.onChangeStarted(handler, type)
if (!type.isPush && handler is SettingsSourcesFadeChangeHandler) { if (!type.isPush && handler is SettingsSourcesFadeChangeHandler) {
ext_bottom_sheet.updateExtTitle() ext_bottom_sheet.updateExtTitle()
presenter.updateSources() ext_bottom_sheet.presenter.refreshExtensions()
} }
} }
override fun onActivityResumed(activity: Activity) {
super.onActivityResumed(activity)
ext_bottom_sheet.presenter.refreshExtensions()
}
/** /**
* Called when login dialog is closed, refreshes the adapter. * Called when login dialog is closed, refreshes the adapter.
* *

View File

@ -5,17 +5,16 @@ import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.preference.getOrDefault import eu.kanade.tachiyomi.data.preference.getOrDefault
import eu.kanade.tachiyomi.extension.ExtensionManager import eu.kanade.tachiyomi.extension.ExtensionManager
import eu.kanade.tachiyomi.extension.ExtensionsChangedListener
import eu.kanade.tachiyomi.extension.model.Extension import eu.kanade.tachiyomi.extension.model.Extension
import eu.kanade.tachiyomi.extension.model.InstallStep import eu.kanade.tachiyomi.extension.model.InstallStep
import eu.kanade.tachiyomi.util.system.LocaleHelper import eu.kanade.tachiyomi.util.system.LocaleHelper
import java.util.concurrent.TimeUnit
import kotlin.coroutines.CoroutineContext
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import rx.Observable import rx.Observable
import rx.Subscription
import rx.android.schedulers.AndroidSchedulers
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
@ -25,36 +24,51 @@ typealias ExtensionTuple =
/** /**
* Presenter of [ExtensionBottomSheet]. * Presenter of [ExtensionBottomSheet].
*/ */
open class ExtensionBottomPresenter( class ExtensionBottomPresenter(
private val bottomSheet: ExtensionBottomSheet, private val bottomSheet: ExtensionBottomSheet,
private val extensionManager: ExtensionManager = Injekt.get(), private val extensionManager: ExtensionManager = Injekt.get(),
private val preferences: PreferencesHelper = Injekt.get() private val preferences: PreferencesHelper = Injekt.get()
) : CoroutineScope { ) : ExtensionsChangedListener {
private var scope = CoroutineScope(Job() + Dispatchers.Default)
override var coroutineContext: CoroutineContext = Job() + Dispatchers.Default
private var extensions = emptyList<ExtensionItem>() private var extensions = emptyList<ExtensionItem>()
private var currentDownloads = hashMapOf<String, InstallStep>() private var currentDownloads = hashMapOf<String, InstallStep>()
fun onCreate() { fun onCreate() {
// extensionManager.findAvailableExtensions() scope.launch {
bindToExtensionsObservable() extensionManager.findAvailableExtensionsAsync()
extensions = toItems(
Triple(
extensionManager.installedExtensions,
extensionManager.untrustedExtensions,
extensionManager.availableExtensions
)
)
withContext(Dispatchers.Main) { bottomSheet.setExtensions(extensions) }
extensionManager.setListener(this@ExtensionBottomPresenter)
}
} }
private fun bindToExtensionsObservable(): Subscription { fun onDestroy() {
val installedObservable = extensionManager.getInstalledExtensionsObservable() extensionManager.removeListener(this)
val untrustedObservable = extensionManager.getUntrustedExtensionsObservable() }
val availableObservable = extensionManager.getAvailableExtensionsObservable()
.startWith(emptyList<Extension.Available>())
return Observable.combineLatest(installedObservable, untrustedObservable, availableObservable) { installed, untrusted, available -> Triple(installed, untrusted, available) } fun refreshExtensions() {
.debounce(100, TimeUnit.MILLISECONDS) scope.launch {
.map(::toItems) extensions = toItems(
.observeOn(AndroidSchedulers.mainThread()) Triple(
.subscribe { extensionManager.installedExtensions,
bottomSheet.setExtensions(extensions) extensionManager.untrustedExtensions,
} extensionManager.availableExtensions
)
)
withContext(Dispatchers.Main) { bottomSheet.setExtensions(extensions) }
}
}
override fun extensionsUpdated() {
refreshExtensions()
} }
@Synchronized @Synchronized

View File

@ -33,7 +33,7 @@ ExtensionAdapter.OnButtonClickListener,
var sheetBehavior: BottomSheetBehavior<*>? = null var sheetBehavior: BottomSheetBehavior<*>? = null
private lateinit var autoCheckItem: AutoCheckItem private lateinit var autoCheckItem: AutoCheckItem
var shouldCallApi = true var shouldCallApi = false
/** /**
* Adapter containing the list of manga from the catalogue. * Adapter containing the list of manga from the catalogue.
@ -54,6 +54,7 @@ ExtensionAdapter.OnButtonClickListener,
// Create recycler and set adapter. // Create recycler and set adapter.
ext_recycler.layoutManager = androidx.recyclerview.widget.LinearLayoutManager(context) ext_recycler.layoutManager = androidx.recyclerview.widget.LinearLayoutManager(context)
ext_recycler.adapter = adapter ext_recycler.adapter = adapter
ext_recycler.setHasFixedSize(true)
ext_recycler.addItemDecoration(ExtensionDividerItemDecoration(context)) ext_recycler.addItemDecoration(ExtensionDividerItemDecoration(context))
ext_recycler.setOnApplyWindowInsetsListener(RecyclerWindowInsetsListener) ext_recycler.setOnApplyWindowInsetsListener(RecyclerWindowInsetsListener)
this.controller = controller this.controller = controller
@ -146,7 +147,6 @@ ExtensionAdapter.OnButtonClickListener,
} }
fun setExtensions(extensions: List<ExtensionItem>) { fun setExtensions(extensions: List<ExtensionItem>) {
// ext_swipe_refresh?.isRefreshing = false
this.extensions = extensions this.extensions = extensions
controller.presenter.updateSources() controller.presenter.updateSources()
drawExtensions() drawExtensions()

View File

@ -34,11 +34,11 @@ import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.util.system.dpToPx import eu.kanade.tachiyomi.util.system.dpToPx
import eu.kanade.tachiyomi.util.system.getResourceColor import eu.kanade.tachiyomi.util.system.getResourceColor
import kotlin.math.abs
import kotlin.math.min
import kotlinx.android.synthetic.main.main_activity.* import kotlinx.android.synthetic.main.main_activity.*
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import kotlin.math.abs
import kotlin.math.min
/** /**
* Returns coordinates of view. * Returns coordinates of view.