For #21565 - Adds inactive tabs onboarding popup

upstream-sync
codrut.topliceanu 3 years ago committed by mergify[bot]
parent 571a2fc88e
commit a53b52b764

@ -31,7 +31,6 @@ import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.NavGraphDirections
import org.mozilla.fenix.R
import org.mozilla.fenix.components.FenixSnackbar
import org.mozilla.fenix.share.ShareFragment
import org.mozilla.fenix.components.StoreProvider
import org.mozilla.fenix.components.metrics.Event
import org.mozilla.fenix.databinding.ComponentTabstray2Binding
@ -43,6 +42,7 @@ import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.requireComponents
import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.home.HomeScreenViewModel
import org.mozilla.fenix.share.ShareFragment
import org.mozilla.fenix.tabstray.browser.BrowserTrayInteractor
import org.mozilla.fenix.tabstray.browser.DefaultBrowserTrayInteractor
import org.mozilla.fenix.tabstray.browser.SelectionBannerBinding
@ -72,6 +72,7 @@ class TabsTrayFragment : AppCompatDialogFragment() {
private val selectionHandleBinding = ViewBoundFeatureWrapper<SelectionHandleBinding>()
private val tabsTrayCtaBinding = ViewBoundFeatureWrapper<TabsTrayInfoBannerBinding>()
private val secureTabsTrayBinding = ViewBoundFeatureWrapper<SecureTabsTrayBinding>()
private val tabsTrayInactiveTabsOnboardingBinding = ViewBoundFeatureWrapper<TabsTrayInactiveTabsOnboardingBinding>()
@VisibleForTesting @Suppress("VariableNaming")
internal var _tabsTrayBinding: ComponentTabstray2Binding? = null
@ -319,6 +320,18 @@ class TabsTrayFragment : AppCompatDialogFragment() {
view = view
)
tabsTrayInactiveTabsOnboardingBinding.set(
feature = TabsTrayInactiveTabsOnboardingBinding(
context = requireContext(),
store = requireComponents.core.store,
tabsTrayBinding = tabsTrayBinding,
settings = requireComponents.settings,
navigationInteractor = navigationInteractor
),
owner = this,
view = view
)
setFragmentResultListener(ShareFragment.RESULT_KEY) { _, _ ->
dismissTabsTray()
}

@ -0,0 +1,114 @@
/* 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.tabstray
import android.app.Dialog
import android.content.Context
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.text.SpannableStringBuilder
import android.text.Spanned
import android.text.style.UnderlineSpan
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import androidx.annotation.VisibleForTesting
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.map
import mozilla.components.browser.state.selector.normalTabs
import mozilla.components.browser.state.state.BrowserState
import mozilla.components.browser.state.store.BrowserStore
import mozilla.components.lib.state.helpers.AbstractBinding
import mozilla.components.support.ktx.android.util.dpToPx
import mozilla.components.support.ktx.kotlinx.coroutines.flow.ifChanged
import org.mozilla.fenix.R
import org.mozilla.fenix.browser.infobanner.InfoBanner
import org.mozilla.fenix.databinding.ComponentTabstray2Binding
import org.mozilla.fenix.databinding.OnboardingInactiveTabsCfrBinding
import org.mozilla.fenix.tabstray.ext.inactiveTabs
import org.mozilla.fenix.utils.Settings
@OptIn(ExperimentalCoroutinesApi::class)
class TabsTrayInactiveTabsOnboardingBinding(
private val context: Context,
private val store: BrowserStore,
private val tabsTrayBinding: ComponentTabstray2Binding?,
private val settings: Settings,
private val navigationInteractor: NavigationInteractor
) : AbstractBinding<BrowserState>(store) {
@VisibleForTesting
internal var banner: InfoBanner? = null
override suspend fun onState(flow: Flow<BrowserState>) {
flow.map { state -> state.normalTabs.size }
.ifChanged()
.collect {
val inactiveTabsList =
if (settings.inactiveTabsAreEnabled) { store.state.inactiveTabs } else emptyList()
if (inactiveTabsList.isNotEmpty() && shouldShowOnboardingForInactiveTabs()) {
createInactiveCFR()
}
}
}
private fun shouldShowOnboardingForInactiveTabs() =
settings.shouldShowInactiveTabsOnboardingPopup &&
settings.canShowCfr
private fun createInactiveCFR() {
val context: Context = context
val anchorPosition = IntArray(2)
val popupBinding = OnboardingInactiveTabsCfrBinding.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()
settings.shouldShowInactiveTabsOnboardingPopup = false
}
popupBinding.bannerInfoMessage.setOnClickListener {
popup.dismiss()
settings.shouldShowInactiveTabsOnboardingPopup = false
navigationInteractor.onTabSettingsClicked()
}
val messageText = context.getString(R.string.tab_tray_inactive_onboarding_message)
val actionText = context.getString(R.string.tab_tray_inactive_onboarding_button_text)
val spannableStringBuilder = SpannableStringBuilder(messageText)
spannableStringBuilder.append(" ")
.append(actionText, UnderlineSpan(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
popupBinding.bannerInfoMessage.text = spannableStringBuilder
tabsTrayBinding?.tabsTray?.getLocationOnScreen(anchorPosition)
val (x, y) = anchorPosition
if (x == 0 && y == 0) {
return
}
popupBinding.root.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED)
popup.window?.apply {
val attr = attributes
setGravity(Gravity.START or Gravity.TOP)
attr.x = x + 15.dpToPx(context.resources.displayMetrics)
attr.y = y + 20.dpToPx(context.resources.displayMetrics)
attributes = attr
setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
}
popup.show()
}
}

@ -832,6 +832,11 @@ class Settings(private val appContext: Context) : PreferencesHolder {
default = true
)
var shouldShowInactiveTabsOnboardingPopup by booleanPreference(
appContext.getPreferenceKey(R.string.pref_key_should_show_inactive_tabs_popup),
default = true
)
fun getSitePermissionsPhoneFeatureAction(
feature: PhoneFeature,
default: Action = Action.ASK_TO_ALLOW

@ -0,0 +1,60 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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/. -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ImageView
android:layout_width="@dimen/cfr_triangle_width"
android:layout_height="@dimen/cfr_triangle_height"
android:layout_gravity="start"
android:layout_marginStart="15dp"
android:layout_marginEnd="@dimen/cfr_triangle_margin_edge"
android:importantForAccessibility="no"
app:srcCompat="@drawable/ic_cfr_triangle"
app:tint="#7542E5" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/banner_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/onboarding_popup_shape">
<TextView
android:id="@+id/banner_info_message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="16dp"
android:maxWidth="200dp"
android:text="@string/tab_tray_inactive_onboarding_message"
android:textAppearance="@style/Body16TextStyle"
android:textColor="@color/contrast_text_light_theme"
android:textSize="16sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/close_info_banner"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0" />
<ImageButton
android:id="@+id/close_info_banner"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:background="?selectableItemBackgroundBorderless"
android:contentDescription="@string/content_description_close_button"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/ic_close"
app:tint="@color/contrast_text_light_theme" />
</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>

@ -225,6 +225,10 @@
<!-- A value of `true` means the Auto Close Tabs Banner has not been shown yet -->
<string name="pref_key_should_show_auto_close_tabs_banner" translatable="false">pref_key_should_show_auto_close_tabs_banner</string>
<!-- A value of `true` means the Inactive tabs onboarding popup has not been shown yet -->
<string name="pref_key_should_show_inactive_tabs_popup" translatable="false">pref_key_should_show_inactive_tabs_popup</string>
<string name="pref_key_migrating_from_fenix_nightly_tip" translatable="false">pref_key_migrating_from_fenix_nightly_tip</string>
<string name="pref_key_migrating_from_firefox_nightly_tip" translatable="false">pref_key_migrating_from_firefox_nightly_tip</string>
<string name="pref_key_migrating_from_fenix_tip" translatable="false">pref_key_migrating_from_fenix_tip</string>

@ -107,9 +107,9 @@
<!-- Text for the negative action button to dismiss the Close Tabs Banner. -->
<string name="tab_tray_close_tabs_banner_negative_button_text">Dismiss</string>
<!-- Text for the banner message to tell users about our inactive tabs feature. -->
<string name="tab_tray_inactive_onboarding_message" tools:ignore="UnusedResources">Tabs you havent viewed for two weeks get moved here.</string>
<string name="tab_tray_inactive_onboarding_message">Tabs you havent viewed for two weeks get moved here.</string>
<!-- Text for the action link to go to Settings for inactive tabs. -->
<string name="tab_tray_inactive_onboarding_button_text" tools:ignore="UnusedResources">Turn off in settings</string>
<string name="tab_tray_inactive_onboarding_button_text">Turn off in settings</string>
<!-- Home screen icons - Long press shortcuts -->
<!-- Shortcut action to open new tab -->

Loading…
Cancel
Save