Skip to content
This repository has been archived by the owner on Feb 20, 2023. It is now read-only.

Commit

Permalink
Bug 1812518 - Show the 3rd party download dialog as an Android View
Browse files Browse the repository at this point in the history
This uses the same direction as the before patch - inflating a new View that
can then serve as an anchor for the Snackbar.
Here we could use directly the AC layout as it needed no special customization.
  • Loading branch information
Mugurell authored and mergify[bot] committed Jan 26, 2023
1 parent 14a81f1 commit 6428f96
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 0 deletions.
13 changes: 13 additions & 0 deletions app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt
Expand Up @@ -124,6 +124,7 @@ import org.mozilla.fenix.downloads.DownloadService
import org.mozilla.fenix.downloads.DynamicDownloadDialog
import org.mozilla.fenix.downloads.FirstPartyDownloadDialog
import org.mozilla.fenix.downloads.StartDownloadDialog
import org.mozilla.fenix.downloads.ThirdPartyDownloadDialog
import org.mozilla.fenix.ext.accessibilityManager
import org.mozilla.fenix.ext.breadcrumb
import org.mozilla.fenix.ext.components
Expand Down Expand Up @@ -527,6 +528,18 @@ abstract class BaseBrowserFragment :
currentStartDownloadDialog = it
}
},
customThirdPartyDownloadDialog = { downloaderApps, onAppSelected, negativeActionCallback ->
ThirdPartyDownloadDialog(
activity = requireActivity(),
downloaderApps = downloaderApps.value,
onAppSelected = onAppSelected.value,
negativeButtonAction = negativeActionCallback.value,
).onDismiss {
currentStartDownloadDialog = null
}.show(binding.startDownloadDialogContainer).also {
currentStartDownloadDialog = it
}
},
)

downloadFeature.onDownloadStopped = { downloadState, _, downloadJobStatus ->
Expand Down
Expand Up @@ -20,7 +20,10 @@ import androidx.core.content.ContextCompat
import androidx.core.view.ViewCompat
import androidx.core.view.children
import androidx.viewbinding.ViewBinding
import mozilla.components.feature.downloads.databinding.MozacDownloaderChooserPromptBinding
import mozilla.components.feature.downloads.toMegabyteOrKilobyteString
import mozilla.components.feature.downloads.ui.DownloaderApp
import mozilla.components.feature.downloads.ui.DownloaderAppAdapter
import mozilla.components.support.ktx.android.view.setNavigationBarTheme
import mozilla.components.support.ktx.android.view.setStatusBarTheme
import org.mozilla.fenix.R
Expand Down Expand Up @@ -210,3 +213,36 @@ class FirstPartyDownloadDialog(
}
}
}

/**
* A download view mimicking a modal dialog that presents the user with a list of all apps
* that can handle the download request.
*
* @param activity The [Activity] in which the dialog will be shown.
* Used to update the activity [Window] to best mimic a modal dialog.
* @param downloaderApps List of all applications that can handle the download request.
* @param onAppSelected Callback for when the user chooses a specific application to handle the download request.
* @param negativeButtonAction Callback for when the user interacts with the dialog to dismiss it.
*/
class ThirdPartyDownloadDialog(
private val activity: Activity,
private val downloaderApps: List<DownloaderApp>,
private val onAppSelected: (DownloaderApp) -> Unit,
private val negativeButtonAction: () -> Unit,
) : StartDownloadDialog(activity) {
override fun setupView() {
val dialog = MozacDownloaderChooserPromptBinding.inflate(LayoutInflater.from(activity), container, true)
.also { binding = it }

val recyclerView = dialog.appsList
recyclerView.adapter = DownloaderAppAdapter(activity, downloaderApps) { app ->
onAppSelected(app)
dismiss()
}

dialog.closeButton.setOnClickListener {
negativeButtonAction()
dismiss()
}
}
}
@@ -0,0 +1,54 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

package org.mozilla.fenix.downloads

import android.app.Activity
import android.widget.FrameLayout
import io.mockk.Runs
import io.mockk.every
import io.mockk.just
import io.mockk.mockk
import io.mockk.spyk
import io.mockk.verify
import mozilla.components.feature.downloads.databinding.MozacDownloaderChooserPromptBinding
import mozilla.components.support.test.robolectric.testContext
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Test
import org.junit.runner.RunWith
import org.mozilla.fenix.R
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
import org.robolectric.Robolectric

@RunWith(FenixRobolectricTestRunner::class)
class ThirdPartyDownloadDialogTest {
private val activity: Activity = Robolectric.buildActivity(Activity::class.java).create().get()

@Test
fun `GIVEN a list of downloader apps WHEN setting it's View THEN bind all provided download data`() {
var wasNegativeActionDone = false
val dialog = spyk(
ThirdPartyDownloadDialog(
activity = activity,
downloaderApps = listOf(mockk(), mockk()),
onAppSelected = { /* cannot test the viewholder click */ },
negativeButtonAction = { wasNegativeActionDone = true },
),
)
every { dialog.dismiss() } just Runs
val dialogParent = FrameLayout(testContext)
dialog.container = dialogParent

dialog.setupView()

assertEquals(1, dialogParent.childCount)
assertEquals(R.id.relativeLayout, dialogParent.getChildAt(0).id)
val dialogBinding = dialog.binding as MozacDownloaderChooserPromptBinding
assertEquals(2, dialogBinding.appsList.adapter?.itemCount)
dialogBinding.closeButton.callOnClick()
assertTrue(wasNegativeActionDone)
verify { dialog.dismiss() }
}
}

0 comments on commit 6428f96

Please sign in to comment.