From 0f07703c3eb51c08a48b17124038dbcf50a31f1f Mon Sep 17 00:00:00 2001 From: Arturo Mejia Date: Tue, 5 Oct 2021 16:47:59 -0400 Subject: [PATCH] For #21611: Show the jump back in Contextual Hints independently of the home onboarding dialog. --- .../org/mozilla/fenix/ui/BookmarksTest.kt | 4 +- .../org/mozilla/fenix/ui/CollectionTest.kt | 2 +- .../java/org/mozilla/fenix/ui/HistoryTest.kt | 2 +- .../org/mozilla/fenix/ui/HomeScreenTest.kt | 2 +- .../mozilla/fenix/ui/NavigationToolbarTest.kt | 3 + .../fenix/ui/NoNetworkAccessStartupTests.kt | 2 +- .../org/mozilla/fenix/ui/SettingsAboutTest.kt | 2 +- .../mozilla/fenix/ui/SettingsBasicsTest.kt | 4 +- .../mozilla/fenix/ui/SettingsPrivacyTest.kt | 6 +- .../java/org/mozilla/fenix/ui/SmokeTest.kt | 18 ++-- .../StrictEnhancedTrackingProtectionTest.kt | 4 +- .../mozilla/fenix/ui/TabbedBrowsingTest.kt | 5 +- .../mozilla/fenix/ui/ThreeDotMenuMainTest.kt | 2 +- .../java/org/mozilla/fenix/ui/TopSitesTest.kt | 10 +-- .../debug/res/raw/initial_experiments.json | 2 +- .../home/sessioncontrol/SessionControlView.kt | 9 +- .../HomeOnboardingDialogFragment.kt | 66 -------------- .../fenix/onboarding/JumpBackInCFRDialog.kt | 89 +++++++++++++++++++ .../java/org/mozilla/fenix/utils/Settings.kt | 8 ++ app/src/main/res/values/preference_keys.xml | 2 + 20 files changed, 144 insertions(+), 98 deletions(-) create mode 100644 app/src/main/java/org/mozilla/fenix/onboarding/JumpBackInCFRDialog.kt diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/BookmarksTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/BookmarksTest.kt index 6e6333359a..98be189808 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/BookmarksTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/BookmarksTest.kt @@ -52,6 +52,8 @@ class BookmarksTest { dispatcher = AndroidAssetDispatcher() start() } + val settings = activityTestRule.activity.settings() + settings.shouldShowJumpBackInCFR = false } @After @@ -346,7 +348,7 @@ class BookmarksTest { @Test fun openSelectionInNewTabTest() { val settings = activityTestRule.activity.applicationContext.settings() - settings.hasShownHomeOnboardingDialog = true + settings.shouldShowJumpBackInCFR = false val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1) browserScreen { diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/CollectionTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/CollectionTest.kt index 926e937106..3062db3909 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/CollectionTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/CollectionTest.kt @@ -40,7 +40,7 @@ class CollectionTest { @Before fun setUp() { - activityTestRule.activity.applicationContext.settings().hasShownHomeOnboardingDialog = true + activityTestRule.activity.applicationContext.settings().shouldShowJumpBackInCFR = false mockWebServer = MockWebServer().apply { dispatcher = AndroidAssetDispatcher() diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/HistoryTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/HistoryTest.kt index 448be81cee..094080b47b 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/HistoryTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/HistoryTest.kt @@ -43,7 +43,7 @@ class HistoryTest { @Before fun setUp() { InstrumentationRegistry.getInstrumentation().targetContext.settings() - .hasShownHomeOnboardingDialog = true + .shouldShowJumpBackInCFR = false mockWebServer = MockWebServer().apply { dispatcher = AndroidAssetDispatcher() diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/HomeScreenTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/HomeScreenTest.kt index c69a90c77e..dcd4fa299b 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/HomeScreenTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/HomeScreenTest.kt @@ -119,7 +119,7 @@ class HomeScreenTest { @Test fun dismissOnboardingUsingHelpTest() { val settings = activityTestRule.activity.applicationContext.settings() - settings.hasShownHomeOnboardingDialog = true + settings.shouldShowJumpBackInCFR = false homeScreen { verifyWelcomeHeader() }.openThreeDotMenu { diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/NavigationToolbarTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/NavigationToolbarTest.kt index c0efe42f71..0fdaa1810b 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/NavigationToolbarTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/NavigationToolbarTest.kt @@ -12,6 +12,7 @@ import org.junit.Before import org.junit.Ignore import org.junit.Rule import org.junit.Test +import org.mozilla.fenix.ext.settings import org.mozilla.fenix.helpers.AndroidAssetDispatcher import org.mozilla.fenix.helpers.HomeActivityTestRule import org.mozilla.fenix.helpers.TestAssetHelper @@ -41,6 +42,8 @@ class NavigationToolbarTest { dispatcher = AndroidAssetDispatcher() start() } + val settings = activityTestRule.activity.settings() + settings.shouldShowJumpBackInCFR = false } @After diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/NoNetworkAccessStartupTests.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/NoNetworkAccessStartupTests.kt index 67edeaa260..0720497078 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/NoNetworkAccessStartupTests.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/NoNetworkAccessStartupTests.kt @@ -56,7 +56,7 @@ class NoNetworkAccessStartupTests { fun networkInterruptedFromBrowserToHomeTest() { val url = "example.com" val settings = InstrumentationRegistry.getInstrumentation().targetContext.settings() - settings.hasShownHomeOnboardingDialog = true + settings.shouldShowJumpBackInCFR = false activityTestRule.launchActivity(null) diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/SettingsAboutTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/SettingsAboutTest.kt index 05492c4530..5e2a09bf03 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/SettingsAboutTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/SettingsAboutTest.kt @@ -77,7 +77,7 @@ class SettingsAboutTest { @Test fun verifyAboutFirefoxPreview() { val settings = activityIntentTestRule.activity.settings() - settings.hasShownHomeOnboardingDialog = true + settings.shouldShowJumpBackInCFR = false homeScreen { }.openThreeDotMenu { }.openSettings { diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/SettingsBasicsTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/SettingsBasicsTest.kt index 7dc9396480..1b70724990 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/SettingsBasicsTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/SettingsBasicsTest.kt @@ -43,6 +43,8 @@ class SettingsBasicsTest { dispatcher = AndroidAssetDispatcher() start() } + val settings = activityIntentTestRule.activity.settings() + settings.shouldShowJumpBackInCFR = false } @After @@ -157,7 +159,7 @@ class SettingsBasicsTest { val fenixApp = activityIntentTestRule.activity.applicationContext as FenixApplication val webpage = getLoremIpsumAsset(mockWebServer).url val settings = fenixApp.applicationContext.settings() - settings.hasShownHomeOnboardingDialog = true + settings.shouldShowJumpBackInCFR = false // This value will represent the text size percentage the webpage will scale to. The default value is 100%. val textSizePercentage = 180 diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/SettingsPrivacyTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/SettingsPrivacyTest.kt index 8178901ad0..cc58dbfd69 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/SettingsPrivacyTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/SettingsPrivacyTest.kt @@ -47,7 +47,7 @@ class SettingsPrivacyTest { } val settings = activityTestRule.activity.applicationContext.settings() - settings.hasShownHomeOnboardingDialog = true + settings.shouldShowJumpBackInCFR = false } @After @@ -223,7 +223,7 @@ class SettingsPrivacyTest { fun neverSaveLoginFromPromptTest() { val saveLoginTest = TestAssetHelper.getSaveLoginAsset(mockWebServer) val settings = activityTestRule.activity.settings() - settings.hasShownHomeOnboardingDialog = true + settings.shouldShowJumpBackInCFR = false navigationToolbar { }.enterURLAndEnterToBrowser(saveLoginTest.url) { @@ -330,7 +330,7 @@ class SettingsPrivacyTest { @Test fun launchLinksInPrivateToggleOffStateDoesntChangeTest() { val settings = activityTestRule.activity.applicationContext.settings() - settings.hasShownHomeOnboardingDialog = true + settings.shouldShowJumpBackInCFR = false val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1) setOpenLinksInPrivateOn() diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/SmokeTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/SmokeTest.kt index 701f34aa74..ef975a5280 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/SmokeTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/SmokeTest.kt @@ -108,7 +108,7 @@ class SmokeTest { // So we are initializing this here instead of in all related tests. browserStore = activityTestRule.activity.components.core.store - activityTestRule.activity.applicationContext.settings().hasShownHomeOnboardingDialog = true + activityTestRule.activity.applicationContext.settings().shouldShowJumpBackInCFR = false mockWebServer = MockWebServer().apply { dispatcher = AndroidAssetDispatcher() start() @@ -312,7 +312,7 @@ class SmokeTest { // Verifies the Add to top sites option in a tab's 3 dot menu fun openMainMenuAddTopSiteTest() { val settings = activityTestRule.activity.applicationContext.settings() - settings.hasShownHomeOnboardingDialog = true + settings.shouldShowJumpBackInCFR = false val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1) @@ -824,7 +824,7 @@ class SmokeTest { @Ignore("https://github.com/mozilla-mobile/fenix/issues/21397") fun createFirstCollectionTest() { val settings = activityTestRule.activity.applicationContext.settings() - settings.hasShownHomeOnboardingDialog = true + settings.shouldShowJumpBackInCFR = false val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1) val secondWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 2) @@ -858,7 +858,7 @@ class SmokeTest { @Ignore("https://github.com/mozilla-mobile/fenix/issues/21397") fun verifyExpandedCollectionItemsTest() { val settings = activityTestRule.activity.applicationContext.settings() - settings.hasShownHomeOnboardingDialog = true + settings.shouldShowJumpBackInCFR = false val webPage = TestAssetHelper.getGenericAsset(mockWebServer, 1) navigationToolbar { @@ -912,7 +912,7 @@ class SmokeTest { @Test fun shareCollectionTest() { val settings = activityTestRule.activity.applicationContext.settings() - settings.hasShownHomeOnboardingDialog = true + settings.shouldShowJumpBackInCFR = false val webPage = TestAssetHelper.getGenericAsset(mockWebServer, 1) @@ -938,7 +938,7 @@ class SmokeTest { // caution when making changes to it, so they don't block the builds fun deleteCollectionTest() { val settings = activityTestRule.activity.applicationContext.settings() - settings.hasShownHomeOnboardingDialog = true + settings.shouldShowJumpBackInCFR = false val webPage = TestAssetHelper.getGenericAsset(mockWebServer, 1) navigationToolbar { @@ -1357,7 +1357,7 @@ class SmokeTest { @Test fun goToHomeScreenBottomToolbarTest() { val settings = activityTestRule.activity.applicationContext.settings() - settings.hasShownHomeOnboardingDialog = true + settings.shouldShowJumpBackInCFR = false val genericURL = TestAssetHelper.getGenericAsset(mockWebServer, 1) navigationToolbar { @@ -1371,7 +1371,7 @@ class SmokeTest { @Test fun goToHomeScreenTopToolbarTest() { val settings = activityTestRule.activity.applicationContext.settings() - settings.hasShownHomeOnboardingDialog = true + settings.shouldShowJumpBackInCFR = false val genericURL = TestAssetHelper.getGenericAsset(mockWebServer, 1) @@ -1441,7 +1441,7 @@ class SmokeTest { @Test fun alwaysStartOnHomeTest() { val settings = activityTestRule.activity.applicationContext.settings() - settings.hasShownHomeOnboardingDialog = true + settings.shouldShowJumpBackInCFR = false val genericURL = TestAssetHelper.getGenericAsset(mockWebServer, 1) navigationToolbar { diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/StrictEnhancedTrackingProtectionTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/StrictEnhancedTrackingProtectionTest.kt index d22b12206e..1a5320a1bb 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/StrictEnhancedTrackingProtectionTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/StrictEnhancedTrackingProtectionTest.kt @@ -44,7 +44,9 @@ class StrictEnhancedTrackingProtectionTest { start() } - activityTestRule.activity.settings().setStrictETP() + val settings = activityTestRule.activity.settings() + settings.setStrictETP() + settings.shouldShowJumpBackInCFR = false } @After diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/TabbedBrowsingTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/TabbedBrowsingTest.kt index 685e3bc903..abe2f4ce96 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/TabbedBrowsingTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/TabbedBrowsingTest.kt @@ -48,14 +48,11 @@ class TabbedBrowsingTest { @Before fun setUp() { - activityTestRule.activity.applicationContext.settings().hasShownHomeOnboardingDialog = true + activityTestRule.activity.applicationContext.settings().shouldShowJumpBackInCFR = false mockWebServer = MockWebServer().apply { dispatcher = AndroidAssetDispatcher() start() } - - val settings = activityTestRule.activity.applicationContext.settings() - settings.hasShownHomeOnboardingDialog = true } @After diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/ThreeDotMenuMainTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/ThreeDotMenuMainTest.kt index c1689eac7d..ac0d9e7daf 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/ThreeDotMenuMainTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/ThreeDotMenuMainTest.kt @@ -29,7 +29,7 @@ class ThreeDotMenuMainTest { @Before fun setUp() { - activityTestRule.activity.applicationContext.settings().hasShownHomeOnboardingDialog = true + activityTestRule.activity.applicationContext.settings().shouldShowJumpBackInCFR = false mockWebServer = MockWebServer().apply { dispatcher = AndroidAssetDispatcher() start() diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/TopSitesTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/TopSitesTest.kt index d989813ee5..1e3616734f 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/TopSitesTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/TopSitesTest.kt @@ -50,7 +50,7 @@ class TopSitesTest { @Test fun verifyAddToFirefoxHome() { val settings = activityIntentTestRule.activity.applicationContext.settings() - settings.hasShownHomeOnboardingDialog = true + settings.shouldShowJumpBackInCFR = false val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1) val defaultWebPageTitle = "Test_Page_1" @@ -70,7 +70,7 @@ class TopSitesTest { @Test fun verifyOpenTopSiteNormalTab() { val settings = activityIntentTestRule.activity.applicationContext.settings() - settings.hasShownHomeOnboardingDialog = true + settings.shouldShowJumpBackInCFR = false val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1) val defaultWebPageTitle = "Test_Page_1" @@ -100,7 +100,7 @@ class TopSitesTest { @Test fun verifyOpenTopSitePrivateTab() { val settings = activityIntentTestRule.activity.applicationContext.settings() - settings.hasShownHomeOnboardingDialog = true + settings.shouldShowJumpBackInCFR = false val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1) val defaultWebPageTitle = "Test_Page_1" @@ -124,7 +124,7 @@ class TopSitesTest { @Test fun verifyRenameTopSite() { val settings = activityIntentTestRule.activity.applicationContext.settings() - settings.hasShownHomeOnboardingDialog = true + settings.shouldShowJumpBackInCFR = false val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1) val defaultWebPageTitle = "Test_Page_1" val defaultWebPageTitleNew = "Test_Page_2" @@ -150,7 +150,7 @@ class TopSitesTest { @Test fun verifyRemoveTopSite() { val settings = activityIntentTestRule.activity.applicationContext.settings() - settings.hasShownHomeOnboardingDialog = true + settings.shouldShowJumpBackInCFR = false val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1) val defaultWebPageTitle = "Test_Page_1" diff --git a/app/src/debug/res/raw/initial_experiments.json b/app/src/debug/res/raw/initial_experiments.json index 3514af8ee0..6bced9269e 100644 --- a/app/src/debug/res/raw/initial_experiments.json +++ b/app/src/debug/res/raw/initial_experiments.json @@ -12,7 +12,7 @@ "value": { "sections-enabled": { "topSites": true, - "recentExplorations": false, + "recentExplorations": true, "recentlySaved": false, "jumpBackIn": false, "pocket": false diff --git a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlView.kt b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlView.kt index 0903563cf7..5768118482 100644 --- a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlView.kt +++ b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlView.kt @@ -24,6 +24,7 @@ import org.mozilla.fenix.home.HomeScreenViewModel import org.mozilla.fenix.home.Mode import org.mozilla.fenix.home.OnboardingState import org.mozilla.fenix.home.recenttabs.RecentTab +import org.mozilla.fenix.onboarding.JumpBackInCFRDialog import org.mozilla.fenix.utils.Settings // This method got a little complex with the addition of the tab tray feature flag @@ -197,7 +198,13 @@ class SessionControlView( init { view.apply { adapter = sessionControlAdapter - layoutManager = LinearLayoutManager(containerView.context) + layoutManager = object : LinearLayoutManager(containerView.context) { + override fun onLayoutCompleted(state: RecyclerView.State?) { + super.onLayoutCompleted(state) + + JumpBackInCFRDialog(view).showIfNeeded() + } + } val itemTouchHelper = ItemTouchHelper( SwipeToDeleteCallback( diff --git a/app/src/main/java/org/mozilla/fenix/onboarding/HomeOnboardingDialogFragment.kt b/app/src/main/java/org/mozilla/fenix/onboarding/HomeOnboardingDialogFragment.kt index f776bead06..ad078aadba 100644 --- a/app/src/main/java/org/mozilla/fenix/onboarding/HomeOnboardingDialogFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/onboarding/HomeOnboardingDialogFragment.kt @@ -4,22 +4,14 @@ package org.mozilla.fenix.onboarding -import android.app.Dialog -import android.content.Context -import android.graphics.Color -import android.graphics.drawable.ColorDrawable import android.os.Bundle -import android.view.Gravity import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.fragment.app.DialogFragment -import androidx.recyclerview.widget.RecyclerView import org.mozilla.fenix.R import org.mozilla.fenix.databinding.FragmentOnboardingHomeDialogBinding -import org.mozilla.fenix.databinding.OnboardingJumpBackInCfrBinding import org.mozilla.fenix.ext.settings -import org.mozilla.fenix.home.recenttabs.view.RecentTabsHeaderViewHolder /** * Dialog displayed once when one or multiples of these sections are shown in the home screen @@ -45,65 +37,7 @@ class HomeOnboardingDialogFragment : DialogFragment() { context?.settings()?.let { settings -> settings.hasShownHomeOnboardingDialog = true } - showJumpCFR() dismiss() } } - - private fun showJumpCFR() { - val jumpBackInView = findJumpBackInView() - jumpBackInView?.let { - val crfDialog = createJumpCRF(anchor = jumpBackInView) - crfDialog?.show() - } - } - - private fun findJumpBackInView(): View? { - val list = activity?.findViewById(R.id.sessionControlRecyclerView) - val count = list?.adapter?.itemCount ?: return null - - for (index in 0..count) { - val viewHolder = list.findViewHolderForAdapterPosition(index) - if (viewHolder is RecentTabsHeaderViewHolder) { - return viewHolder.containerView - } - } - return null - } - - private fun createJumpCRF(anchor: View): Dialog? { - val context: Context = requireContext() - val anchorPosition = IntArray(2) - val popupBinding = OnboardingJumpBackInCfrBinding.inflate(LayoutInflater.from(context)) - val popup = Dialog(context) - - popup.apply { - setContentView(popupBinding.root) - setCancelable(false) - // removing title or setting it as an empty string does not prevent a11y services from assigning one - setTitle(" ") - } - popupBinding.closeInfoBanner.setOnClickListener { - popup.dismiss() - } - - anchor.getLocationOnScreen(anchorPosition) - val (x, y) = anchorPosition - - if (x == 0 && y == 0) { - return null - } - - popupBinding.root.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED) - - popup.window?.apply { - val attr = attributes - setGravity(Gravity.START or Gravity.TOP) - attr.x = x - attr.y = y - popupBinding.root.measuredHeight - attributes = attr - setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) - } - return popup - } } diff --git a/app/src/main/java/org/mozilla/fenix/onboarding/JumpBackInCFRDialog.kt b/app/src/main/java/org/mozilla/fenix/onboarding/JumpBackInCFRDialog.kt new file mode 100644 index 0000000000..31a87ae3a9 --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/onboarding/JumpBackInCFRDialog.kt @@ -0,0 +1,89 @@ +/* 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.onboarding + +import android.app.Dialog +import android.content.Context +import android.graphics.Color +import android.graphics.drawable.ColorDrawable +import android.view.Gravity +import android.view.LayoutInflater +import android.view.View +import androidx.recyclerview.widget.RecyclerView +import org.mozilla.fenix.databinding.OnboardingJumpBackInCfrBinding +import org.mozilla.fenix.ext.settings +import org.mozilla.fenix.home.recenttabs.view.RecentTabsHeaderViewHolder + +/** + * Dialog displayed once when the jump back in section is shown in the home screen. + */ +class JumpBackInCFRDialog(val recyclerView: RecyclerView) { + + /** + * Try to show the crf dialog if it hasn't been shown before. + */ + fun showIfNeeded() { + val jumpBackInView = findJumpBackInView() + jumpBackInView?.let { + val crfDialog = createJumpCRF(anchor = jumpBackInView) + crfDialog?.let { + val context = jumpBackInView.context + context.settings().shouldShowJumpBackInCFR = false + it.show() + } + } + } + + private fun findJumpBackInView(): View? { + val count = recyclerView.adapter?.itemCount ?: return null + + for (index in 0..count) { + val viewHolder = recyclerView.findViewHolderForAdapterPosition(index) + if (viewHolder is RecentTabsHeaderViewHolder) { + return viewHolder.containerView + } + } + return null + } + + private fun createJumpCRF(anchor: View): Dialog? { + val context: Context = recyclerView.context + if (!context.settings().shouldShowJumpBackInCFR) { + return null + } + val anchorPosition = IntArray(2) + val popupBinding = OnboardingJumpBackInCfrBinding.inflate(LayoutInflater.from(context)) + val popup = Dialog(context) + + popup.apply { + setContentView(popupBinding.root) + setCancelable(false) + // removing title or setting it as an empty string does not prevent a11y services from assigning one + setTitle(" ") + } + popupBinding.closeInfoBanner.setOnClickListener { + popup.dismiss() + } + + anchor.getLocationOnScreen(anchorPosition) + val (x, y) = anchorPosition + + if (x == 0 && y == 0) { + return null + } + + popupBinding.root.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED) + + popup.window?.apply { + val attr = attributes + setGravity(Gravity.START or Gravity.TOP) + attr.x = x + attr.y = y - popupBinding.root.measuredHeight + attributes = attr + setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) + } + return popup + } +} diff --git a/app/src/main/java/org/mozilla/fenix/utils/Settings.kt b/app/src/main/java/org/mozilla/fenix/utils/Settings.kt index a7b7459722..a930e80ac6 100644 --- a/app/src/main/java/org/mozilla/fenix/utils/Settings.kt +++ b/app/src/main/java/org/mozilla/fenix/utils/Settings.kt @@ -837,6 +837,14 @@ class Settings(private val appContext: Context) : PreferencesHolder { default = true ) + /** + * Indicates if the jump back in CRF should be shown. + */ + var shouldShowJumpBackInCFR by booleanPreference( + appContext.getPreferenceKey(R.string.pref_key_should_show_jump_back_in_tabs_popup), + default = true + ) + fun getSitePermissionsPhoneFeatureAction( feature: PhoneFeature, default: Action = Action.ASK_TO_ALLOW diff --git a/app/src/main/res/values/preference_keys.xml b/app/src/main/res/values/preference_keys.xml index d3d2873fac..8dfec3df80 100644 --- a/app/src/main/res/values/preference_keys.xml +++ b/app/src/main/res/values/preference_keys.xml @@ -227,6 +227,8 @@ pref_key_should_show_inactive_tabs_popup + + pref_key_should_show_jump_back_in_tabs_popup pref_key_migrating_from_fenix_nightly_tip