Skip to content

Commit

Permalink
feat: prompt to use Ktor downloader on Android DownloadManager failure
Browse files Browse the repository at this point in the history
  • Loading branch information
rushiiMachine committed Aug 5, 2024
1 parent ad7fc35 commit 3662b67
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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()

/**
Expand All @@ -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!")
Expand All @@ -60,6 +72,9 @@ abstract class DownloadStep : Step(), KoinComponent {
}

when (result) {
is IDownloadManager.Result.Cancelled ->
state = StepState.Error

is IDownloadManager.Result.Success -> {
try {
verify()
Expand All @@ -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
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Original file line number Diff line number Diff line change
@@ -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) },
)
}
3 changes: 3 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down

0 comments on commit 3662b67

Please sign in to comment.