Skip to content
Snippets Groups Projects
Commit 4ec68dfa authored by Mugurell's avatar Mugurell Committed by Richard Pospesel
Browse files

Bug 1812518 - Allow a custom View for first party downloads

This will allow clients easily implement their own UI.

Backport of https://github.com/mozilla-mobile/firefox-android/commit/e678610bc10df96b8543c26fb5eb7c1ba26e3e20
parent 52f79946
Branches
Tags
No related merge requests found
......@@ -10,7 +10,7 @@ import mozilla.components.browser.state.state.content.DownloadState
import mozilla.components.feature.downloads.DownloadDialogFragment.Companion.BYTES_TO_MB_LIMIT
import mozilla.components.feature.downloads.DownloadDialogFragment.Companion.KILOBYTE
import mozilla.components.feature.downloads.DownloadDialogFragment.Companion.MEGABYTE
import mozilla.components.support.utils.DownloadUtils
import mozilla.components.feature.downloads.ext.realFilenameOrGuessed
/**
* This is a general representation of a dialog meant to be used in collaboration with [DownloadsFeature]
......@@ -34,11 +34,7 @@ abstract class DownloadDialogFragment : AppCompatDialogFragment() {
*/
fun setDownload(download: DownloadState) {
val args = arguments ?: Bundle()
args.putString(
KEY_FILE_NAME,
download.fileName
?: DownloadUtils.guessFileName(null, download.destinationDirectory, download.url, download.contentType)
)
args.putString(KEY_FILE_NAME, download.realFilenameOrGuessed)
args.putString(KEY_URL, download.url)
args.putLong(KEY_CONTENT_LENGTH, download.contentLength ?: 0)
arguments = args
......
......@@ -25,6 +25,7 @@ import mozilla.components.browser.state.state.SessionState
import mozilla.components.browser.state.state.content.DownloadState
import mozilla.components.browser.state.store.BrowserStore
import mozilla.components.feature.downloads.DownloadDialogFragment.Companion.FRAGMENT_TAG
import mozilla.components.feature.downloads.ext.realFilenameOrGuessed
import mozilla.components.feature.downloads.manager.DownloadManager
import mozilla.components.feature.downloads.manager.noop
import mozilla.components.feature.downloads.manager.onDownloadStopped
......@@ -41,6 +42,31 @@ import mozilla.components.support.ktx.kotlin.isSameOriginAs
import mozilla.components.support.ktx.kotlinx.coroutines.flow.ifChanged
import mozilla.components.support.utils.Browsers
/**
* The name of the file to be downloaded.
*/
@JvmInline
value class Filename(val value: String)
/**
* The size of the file to be downloaded expressed as the number of `bytes`.
* The value will be `0` if the size is unknown.
*/
@JvmInline
value class ContentSize(val value: Long)
/**
* Action for when the positive button of a download dialog was tapped.
*/
@JvmInline
value class PositiveActionCallback(val value: () -> Unit)
/**
* Action for when the negative button of a download dialog was tapped.
*/
@JvmInline
value class NegativeActionCallback(val value: () -> Unit)
/**
* Feature implementation to provide download functionality for the selected
* session. The feature will subscribe to the selected session and listen
......@@ -60,6 +86,7 @@ import mozilla.components.support.utils.Browsers
* @property promptsStyling styling properties for the dialog.
* @property shouldForwardToThirdParties Indicates if downloads should be forward to third party apps,
* if there are multiple apps a chooser dialog will shown.
* @property customDownloadDialog An optional delegate for showing a download dialog.
*/
@Suppress("LongParameterList", "LargeClass")
class DownloadsFeature(
......@@ -73,7 +100,8 @@ class DownloadsFeature(
private val tabId: String? = null,
private val fragmentManager: FragmentManager? = null,
private val promptsStyling: PromptsStyling? = null,
private val shouldForwardToThirdParties: () -> Boolean = { false }
private val shouldForwardToThirdParties: () -> Boolean = { false },
private val customDownloadDialog: ((Filename, ContentSize, PositiveActionCallback, NegativeActionCallback) -> Unit)? = null,
) : LifecycleAwareFeature, PermissionsFeature {
var onDownloadStopped: onDownloadStopped
......@@ -163,13 +191,30 @@ class DownloadsFeature(
false
} else {
if (applicationContext.isPermissionGranted(downloadManager.permissions.asIterable())) {
if (fragmentManager != null && !download.skipConfirmation) {
when {
customDownloadDialog != null && !download.skipConfirmation -> {
customDownloadDialog.invoke(
Filename(download.realFilenameOrGuessed),
ContentSize(download.contentLength ?: 0),
PositiveActionCallback {
startDownload(download)
useCases.consumeDownload.invoke(tab.id, download.id)
},
NegativeActionCallback {
useCases.cancelDownloadRequest.invoke(tab.id, download.id)
},
)
false
}
fragmentManager != null && !download.skipConfirmation -> {
showDownloadDialog(tab, download)
false
} else {
}
else -> {
useCases.consumeDownload(tab.id, download.id)
startDownload(download)
}
}
} else {
onNeedToRequestPermissions(downloadManager.permissions)
false
......
......@@ -47,3 +47,6 @@ internal fun DownloadState.withResponse(headers: Headers, stream: InputStream?):
contentLength = contentLength ?: headers[CONTENT_LENGTH]?.toLongOrNull()
)
}
internal val DownloadState.realFilenameOrGuessed
get() = fileName ?: DownloadUtils.guessFileName(null, destinationDirectory, url, contentType)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment