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/onboarding/HomeCFRPresenter.kt

176 lines
6.4 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.onboarding
import android.content.Context
import android.view.View
import androidx.compose.material.Text
import androidx.compose.ui.unit.dp
import androidx.core.content.ContextCompat.getColor
import androidx.recyclerview.widget.RecyclerView
import mozilla.components.compose.cfr.CFRPopup
import mozilla.components.compose.cfr.CFRPopupProperties
import mozilla.components.service.glean.private.NoExtras
import org.mozilla.fenix.GleanMetrics.Onboarding
import org.mozilla.fenix.GleanMetrics.RecentTabs
import org.mozilla.fenix.R
import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.home.recentsyncedtabs.view.RecentSyncedTabViewHolder
import org.mozilla.fenix.home.recenttabs.view.RecentTabsHeaderViewHolder
import org.mozilla.fenix.theme.FirefoxTheme
/**
* Vertical padding needed to improve the visual alignment of the popup and respect the UX design.
*/
private const val CFR_TO_ANCHOR_VERTICAL_PADDING = -16
/**
* Delegate for handling the Home Onboarding CFR.
*
* @param context [Context] used for various Android interactions.
* @param recyclerView [RecyclerView] will serve as anchor for the CFR.
*/
class HomeCFRPresenter(
private val context: Context,
private val recyclerView: RecyclerView,
) {
/**
* Determine the CFR to be shown on the Home screen and show a CFR for the resultant view
* if any.
*/
fun show(): Boolean {
return when (val result = getCFRToShow()) {
is Result.SyncedTab -> {
showSyncedTabCFR(view = result.view)
true
}
is Result.JumpBackIn -> {
showJumpBackInCFR(view = result.view)
true
}
else -> false
}
}
private fun showSyncedTabCFR(view: View) {
CFRPopup(
anchor = view,
properties = CFRPopupProperties(
popupBodyColors = listOf(
getColor(context, R.color.fx_mobile_layer_color_gradient_end),
getColor(context, R.color.fx_mobile_layer_color_gradient_start),
),
popupVerticalOffset = CFR_TO_ANCHOR_VERTICAL_PADDING.dp,
dismissButtonColor = getColor(context, R.color.fx_mobile_icon_color_oncolor),
indicatorDirection = CFRPopup.IndicatorDirection.DOWN,
),
onDismiss = {
when (it) {
true -> Onboarding.syncCfrExplicitDismissal.record(NoExtras())
false -> Onboarding.syncCfrImplicitDismissal.record(NoExtras())
}
},
text = {
FirefoxTheme {
Text(
text = context.getString(R.string.sync_cfr_message),
color = FirefoxTheme.colors.textOnColorPrimary,
style = FirefoxTheme.typography.body2,
)
}
},
).show()
// Turn off both the recent tab and synced tab CFR after the recent synced tab CFR is shown.
context.settings().showSyncCFR = false
context.settings().shouldShowJumpBackInCFR = false
Onboarding.synCfrShown.record(NoExtras())
}
@Suppress("MagicNumber")
private fun showJumpBackInCFR(view: View) {
CFRPopup(
anchor = view,
properties = CFRPopupProperties(
popupBodyColors = listOf(
getColor(context, R.color.fx_mobile_layer_color_gradient_end),
getColor(context, R.color.fx_mobile_layer_color_gradient_start),
),
popupVerticalOffset = (-40).dp, // Offset the top spacer in the recent tabs header.
dismissButtonColor = getColor(context, R.color.fx_mobile_icon_color_oncolor),
indicatorDirection = CFRPopup.IndicatorDirection.DOWN,
),
onDismiss = {
when (it) {
true -> RecentTabs.jumpBackInCfrDismissed.record(NoExtras())
false -> RecentTabs.jumpBackInCfrCancelled.record(NoExtras())
}
},
text = {
FirefoxTheme {
Text(
text = context.getString(R.string.onboarding_home_screen_jump_back_contextual_hint_2),
color = FirefoxTheme.colors.textOnColorPrimary,
style = FirefoxTheme.typography.body2,
)
}
},
).show()
// Users can still see the recent synced tab CFR after the recent tab CFR is shown in
// subsequent navigation to the Home screen.
context.settings().shouldShowJumpBackInCFR = false
RecentTabs.jumpBackInCfrShown.record(NoExtras())
}
/**
* Returns a [Result] that indicates the CFR that should be shown on the Home screen if any
* based on the views available and the preferences.
*/
private fun getCFRToShow(): Result {
var result: Result = Result.None
val count = recyclerView.adapter?.itemCount ?: return result
for (index in count downTo 0) {
val viewHolder = recyclerView.findViewHolderForAdapterPosition(index)
if (context.settings().showSyncCFR && viewHolder is RecentSyncedTabViewHolder) {
result = Result.SyncedTab(view = viewHolder.composeView)
break
} else if (context.settings().shouldShowJumpBackInCFR &&
viewHolder is RecentTabsHeaderViewHolder
) {
result = Result.JumpBackIn(view = viewHolder.composeView)
}
}
return result
}
/**
* The result of determining which CFR to show on the Home screen.
*/
sealed class Result {
/**
* Indicates no CFR should be shown on the Home screen.
*/
object None : Result()
/**
* Indicates a CFR should be shown for a Synced Tab and the associated [view] to anchor
* the CFR.
*/
data class SyncedTab(val view: View) : Result()
/**
* Indicates a CFR should be for Jump Back In and the associated [view] to anchor the CFR.
*/
data class JumpBackIn(val view: View) : Result()
}
}