mirror of
https://github.com/mihonapp/mihon.git
synced 2025-11-16 14:07:28 +01:00
Implement new extension install methods (#5904)
* Implement new extension install methods * Fixes * Resolve feedback * Keep pending status when waiting to install * Cancellable installation * Remove auto error now that we have cancellable job
This commit is contained in:
@@ -22,5 +22,6 @@ class ExtensionAdapter(controller: ExtensionController) :
|
||||
|
||||
interface OnButtonClickListener {
|
||||
fun onButtonClick(position: Int)
|
||||
fun onCancelButtonClick(position: Int)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,6 +119,11 @@ open class ExtensionController :
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCancelButtonClick(position: Int) {
|
||||
val extension = (adapter?.getItem(position) as? ExtensionItem)?.extension ?: return
|
||||
presenter.cancelInstallUpdateExtension(extension)
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
||||
inflater.inflate(R.menu.browse_extensions, menu)
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package eu.kanade.tachiyomi.ui.browse.extension
|
||||
|
||||
import android.view.View
|
||||
import androidx.core.view.isVisible
|
||||
import coil.clear
|
||||
import coil.load
|
||||
import eu.davidea.viewholders.FlexibleViewHolder
|
||||
@@ -9,7 +10,6 @@ import eu.kanade.tachiyomi.databinding.ExtensionCardItemBinding
|
||||
import eu.kanade.tachiyomi.extension.model.Extension
|
||||
import eu.kanade.tachiyomi.extension.model.InstallStep
|
||||
import eu.kanade.tachiyomi.util.system.LocaleHelper
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
class ExtensionHolder(view: View, val adapter: ExtensionAdapter) :
|
||||
FlexibleViewHolder(view, adapter) {
|
||||
@@ -20,6 +20,9 @@ class ExtensionHolder(view: View, val adapter: ExtensionAdapter) :
|
||||
binding.extButton.setOnClickListener {
|
||||
adapter.buttonClickListener.onButtonClick(bindingAdapterPosition)
|
||||
}
|
||||
binding.cancelButton.setOnClickListener {
|
||||
adapter.buttonClickListener.onCancelButtonClick(bindingAdapterPosition)
|
||||
}
|
||||
}
|
||||
|
||||
fun bind(item: ExtensionItem) {
|
||||
@@ -42,44 +45,40 @@ class ExtensionHolder(view: View, val adapter: ExtensionAdapter) :
|
||||
} else {
|
||||
extension.getApplicationIcon(itemView.context)?.let { binding.image.setImageDrawable(it) }
|
||||
}
|
||||
bindButton(item)
|
||||
bindButtons(item)
|
||||
}
|
||||
|
||||
@Suppress("ResourceType")
|
||||
fun bindButton(item: ExtensionItem) = with(binding.extButton) {
|
||||
isEnabled = true
|
||||
isClickable = true
|
||||
|
||||
fun bindButtons(item: ExtensionItem) = with(binding.extButton) {
|
||||
val extension = item.extension
|
||||
|
||||
val installStep = item.installStep
|
||||
if (installStep != null) {
|
||||
setText(
|
||||
when (installStep) {
|
||||
InstallStep.Pending -> R.string.ext_pending
|
||||
InstallStep.Downloading -> R.string.ext_downloading
|
||||
InstallStep.Installing -> R.string.ext_installing
|
||||
InstallStep.Installed -> R.string.ext_installed
|
||||
InstallStep.Error -> R.string.action_retry
|
||||
}
|
||||
)
|
||||
if (installStep != InstallStep.Error) {
|
||||
isEnabled = false
|
||||
isClickable = false
|
||||
}
|
||||
} else if (extension is Extension.Installed) {
|
||||
when {
|
||||
extension.hasUpdate -> {
|
||||
setText(R.string.ext_update)
|
||||
}
|
||||
else -> {
|
||||
setText(R.string.action_settings)
|
||||
setText(
|
||||
when (installStep) {
|
||||
InstallStep.Pending -> R.string.ext_pending
|
||||
InstallStep.Downloading -> R.string.ext_downloading
|
||||
InstallStep.Installing -> R.string.ext_installing
|
||||
InstallStep.Installed -> R.string.ext_installed
|
||||
InstallStep.Error -> R.string.action_retry
|
||||
InstallStep.Idle -> {
|
||||
when (extension) {
|
||||
is Extension.Installed -> {
|
||||
if (extension.hasUpdate) {
|
||||
R.string.ext_update
|
||||
} else {
|
||||
R.string.action_settings
|
||||
}
|
||||
}
|
||||
is Extension.Untrusted -> R.string.ext_trust
|
||||
is Extension.Available -> R.string.ext_install
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (extension is Extension.Untrusted) {
|
||||
setText(R.string.ext_trust)
|
||||
} else {
|
||||
setText(R.string.ext_install)
|
||||
}
|
||||
)
|
||||
|
||||
val isIdle = installStep == InstallStep.Idle || installStep == InstallStep.Error
|
||||
binding.cancelButton.isVisible = !isIdle
|
||||
isEnabled = isIdle
|
||||
isClickable = isIdle
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ import eu.kanade.tachiyomi.source.CatalogueSource
|
||||
data class ExtensionItem(
|
||||
val extension: Extension,
|
||||
val header: ExtensionGroupItem? = null,
|
||||
val installStep: InstallStep? = null
|
||||
val installStep: InstallStep = InstallStep.Idle
|
||||
) :
|
||||
AbstractSectionableItem<ExtensionHolder, ExtensionGroupItem>(header) {
|
||||
|
||||
@@ -49,7 +49,7 @@ data class ExtensionItem(
|
||||
if (payloads == null || payloads.isEmpty()) {
|
||||
holder.bind(this)
|
||||
} else {
|
||||
holder.bindButton(this)
|
||||
holder.bindButtons(this)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -77,14 +77,14 @@ open class ExtensionPresenter(
|
||||
if (updatesSorted.isNotEmpty()) {
|
||||
val header = ExtensionGroupItem(context.getString(R.string.ext_updates_pending), updatesSorted.size, true)
|
||||
items += updatesSorted.map { extension ->
|
||||
ExtensionItem(extension, header, currentDownloads[extension.pkgName])
|
||||
ExtensionItem(extension, header, currentDownloads[extension.pkgName] ?: InstallStep.Idle)
|
||||
}
|
||||
}
|
||||
if (installedSorted.isNotEmpty() || untrustedSorted.isNotEmpty()) {
|
||||
val header = ExtensionGroupItem(context.getString(R.string.ext_installed), installedSorted.size + untrustedSorted.size)
|
||||
|
||||
items += installedSorted.map { extension ->
|
||||
ExtensionItem(extension, header, currentDownloads[extension.pkgName])
|
||||
ExtensionItem(extension, header, currentDownloads[extension.pkgName] ?: InstallStep.Idle)
|
||||
}
|
||||
|
||||
items += untrustedSorted.map { extension ->
|
||||
@@ -100,7 +100,7 @@ open class ExtensionPresenter(
|
||||
.forEach {
|
||||
val header = ExtensionGroupItem(it.key, it.value.size)
|
||||
items += it.value.map { extension ->
|
||||
ExtensionItem(extension, header, currentDownloads[extension.pkgName])
|
||||
ExtensionItem(extension, header, currentDownloads[extension.pkgName] ?: InstallStep.Idle)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -133,6 +133,10 @@ open class ExtensionPresenter(
|
||||
extensionManager.updateExtension(extension).subscribeToInstallUpdate(extension)
|
||||
}
|
||||
|
||||
fun cancelInstallUpdateExtension(extension: Extension) {
|
||||
extensionManager.cancelInstallUpdateExtension(extension)
|
||||
}
|
||||
|
||||
private fun Observable<InstallStep>.subscribeToInstallUpdate(extension: Extension) {
|
||||
this.doOnNext { currentDownloads[extension.pkgName] = it }
|
||||
.doOnUnsubscribe { currentDownloads.remove(extension.pkgName) }
|
||||
|
||||
@@ -36,6 +36,8 @@ import eu.kanade.tachiyomi.util.preference.preferenceCategory
|
||||
import eu.kanade.tachiyomi.util.preference.summaryRes
|
||||
import eu.kanade.tachiyomi.util.preference.switchPreference
|
||||
import eu.kanade.tachiyomi.util.preference.titleRes
|
||||
import eu.kanade.tachiyomi.util.system.MiuiUtil
|
||||
import eu.kanade.tachiyomi.util.system.isPackageInstalled
|
||||
import eu.kanade.tachiyomi.util.system.isTablet
|
||||
import eu.kanade.tachiyomi.util.system.powerManager
|
||||
import eu.kanade.tachiyomi.util.system.toast
|
||||
@@ -187,6 +189,45 @@ class SettingsAdvancedController : SettingsController() {
|
||||
}
|
||||
}
|
||||
|
||||
preferenceCategory {
|
||||
titleRes = R.string.label_extensions
|
||||
|
||||
listPreference {
|
||||
key = Keys.extensionInstaller
|
||||
titleRes = R.string.ext_installer_pref
|
||||
summary = "%s"
|
||||
entriesRes = arrayOf(
|
||||
R.string.ext_installer_legacy,
|
||||
R.string.ext_installer_packageinstaller,
|
||||
R.string.ext_installer_shizuku
|
||||
)
|
||||
entryValues = PreferenceValues.ExtensionInstaller.values().map { it.name }.toTypedArray()
|
||||
defaultValue = if (MiuiUtil.isMiui()) {
|
||||
PreferenceValues.ExtensionInstaller.LEGACY
|
||||
} else {
|
||||
PreferenceValues.ExtensionInstaller.PACKAGEINSTALLER
|
||||
}.name
|
||||
|
||||
onChange {
|
||||
if (it == PreferenceValues.ExtensionInstaller.SHIZUKU.name &&
|
||||
!context.isPackageInstalled("moe.shizuku.privileged.api")
|
||||
) {
|
||||
MaterialAlertDialogBuilder(context)
|
||||
.setTitle(R.string.ext_installer_shizuku)
|
||||
.setMessage(R.string.ext_installer_shizuku_unavailable_dialog)
|
||||
.setPositiveButton(android.R.string.ok) { _, _ ->
|
||||
openInBrowser("https://shizuku.rikka.app/download")
|
||||
}
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.show()
|
||||
false
|
||||
} else {
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
preferenceCategory {
|
||||
titleRes = R.string.pref_category_display
|
||||
|
||||
|
||||
Reference in New Issue
Block a user