diff --git a/app/src/main/java/org/mozilla/fenix/browser/InfoBanner.kt b/app/src/main/java/org/mozilla/fenix/browser/InfoBanner.kt
index be74646d2..d7f4187cc 100644
--- a/app/src/main/java/org/mozilla/fenix/browser/InfoBanner.kt
+++ b/app/src/main/java/org/mozilla/fenix/browser/InfoBanner.kt
@@ -13,6 +13,7 @@ import android.view.ViewGroup.LayoutParams.MATCH_PARENT
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
import kotlinx.android.synthetic.main.info_banner.view.*
import org.mozilla.fenix.R
+import org.mozilla.fenix.ext.settings
/**
* Displays an Info Banner in the specified container with a message and an optional action.
@@ -25,12 +26,15 @@ import org.mozilla.fenix.R
* @param actionText - The text on the action to perform button
* @param actionToPerform - The action to be performed on action button press
*/
+@SuppressWarnings("LongParameterList")
class InfoBanner(
private val context: Context,
private val container: ViewGroup,
private val message: String,
private val dismissText: String,
private val actionText: String? = null,
+ private val dismissByHiding: Boolean = false,
+ private val dismissAction: (() -> Unit)? = null,
private val actionToPerform: (() -> Unit)? = null
) {
@SuppressLint("InflateParams")
@@ -54,12 +58,15 @@ class InfoBanner(
params.width = MATCH_PARENT
bannerLayout.dismiss.setOnClickListener {
- dismiss()
+ dismissAction?.invoke()
+ if (dismissByHiding) { bannerLayout.visibility = GONE } else { dismiss() }
}
bannerLayout.action.setOnClickListener {
actionToPerform?.invoke()
}
+
+ context.settings().lastCfrShownTimeInMillis = System.currentTimeMillis()
}
internal fun dismiss() {
diff --git a/app/src/main/java/org/mozilla/fenix/browser/OpenInAppOnboardingObserver.kt b/app/src/main/java/org/mozilla/fenix/browser/OpenInAppOnboardingObserver.kt
index 43be8b169..63b8c2635 100644
--- a/app/src/main/java/org/mozilla/fenix/browser/OpenInAppOnboardingObserver.kt
+++ b/app/src/main/java/org/mozilla/fenix/browser/OpenInAppOnboardingObserver.kt
@@ -60,7 +60,6 @@ class OpenInAppOnboardingObserver(
infoBanner?.showBanner()
sessionDomainForDisplayedBanner = session.url.tryGetHostFromUrl()
- settings.lastCfrShownTimeInMillis = System.currentTimeMillis()
settings.shouldShowOpenInAppBanner = false
}
}
diff --git a/app/src/main/java/org/mozilla/fenix/tabtray/TabTrayController.kt b/app/src/main/java/org/mozilla/fenix/tabtray/TabTrayController.kt
index 431bfe898..41c6ddf40 100644
--- a/app/src/main/java/org/mozilla/fenix/tabtray/TabTrayController.kt
+++ b/app/src/main/java/org/mozilla/fenix/tabtray/TabTrayController.kt
@@ -43,6 +43,7 @@ interface TabTrayController {
fun handleOpenTab(tab: Tab)
fun handleEnterMultiselect()
fun handleRecentlyClosedClicked()
+ fun handleSetUpAutoCloseTabsClicked()
}
/**
@@ -184,4 +185,9 @@ class DefaultTabTrayController(
val directions = TabTrayDialogFragmentDirections.actionGlobalRecentlyClosed()
navController.navigate(directions)
}
+
+ override fun handleSetUpAutoCloseTabsClicked() {
+ val directions = TabTrayDialogFragmentDirections.actionGlobalCloseTabSettingsFragment()
+ navController.navigate(directions)
+ }
}
diff --git a/app/src/main/java/org/mozilla/fenix/tabtray/TabTrayFragmentInteractor.kt b/app/src/main/java/org/mozilla/fenix/tabtray/TabTrayFragmentInteractor.kt
index 3cf89a386..556023572 100644
--- a/app/src/main/java/org/mozilla/fenix/tabtray/TabTrayFragmentInteractor.kt
+++ b/app/src/main/java/org/mozilla/fenix/tabtray/TabTrayFragmentInteractor.kt
@@ -54,6 +54,11 @@ interface TabTrayInteractor {
*/
fun onModeRequested(): TabTrayDialogFragmentState.Mode
+ /**
+ * Called when user clicks on the "set it up" prompt for automatically closing tabs
+ */
+ fun onSetUpAutoCloseTabsClicked()
+
/**
* Called when a tab should be opened in the browser.
*/
@@ -140,4 +145,8 @@ class TabTrayFragmentInteractor(private val controller: TabTrayController) : Tab
override fun onEnterMultiselect() {
controller.handleEnterMultiselect()
}
+
+ override fun onSetUpAutoCloseTabsClicked() {
+ controller.handleSetUpAutoCloseTabsClicked()
+ }
}
diff --git a/app/src/main/java/org/mozilla/fenix/tabtray/TabTrayView.kt b/app/src/main/java/org/mozilla/fenix/tabtray/TabTrayView.kt
index 948fb9e88..2d24cc0ef 100644
--- a/app/src/main/java/org/mozilla/fenix/tabtray/TabTrayView.kt
+++ b/app/src/main/java/org/mozilla/fenix/tabtray/TabTrayView.kt
@@ -43,6 +43,7 @@ import mozilla.components.browser.tabstray.TabViewHolder
import mozilla.components.feature.syncedtabs.SyncedTabsFeature
import mozilla.components.support.base.feature.ViewBoundFeatureWrapper
import org.mozilla.fenix.R
+import org.mozilla.fenix.browser.InfoBanner
import org.mozilla.fenix.components.metrics.Event
import org.mozilla.fenix.components.toolbar.TabCounter.Companion.INFINITE_CHAR_PADDING_BOTTOM
import org.mozilla.fenix.components.toolbar.TabCounter.Companion.MAX_VISIBLE_TABS
@@ -239,6 +240,28 @@ class TabTrayView(
}
adjustNewTabButtonsForNormalMode()
+
+ if (
+ view.context.settings().shouldShowAutoCloseTabsBanner &&
+ view.context.settings().canShowCfr &&
+ tabs.size >= TAB_COUNT_SHOW_CFR
+ ) {
+ InfoBanner(
+ context = view.context,
+ message = view.context.getString(R.string.tab_tray_close_tabs_banner_message),
+ dismissText = view.context.getString(R.string.tab_tray_close_tabs_banner_negative_button_text),
+ actionText = view.context.getString(R.string.tab_tray_close_tabs_banner_positive_button_text),
+ container = view.infoBanner,
+ dismissByHiding = true,
+ dismissAction = { view.context.settings().shouldShowAutoCloseTabsBanner = false }
+ ) {
+ interactor.onSetUpAutoCloseTabsClicked()
+ view.context.settings().shouldShowAutoCloseTabsBanner = false
+ }.apply {
+ view.infoBanner.visibility = View.VISIBLE
+ showBanner()
+ }
+ }
}
private fun handleTabClicked(tab: SyncTab) {
@@ -578,6 +601,7 @@ class TabTrayView(
}
companion object {
+ private const val TAB_COUNT_SHOW_CFR = 6
private const val DEFAULT_TAB_ID = 0
private const val PRIVATE_TAB_ID = 1
private const val EXPAND_AT_SIZE = 3
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 ff4bed759..a0bd0ad76 100644
--- a/app/src/main/java/org/mozilla/fenix/utils/Settings.kt
+++ b/app/src/main/java/org/mozilla/fenix/utils/Settings.kt
@@ -689,6 +689,11 @@ class Settings(private val appContext: Context) : PreferencesHolder {
val shouldShowOpenInAppCfr: Boolean
get() = canShowCfr && shouldShowOpenInAppBanner
+ var shouldShowAutoCloseTabsBanner by booleanPreference(
+ appContext.getPreferenceKey(R.string.pref_key_should_show_auto_close_tabs_banner),
+ default = true
+ )
+
@VisibleForTesting(otherwise = PRIVATE)
internal val trackingProtectionOnboardingCount = counterPreference(
appContext.getPreferenceKey(R.string.pref_key_tracking_protection_onboarding),
diff --git a/app/src/main/res/layout/component_tabstray.xml b/app/src/main/res/layout/component_tabstray.xml
index e785b4dfd..0005ecb5a 100644
--- a/app/src/main/res/layout/component_tabstray.xml
+++ b/app/src/main/res/layout/component_tabstray.xml
@@ -24,6 +24,15 @@
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_percent="0.1" />
+
+
+
+ app:layout_constraintTop_toBottomOf="@id/infoBanner" />
+ app:layout_constraintTop_toBottomOf="@+id/infoBanner" />
pref_key_should_show_open_in_app_banner
+
+ pref_key_should_show_auto_close_tabs_banner
+
pref_key_migrating_from_fenix_nightly_tip
pref_key_migrating_from_firefox_nightly_tip
pref_key_migrating_from_fenix_tip
diff --git a/app/src/test/java/org/mozilla/fenix/tabtray/DefaultTabTrayControllerTest.kt b/app/src/test/java/org/mozilla/fenix/tabtray/DefaultTabTrayControllerTest.kt
index 0e478c3ba..c484c82a2 100644
--- a/app/src/test/java/org/mozilla/fenix/tabtray/DefaultTabTrayControllerTest.kt
+++ b/app/src/test/java/org/mozilla/fenix/tabtray/DefaultTabTrayControllerTest.kt
@@ -248,4 +248,14 @@ class DefaultTabTrayControllerTest {
showChooseCollectionDialog(listOf(session))
}
}
+
+ @Test
+ fun handleSetUpAutoCloseTabsClicked() {
+ controller.handleSetUpAutoCloseTabsClicked()
+ val directions = TabTrayDialogFragmentDirections.actionGlobalCloseTabSettingsFragment()
+
+ verify {
+ navController.navigate(directions)
+ }
+ }
}
diff --git a/app/src/test/java/org/mozilla/fenix/tabtray/TabTrayFragmentInteractorTest.kt b/app/src/test/java/org/mozilla/fenix/tabtray/TabTrayFragmentInteractorTest.kt
index 7fbb8306c..1e1f027e1 100644
--- a/app/src/test/java/org/mozilla/fenix/tabtray/TabTrayFragmentInteractorTest.kt
+++ b/app/src/test/java/org/mozilla/fenix/tabtray/TabTrayFragmentInteractorTest.kt
@@ -106,4 +106,10 @@ class TabTrayFragmentInteractorTest {
interactor.onEnterMultiselect()
verify { controller.handleEnterMultiselect() }
}
+
+ @Test
+ fun onSetUpAutoCloseTabsClicked() {
+ interactor.onSetUpAutoCloseTabsClicked()
+ verify { controller.handleSetUpAutoCloseTabsClicked() }
+ }
}
diff --git a/buildSrc/src/main/java/Dependencies.kt b/buildSrc/src/main/java/Dependencies.kt
index ff7344e09..6daeba32e 100644
--- a/buildSrc/src/main/java/Dependencies.kt
+++ b/buildSrc/src/main/java/Dependencies.kt
@@ -15,7 +15,7 @@ object Versions {
const val androidx_appcompat = "1.2.0-rc01"
const val androidx_biometric = "1.1.0-alpha01"
const val androidx_coordinator_layout = "1.1.0-rc01"
- const val androidx_constraint_layout = "2.0.0-beta6"
+ const val androidx_constraint_layout = "2.0.0"
const val androidx_preference = "1.1.0"
const val androidx_legacy = "1.0.0"
const val androidx_annotation = "1.1.0"