Reduce stutter when entering Browse screen (#6435)
* More coil * ExtensionController: Drop first text change event * Browse-Source: Remove unnecessary load * ExtensionPresenter: Increase debounce timeout To avoid heavy list reload during first enter animation
This commit is contained in:
parent
b8f7653fb2
commit
78a261f5d3
10 changed files with 28 additions and 21 deletions
|
@ -1,5 +1,6 @@
|
|||
package eu.kanade.tachiyomi.extension.model
|
||||
|
||||
import android.graphics.drawable.Drawable
|
||||
import eu.kanade.tachiyomi.source.Source
|
||||
|
||||
sealed class Extension {
|
||||
|
@ -20,6 +21,7 @@ sealed class Extension {
|
|||
override val isNsfw: Boolean,
|
||||
val pkgFactory: String?,
|
||||
val sources: List<Source>,
|
||||
val icon: Drawable?,
|
||||
val hasUpdate: Boolean = false,
|
||||
val isObsolete: Boolean = false,
|
||||
val isUnofficial: Boolean = false
|
||||
|
|
|
@ -13,6 +13,7 @@ import eu.kanade.tachiyomi.source.CatalogueSource
|
|||
import eu.kanade.tachiyomi.source.Source
|
||||
import eu.kanade.tachiyomi.source.SourceFactory
|
||||
import eu.kanade.tachiyomi.util.lang.Hash
|
||||
import eu.kanade.tachiyomi.util.system.getApplicationIcon
|
||||
import eu.kanade.tachiyomi.util.system.logcat
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.runBlocking
|
||||
|
@ -181,7 +182,8 @@ internal object ExtensionLoader {
|
|||
isNsfw,
|
||||
sources = sources,
|
||||
pkgFactory = appInfo.metaData.getString(METADATA_SOURCE_FACTORY),
|
||||
isUnofficial = signatureHash != officialSignature
|
||||
isUnofficial = signatureHash != officialSignature,
|
||||
icon = context.getApplicationIcon(pkgName)
|
||||
)
|
||||
return LoadResult.Success(extension)
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ import eu.kanade.tachiyomi.ui.base.controller.NucleusController
|
|||
import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
|
||||
import eu.kanade.tachiyomi.ui.browse.BrowseController
|
||||
import eu.kanade.tachiyomi.ui.browse.extension.details.ExtensionDetailsController
|
||||
import kotlinx.coroutines.flow.drop
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
|
@ -143,6 +144,7 @@ open class ExtensionController :
|
|||
}
|
||||
|
||||
searchView.queryTextChanges()
|
||||
.drop(1) // Drop first event after subscribed
|
||||
.filter { router.backstack.lastOrNull()?.controller == this }
|
||||
.onEach {
|
||||
query = it.toString()
|
||||
|
|
|
@ -42,8 +42,8 @@ class ExtensionHolder(view: View, val adapter: ExtensionAdapter) :
|
|||
binding.icon.clear()
|
||||
if (extension is Extension.Available) {
|
||||
binding.icon.load(extension.iconUrl)
|
||||
} else {
|
||||
extension.getApplicationIcon(itemView.context)?.let { binding.icon.setImageDrawable(it) }
|
||||
} else if (extension is Extension.Installed) {
|
||||
binding.icon.load(extension.icon)
|
||||
}
|
||||
bindButtons(item)
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ open class ExtensionPresenter(
|
|||
.startWith(emptyList<Extension.Available>())
|
||||
|
||||
return Observable.combineLatest(installedObservable, untrustedObservable, availableObservable) { installed, untrusted, available -> Triple(installed, untrusted, available) }
|
||||
.debounce(100, TimeUnit.MILLISECONDS)
|
||||
.debounce(500, TimeUnit.MILLISECONDS)
|
||||
.map(::toItems)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribeLatestCache({ view, _ -> view.setExtensions(extensions) })
|
||||
|
|
|
@ -2,6 +2,7 @@ package eu.kanade.tachiyomi.ui.browse.migration.sources
|
|||
|
||||
import android.view.View
|
||||
import androidx.core.view.isVisible
|
||||
import coil.load
|
||||
import eu.davidea.viewholders.FlexibleViewHolder
|
||||
import eu.kanade.tachiyomi.databinding.SourceMainControllerItemBinding
|
||||
import eu.kanade.tachiyomi.source.icon
|
||||
|
@ -20,7 +21,7 @@ class SourceHolder(view: View, val adapter: SourceAdapter) :
|
|||
binding.subtitle.text = LocaleHelper.getDisplayName(source.lang)
|
||||
|
||||
itemView.post {
|
||||
binding.image.setImageDrawable(source.icon())
|
||||
binding.image.load(source.icon())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -92,6 +92,7 @@ class SourceController :
|
|||
|
||||
// Update list on extension changes (e.g. new installation)
|
||||
(parentController as BrowseController).extensionListUpdateRelay
|
||||
.skip(1) // Skip first update when ExtensionController created
|
||||
.subscribeUntilDestroy {
|
||||
presenter.updateSources()
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package eu.kanade.tachiyomi.ui.browse.source
|
|||
|
||||
import android.view.View
|
||||
import androidx.core.view.isVisible
|
||||
import coil.load
|
||||
import eu.davidea.viewholders.FlexibleViewHolder
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.databinding.SourceMainControllerItemBinding
|
||||
|
@ -10,7 +11,7 @@ import eu.kanade.tachiyomi.source.icon
|
|||
import eu.kanade.tachiyomi.util.system.LocaleHelper
|
||||
import eu.kanade.tachiyomi.util.view.setVectorCompat
|
||||
|
||||
class SourceHolder(private val view: View, val adapter: SourceAdapter) :
|
||||
class SourceHolder(view: View, val adapter: SourceAdapter) :
|
||||
FlexibleViewHolder(view, adapter) {
|
||||
|
||||
private val binding = SourceMainControllerItemBinding.bind(view)
|
||||
|
@ -33,12 +34,10 @@ class SourceHolder(private val view: View, val adapter: SourceAdapter) :
|
|||
binding.subtitle.text = LocaleHelper.getDisplayName(source.lang)
|
||||
|
||||
// Set source icon
|
||||
itemView.post {
|
||||
val icon = source.icon()
|
||||
when {
|
||||
icon != null -> binding.image.setImageDrawable(icon)
|
||||
item.source.id == LocalSource.ID -> binding.image.setImageResource(R.mipmap.ic_local_source)
|
||||
}
|
||||
icon != null -> binding.image.load(icon)
|
||||
item.source.id == LocalSource.ID -> binding.image.load(R.mipmap.ic_local_source)
|
||||
}
|
||||
|
||||
binding.sourceLatest.isVisible = source.supportsLatest
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package eu.kanade.tachiyomi.ui.browse.source
|
||||
|
||||
import android.os.Bundle
|
||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||
import eu.kanade.tachiyomi.source.CatalogueSource
|
||||
import eu.kanade.tachiyomi.source.LocalSource
|
||||
|
@ -37,14 +36,6 @@ class SourcePresenter(
|
|||
*/
|
||||
private var sourceSubscription: Subscription? = null
|
||||
|
||||
override fun onCreate(savedState: Bundle?) {
|
||||
super.onCreate(savedState)
|
||||
|
||||
// Load enabled and last used sources
|
||||
loadSources()
|
||||
loadLastUsedSource()
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsubscribe and create a new subscription to fetch enabled sources.
|
||||
*/
|
||||
|
|
|
@ -14,6 +14,7 @@ import android.content.pm.PackageManager
|
|||
import android.content.res.Configuration
|
||||
import android.content.res.Resources
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.net.ConnectivityManager
|
||||
import android.net.NetworkCapabilities
|
||||
import android.net.Uri
|
||||
|
@ -418,3 +419,11 @@ fun Context.isPackageInstalled(packageName: String): Boolean {
|
|||
false
|
||||
}
|
||||
}
|
||||
|
||||
fun Context.getApplicationIcon(pkgName: String): Drawable? {
|
||||
return try {
|
||||
packageManager.getApplicationIcon(pkgName)
|
||||
} catch (e: PackageManager.NameNotFoundException) {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
|
Reference in a new issue