mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-10-31 14:27:57 +01:00 
			
		
		
		
	Bugfixes and extension installation improvements
This commit is contained in:
		| @@ -201,6 +201,16 @@ class ExtensionManager( | ||||
|         return installExtension(availableExt) | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Sets the result of the installation of an extension. | ||||
|      * | ||||
|      * @param downloadId The id of the download. | ||||
|      * @param result Whether the extension was installed or not. | ||||
|      */ | ||||
|     fun setInstallationResult(downloadId: Long, result: Boolean) { | ||||
|         installer.setInstallationResult(downloadId, result) | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Uninstalls the extension that matches the given package name. | ||||
|      * | ||||
| @@ -295,17 +305,14 @@ class ExtensionManager( | ||||
|  | ||||
|         override fun onExtensionInstalled(extension: Extension.Installed) { | ||||
|             registerNewExtension(extension.withUpdateCheck()) | ||||
|             installer.onApkInstalled(extension.pkgName) | ||||
|         } | ||||
|  | ||||
|         override fun onExtensionUpdated(extension: Extension.Installed) { | ||||
|             registerUpdatedExtension(extension.withUpdateCheck()) | ||||
|             installer.onApkInstalled(extension.pkgName) | ||||
|         } | ||||
|  | ||||
|         override fun onExtensionUntrusted(extension: Extension.Untrusted) { | ||||
|             untrustedExtensions += extension | ||||
|             installer.onApkInstalled(extension.pkgName) | ||||
|         } | ||||
|  | ||||
|         override fun onPackageUninstalled(pkgName: String) { | ||||
|   | ||||
| @@ -0,0 +1,45 @@ | ||||
| package eu.kanade.tachiyomi.extension.util | ||||
|  | ||||
| import android.app.Activity | ||||
| import android.content.Intent | ||||
| import android.os.Bundle | ||||
| import eu.kanade.tachiyomi.extension.ExtensionManager | ||||
| import uy.kohesive.injekt.Injekt | ||||
| import uy.kohesive.injekt.api.get | ||||
|  | ||||
| /** | ||||
|  * Activity used to install extensions, because we can only receive the result of the installation | ||||
|  * with [startActivityForResult], which we need to update the UI. | ||||
|  */ | ||||
| class ExtensionInstallActivity : Activity() { | ||||
|  | ||||
|     override fun onCreate(savedInstanceState: Bundle?) { | ||||
|         super.onCreate(savedInstanceState) | ||||
|  | ||||
|         val installIntent = Intent(Intent.ACTION_INSTALL_PACKAGE) | ||||
|                 .setDataAndType(intent.data, intent.type) | ||||
|                 .putExtra(Intent.EXTRA_RETURN_RESULT, true) | ||||
|                 .setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) | ||||
|  | ||||
|         startActivityForResult(installIntent, INSTALL_REQUEST_CODE) | ||||
|     } | ||||
|  | ||||
|     override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { | ||||
|         if (requestCode == INSTALL_REQUEST_CODE) { | ||||
|             checkInstallationResult(resultCode) | ||||
|         } | ||||
|         finish() | ||||
|     } | ||||
|  | ||||
|     private fun checkInstallationResult(resultCode: Int) { | ||||
|         val downloadId = intent.extras.getLong(ExtensionInstaller.EXTRA_DOWNLOAD_ID) | ||||
|         val success = resultCode == RESULT_OK | ||||
|  | ||||
|         val extensionManager = Injekt.get<ExtensionManager>() | ||||
|         extensionManager.setInstallationResult(downloadId, success) | ||||
|     } | ||||
|  | ||||
|     private companion object { | ||||
|         const val INSTALL_REQUEST_CODE = 500 | ||||
|     } | ||||
| } | ||||
| @@ -77,8 +77,6 @@ internal class ExtensionInstaller(private val context: Context) { | ||||
|                 .mergeWith(pollStatus(id)) | ||||
|                 // Force an error if the download takes more than 3 minutes | ||||
|                 .mergeWith(Observable.timer(3, TimeUnit.MINUTES).map { InstallStep.Error }) | ||||
|                 // Force an error if the install process takes more than 10 seconds | ||||
|                 .flatMap { Observable.just(it).mergeWith(timeoutWhenInstalling(it)) } | ||||
|                 // Stop when the application is installed or errors | ||||
|                 .takeUntil { it.isCompleted() } | ||||
|                 // Always notify on main thread | ||||
| @@ -118,27 +116,15 @@ internal class ExtensionInstaller(private val context: Context) { | ||||
|                 } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns an observable that timeouts the installation after a specified time when the apk has | ||||
|      * been downloaded. | ||||
|      * | ||||
|      * @param currentStep The current step of the installation process. | ||||
|      */ | ||||
|     private fun timeoutWhenInstalling(currentStep: InstallStep): Observable<InstallStep> { | ||||
|         return Observable.just(currentStep) | ||||
|                 .filter { it == InstallStep.Installing } | ||||
|                 .delay(10, TimeUnit.SECONDS) | ||||
|                 .map { InstallStep.Error } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Starts an intent to install the extension at the given uri. | ||||
|      * | ||||
|      * @param uri The uri of the extension to install. | ||||
|      */ | ||||
|     fun installApk(uri: Uri) { | ||||
|         val intent = Intent(Intent.ACTION_VIEW) | ||||
|     fun installApk(downloadId: Long, uri: Uri) { | ||||
|         val intent = Intent(context, ExtensionInstallActivity::class.java) | ||||
|                 .setDataAndType(uri, APK_MIME) | ||||
|                 .putExtra(EXTRA_DOWNLOAD_ID, downloadId) | ||||
|                 .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_GRANT_READ_URI_PERMISSION) | ||||
|  | ||||
|         context.startActivity(intent) | ||||
| @@ -158,13 +144,14 @@ internal class ExtensionInstaller(private val context: Context) { | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Called when an extension is installed, allowing to update its installation step. | ||||
|      * Sets the result of the installation of an extension. | ||||
|      * | ||||
|      * @param pkgName The package name of the installed application. | ||||
|      * @param downloadId The id of the download. | ||||
|      * @param result Whether the extension was installed or not. | ||||
|      */ | ||||
|     fun onApkInstalled(pkgName: String) { | ||||
|         val id = activeDownloads[pkgName] ?: return | ||||
|         downloadsRelay.call(id to InstallStep.Installed) | ||||
|     fun setInstallationResult(downloadId: Long, result: Boolean) { | ||||
|         val step = if (result) InstallStep.Installed else InstallStep.Error | ||||
|         downloadsRelay.call(downloadId to step) | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -243,17 +230,18 @@ internal class ExtensionInstaller(private val context: Context) { | ||||
|                         @Suppress("DEPRECATION") | ||||
|                         val uriCompat = File(cursor.getString(cursor.getColumnIndex( | ||||
|                                 DownloadManager.COLUMN_LOCAL_FILENAME))).getUriCompat(context) | ||||
|                         installApk(uriCompat) | ||||
|                         installApk(id, uriCompat) | ||||
|                     } | ||||
|                 } | ||||
|             } else { | ||||
|                 installApk(uri) | ||||
|                 installApk(id, uri) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private companion object { | ||||
|     companion object { | ||||
|         const val APK_MIME = "application/vnd.android.package-archive" | ||||
|         const val EXTRA_DOWNLOAD_ID = "ExtensionInstaller.extra.DOWNLOAD_ID" | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -57,7 +57,7 @@ class ExtensionDetailsController(bundle: Bundle? = null) : | ||||
|     override fun onViewCreated(view: View) { | ||||
|         super.onViewCreated(view) | ||||
|  | ||||
|         val extension = presenter.extension | ||||
|         val extension = presenter.extension ?: return | ||||
|         val context = view.context | ||||
|  | ||||
|         extension_title.text = extension.name | ||||
|   | ||||
| @@ -12,7 +12,7 @@ class ExtensionDetailsPresenter( | ||||
|         private val extensionManager: ExtensionManager = Injekt.get() | ||||
| ) : BasePresenter<ExtensionDetailsController>() { | ||||
|  | ||||
|     val extension = extensionManager.installedExtensions.first { it.pkgName == pkgName } | ||||
|     val extension = extensionManager.installedExtensions.find { it.pkgName == pkgName } | ||||
|  | ||||
|     override fun onCreate(savedState: Bundle?) { | ||||
|         super.onCreate(savedState) | ||||
| @@ -33,6 +33,7 @@ class ExtensionDetailsPresenter( | ||||
|     } | ||||
|  | ||||
|     fun uninstallExtension() { | ||||
|         val extension = extension ?: return | ||||
|         extensionManager.uninstallExtension(extension.pkgName) | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -148,7 +148,10 @@ class MainActivity : BaseActivity() { | ||||
|             SHORTCUT_RECENTLY_UPDATED -> setSelectedDrawerItem(R.id.nav_drawer_recent_updates) | ||||
|             SHORTCUT_RECENTLY_READ -> setSelectedDrawerItem(R.id.nav_drawer_recently_read) | ||||
|             SHORTCUT_CATALOGUES -> setSelectedDrawerItem(R.id.nav_drawer_catalogues) | ||||
|             SHORTCUT_MANGA -> router.setRoot(RouterTransaction.with(MangaController(intent.extras))) | ||||
|             SHORTCUT_MANGA -> { | ||||
|                 val extras = intent.extras ?: return false | ||||
|                 router.setRoot(RouterTransaction.with(MangaController(extras))) | ||||
|             } | ||||
|             SHORTCUT_DOWNLOADS -> { | ||||
|                 if (router.backstack.none { it.controller() is DownloadController }) { | ||||
|                     setSelectedDrawerItem(R.id.nav_drawer_downloads) | ||||
|   | ||||
| @@ -39,7 +39,7 @@ import java.util.* | ||||
| class MangaController : RxController, TabbedController { | ||||
|  | ||||
|     constructor(manga: Manga?, fromCatalogue: Boolean = false) : super(Bundle().apply { | ||||
|         putLong(MANGA_EXTRA, manga?.id!!) | ||||
|         putLong(MANGA_EXTRA, manga?.id ?: 0) | ||||
|         putBoolean(FROM_CATALOGUE_EXTRA, fromCatalogue) | ||||
|     }) { | ||||
|         this.manga = manga | ||||
|   | ||||
		Reference in New Issue
	
	Block a user