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...

121 lines
4.7 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 org.mozilla.fenix.R
import org.mozilla.fenix.browser.infobanner.InfoBanner
import org.mozilla.fenix.components.metrics.Event
import org.mozilla.fenix.databinding.ComponentTabstray2Binding
import org.mozilla.fenix.databinding.OnboardingInactiveTabsCfrBinding
import org.mozilla.fenix.ext.components
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) {
@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() {
val context: Context = context
val metrics = context.components.analytics.metrics
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
metrics.track(Event.TabsTrayInactiveTabsCFRDismissed)
}
popupBinding.bannerInfoMessage.setOnClickListener {
popup.dismiss()
settings.shouldShowInactiveTabsOnboardingPopup = false
navigationInteractor.onTabSettingsClicked()
metrics.track(Event.TabsTrayInactiveTabsCFRGotoSettings)
}
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()
metrics.track(Event.TabsTrayInactiveTabsCFRIsVisible)
}
}