feat: prompt to use Ktor downloader on Android DownloadManager failure
This commit is contained in:
parent
ad7fc35495
commit
3662b67ad6
6 changed files with 89 additions and 7 deletions
|
|
@ -110,7 +110,7 @@ class AndroidDownloadManager(application: Application) : IDownloadManager {
|
|||
* Error returned by the system [DownloadManager].
|
||||
* @param reason The reason code returned by the [DownloadManager.COLUMN_REASON] column.
|
||||
*/
|
||||
data class Error(private val reason: Int) : Result.Error() {
|
||||
data class Error(val reason: Int) : Result.Error() {
|
||||
/**
|
||||
* Convert a [DownloadManager.COLUMN_REASON] code into its name.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -19,9 +19,12 @@ import org.koin.core.component.inject
|
|||
* quickly switching the step groups in the UI. (very disorienting)
|
||||
* Larger delay leads to a perception that it's doing more work than it actually is.
|
||||
*/
|
||||
const val MINIMUM_STEP_DELAY: Long = 600L
|
||||
private const val MINIMUM_STEP_DELAY: Long = 600L
|
||||
|
||||
const val ERROR_NOTIF_ID = 200002
|
||||
/**
|
||||
* ID used for showing error notifications emanating from this step runner.
|
||||
*/
|
||||
private const val ERROR_NOTIF_ID = 200002
|
||||
|
||||
abstract class StepRunner : KoinComponent {
|
||||
private val context: Context by inject()
|
||||
|
|
|
|||
|
|
@ -1,13 +1,22 @@
|
|||
package com.aliucord.manager.patcher.steps.base
|
||||
|
||||
import android.app.DownloadManager
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import android.widget.Toast
|
||||
import androidx.annotation.CallSuper
|
||||
import androidx.compose.runtime.Stable
|
||||
import com.aliucord.manager.BuildConfig
|
||||
import com.aliucord.manager.R
|
||||
import com.aliucord.manager.di.DownloadManagerProvider
|
||||
import com.aliucord.manager.di.DownloaderSetting
|
||||
import com.aliucord.manager.manager.OverlayManager
|
||||
import com.aliucord.manager.manager.PreferencesManager
|
||||
import com.aliucord.manager.manager.download.AndroidDownloadManager
|
||||
import com.aliucord.manager.manager.download.IDownloadManager
|
||||
import com.aliucord.manager.patcher.StepRunner
|
||||
import com.aliucord.manager.patcher.steps.StepGroup
|
||||
import com.aliucord.manager.ui.components.dialogs.AlternativeDownloaderDialog
|
||||
import com.aliucord.manager.util.showToast
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
|
|
@ -18,6 +27,8 @@ import java.io.File
|
|||
@Stable
|
||||
abstract class DownloadStep : Step(), KoinComponent {
|
||||
private val context: Context by inject()
|
||||
private val overlays: OverlayManager by inject()
|
||||
private val prefs: PreferencesManager by inject()
|
||||
private val downloaders: DownloadManagerProvider by inject()
|
||||
|
||||
/**
|
||||
|
|
@ -35,6 +46,7 @@ abstract class DownloadStep : Step(), KoinComponent {
|
|||
* Verify that the download completely successfully without errors.
|
||||
* @throws Throwable If verification fails.
|
||||
*/
|
||||
@CallSuper
|
||||
open suspend fun verify() {
|
||||
if (!targetFile.exists())
|
||||
throw Error("Downloaded file is missing!")
|
||||
|
|
@ -60,6 +72,9 @@ abstract class DownloadStep : Step(), KoinComponent {
|
|||
}
|
||||
|
||||
when (result) {
|
||||
is IDownloadManager.Result.Cancelled ->
|
||||
state = StepState.Error
|
||||
|
||||
is IDownloadManager.Result.Success -> {
|
||||
try {
|
||||
verify()
|
||||
|
|
@ -80,11 +95,31 @@ abstract class DownloadStep : Step(), KoinComponent {
|
|||
Toast.makeText(context, toastText, Toast.LENGTH_LONG).show()
|
||||
}
|
||||
|
||||
// If this is a specific Android DownloadManager error, then prompt to use a different downloader
|
||||
if (result is AndroidDownloadManager.Error
|
||||
&& result.reason in arrayOf(DownloadManager.ERROR_HTTP_DATA_ERROR, DownloadManager.ERROR_CANNOT_RESUME)
|
||||
&& prefs.downloader != DownloaderSetting.Ktor
|
||||
) {
|
||||
state = StepState.Error
|
||||
|
||||
val confirmed = overlays.startComposableForResult { callback ->
|
||||
AlternativeDownloaderDialog(
|
||||
onConfirm = { callback(true) },
|
||||
onDismiss = { callback(false) },
|
||||
)
|
||||
}
|
||||
|
||||
if (confirmed) {
|
||||
Log.i(BuildConfig.TAG, "Changing to alternative downloader after failure")
|
||||
prefs.downloader = DownloaderSetting.Ktor
|
||||
state = StepState.Running
|
||||
|
||||
return execute(container)
|
||||
}
|
||||
}
|
||||
|
||||
throw Error("Failed to download: $result")
|
||||
}
|
||||
|
||||
is IDownloadManager.Result.Cancelled ->
|
||||
state = StepState.Error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ class DownloadDiscordStep : DownloadStep(), KoinComponent {
|
|||
|
||||
private companion object {
|
||||
/**
|
||||
* Last version of Discord before the RN transition.
|
||||
* Last version of Discord before the RNA rewrite
|
||||
*/
|
||||
const val DISCORD_KT_VERSION = 126021
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,41 @@
|
|||
package com.aliucord.manager.ui.components.dialogs
|
||||
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import com.aliucord.manager.R
|
||||
|
||||
@Composable
|
||||
fun AlternativeDownloaderDialog(
|
||||
onConfirm: () -> Unit,
|
||||
onDismiss: () -> Unit,
|
||||
) {
|
||||
AlertDialog(
|
||||
onDismissRequest = onDismiss,
|
||||
confirmButton = {
|
||||
FilledTonalButton(
|
||||
onClick = onConfirm,
|
||||
colors = ButtonDefaults.filledTonalButtonColors(
|
||||
containerColor = MaterialTheme.colorScheme.primary,
|
||||
contentColor = MaterialTheme.colorScheme.onPrimary,
|
||||
),
|
||||
) {
|
||||
Text(stringResource(R.string.action_retry))
|
||||
}
|
||||
},
|
||||
dismissButton = {
|
||||
TextButton(
|
||||
onClick = onDismiss,
|
||||
colors = ButtonDefaults.textButtonColors(
|
||||
contentColor = MaterialTheme.colorScheme.error,
|
||||
),
|
||||
) {
|
||||
Text(stringResource(R.string.action_cancel))
|
||||
}
|
||||
},
|
||||
title = { Text(stringResource(R.string.alt_downloader_dialog_title)) },
|
||||
text = { Text(stringResource(R.string.alt_downloader_dialog_desc)) },
|
||||
icon = { Icon(painterResource(R.drawable.ic_download), contentDescription = null) },
|
||||
)
|
||||
}
|
||||
|
|
@ -164,6 +164,9 @@
|
|||
<string name="play_protect_warning_ok">Continue</string>
|
||||
<string name="play_protect_warning_open_gpp">Open Play Protect</string>
|
||||
|
||||
<string name="alt_downloader_dialog_title">Alternative Downloader</string>
|
||||
<string name="alt_downloader_dialog_desc">This download failed with a specific error that may indicate issues with the system\'s DownloadManager. Would you like to retry with the the alternative downloader implementation?</string>
|
||||
|
||||
<string name="fun_fact_prefix">Fun Fact: %s</string>
|
||||
<string name="fun_fact_1">Did you know that Google Play Protect is useless?</string>
|
||||
<string name="fun_fact_2">Did you know Aliucord with 150+ plugins somehow runs better than Discord\'s new app?</string>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue