You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
iceraven-browser/app/src/main/java/org/mozilla/fenix/tabstray/TabsTrayInactiveTabsOnboard...

125 lines
4.9 KiB
Kotlin

/* 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 mozilla.telemetry.glean.private.NoExtras
import org.mozilla.fenix.GleanMetrics.TabsTray
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.ext.potentialInactiveTabs
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) {
private lateinit var inactiveTabsDialog: Dialog
@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.potentialInactiveTabs } else emptyList()
if (inactiveTabsList.isNotEmpty() && shouldShowOnboardingForInactiveTabs()) {
createInactiveCFR()
}
}
}
private fun shouldShowOnboardingForInactiveTabs() =
settings.shouldShowInactiveTabsOnboardingPopup &&
settings.canShowCfr
private fun createInactiveCFR() {
// Don't create a new dialog if one is already displayed
if (this::inactiveTabsDialog.isInitialized) return
val context: Context = context
val anchorPosition = IntArray(2)
val popupBinding = OnboardingInactiveTabsCfrBinding.inflate(LayoutInflater.from(context))
inactiveTabsDialog = Dialog(context)
inactiveTabsDialog.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 {
inactiveTabsDialog.dismiss()
settings.shouldShowInactiveTabsOnboardingPopup = false
TabsTray.inactiveTabsCfrDismissed.record(NoExtras())
}
popupBinding.bannerInfoMessage.setOnClickListener {
inactiveTabsDialog.dismiss()
settings.shouldShowInactiveTabsOnboardingPopup = false
navigationInteractor.onTabSettingsClicked()
TabsTray.inactiveTabsCfrSettings.record(NoExtras())
}
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)
inactiveTabsDialog.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))
}
inactiveTabsDialog.show()
TabsTray.inactiveTabsCfrVisible.record(NoExtras())
}
}