[fenix] For https://github.com/mozilla-mobile/fenix/issues/24235 - Remove Tip from HomeFragmentStore
parent
082705a3c6
commit
13af68853e
@ -1,39 +0,0 @@
|
||||
/* 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.components.tips
|
||||
|
||||
import android.graphics.drawable.Drawable
|
||||
|
||||
sealed class TipType {
|
||||
data class Button(val text: String, val action: () -> Unit) : TipType()
|
||||
}
|
||||
|
||||
open class Tip(
|
||||
val type: TipType,
|
||||
val identifier: String,
|
||||
val title: String,
|
||||
val description: String,
|
||||
val learnMoreURL: String?,
|
||||
val titleDrawable: Drawable? = null
|
||||
)
|
||||
|
||||
interface TipProvider {
|
||||
val tip: Tip?
|
||||
val shouldDisplay: Boolean
|
||||
}
|
||||
|
||||
interface TipManager {
|
||||
fun getTip(): Tip?
|
||||
}
|
||||
|
||||
class FenixTipManager(
|
||||
private val providers: List<TipProvider>
|
||||
) : TipManager {
|
||||
override fun getTip(): Tip? {
|
||||
return providers
|
||||
.firstOrNull { it.shouldDisplay }
|
||||
?.tip
|
||||
}
|
||||
}
|
@ -1,74 +0,0 @@
|
||||
/* 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.home.tips
|
||||
|
||||
import android.view.View
|
||||
import androidx.core.view.isVisible
|
||||
import org.mozilla.fenix.BrowserDirection
|
||||
import org.mozilla.fenix.HomeActivity
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.components.tips.Tip
|
||||
import org.mozilla.fenix.components.tips.TipType
|
||||
import org.mozilla.fenix.databinding.ButtonTipItemBinding
|
||||
import org.mozilla.fenix.ext.addUnderline
|
||||
import org.mozilla.fenix.ext.components
|
||||
import org.mozilla.fenix.home.sessioncontrol.SessionControlInteractor
|
||||
import org.mozilla.fenix.utils.Settings
|
||||
import org.mozilla.fenix.utils.view.ViewHolder
|
||||
|
||||
class ButtonTipViewHolder(
|
||||
private val view: View,
|
||||
private val interactor: SessionControlInteractor,
|
||||
private val settings: Settings = view.context.components.settings
|
||||
) : ViewHolder(view) {
|
||||
|
||||
var tip: Tip? = null
|
||||
|
||||
fun bind(tip: Tip) {
|
||||
val binding = ButtonTipItemBinding.bind(view)
|
||||
require(tip.type is TipType.Button)
|
||||
|
||||
this.tip = tip
|
||||
|
||||
with(binding) {
|
||||
tipHeaderText.text = tip.title
|
||||
tip.titleDrawable?.let {
|
||||
tipHeaderText.setCompoundDrawablesWithIntrinsicBounds(it, null, null, null)
|
||||
}
|
||||
tipDescriptionText.text = tip.description
|
||||
tipButton.text = tip.type.text
|
||||
|
||||
tipLearnMore.isVisible = tip.learnMoreURL != null
|
||||
if (tip.learnMoreURL != null) {
|
||||
tipLearnMore.addUnderline()
|
||||
|
||||
tipLearnMore.setOnClickListener {
|
||||
(itemView.context as HomeActivity).openToBrowserAndLoad(
|
||||
searchTermOrURL = tip.learnMoreURL,
|
||||
newTab = true,
|
||||
from = BrowserDirection.FromHome
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
tipButton.setOnClickListener {
|
||||
tip.type.action.invoke()
|
||||
}
|
||||
|
||||
tipClose.setOnClickListener {
|
||||
settings.preferences
|
||||
.edit()
|
||||
.putBoolean(tip.identifier, false)
|
||||
.apply()
|
||||
|
||||
interactor.onCloseTip(tip)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val LAYOUT_ID = R.layout.button_tip_item
|
||||
}
|
||||
}
|
@ -1,83 +0,0 @@
|
||||
<?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/. -->
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/tip_card"
|
||||
style="@style/OnboardingCardLight"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="@dimen/home_item_horizontal_margin"
|
||||
android:background="@drawable/cfr_background_gradient">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tip_header_text"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="16dp"
|
||||
android:drawablePadding="12dp"
|
||||
android:gravity="center_vertical"
|
||||
android:lineSpacingExtra="2dp"
|
||||
android:maxLines="2"
|
||||
android:textAppearance="@style/HeaderTextStyle"
|
||||
android:textColor="@color/photonLightGrey05"
|
||||
app:drawableTint="@color/photonLightGrey05"
|
||||
app:layout_constraintEnd_toStartOf="@id/tip_close"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="Header text" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/tip_close"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:contentDescription="@string/create_collection_close"
|
||||
app:tint="@color/photonLightGrey05"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:srcCompat="@drawable/ic_close" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tip_description_text"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:lineSpacingExtra="2dp"
|
||||
android:textAppearance="@style/Body14TextStyle"
|
||||
android:textColor="@color/photonLightGrey05"
|
||||
app:layout_constraintEnd_toStartOf="@id/tip_close"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/tip_header_text"
|
||||
tools:text="Tip description" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tip_learn_more"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/search_suggestions_onboarding_learn_more_link"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:textColor="@color/photonLightGrey05"
|
||||
app:layout_constraintEnd_toEndOf="@id/tip_description_text"
|
||||
app:layout_constraintStart_toStartOf="@id/tip_description_text"
|
||||
app:layout_constraintTop_toBottomOf="@id/tip_description_text"
|
||||
tools:textColor="@color/accent_high_contrast_private_theme" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/tip_button"
|
||||
style="@style/NeutralButton"
|
||||
android:layout_height="36dp"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
app:backgroundTint="@color/photonLightGrey20"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/tip_learn_more"
|
||||
tools:text="Call to action" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -1,46 +0,0 @@
|
||||
/* 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.components.tips
|
||||
|
||||
import io.mockk.mockk
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertNull
|
||||
import org.junit.Test
|
||||
|
||||
class TipManagerTest {
|
||||
@Test
|
||||
fun `test first with shouldDisplay`() {
|
||||
val shouldDisplayProvider = object : TipProvider {
|
||||
override val tip = mockk<Tip>()
|
||||
override val shouldDisplay = true
|
||||
}
|
||||
val shouldNotDisplayProvider = object : TipProvider {
|
||||
override val tip = mockk<Tip>()
|
||||
override val shouldDisplay = false
|
||||
}
|
||||
val manager = FenixTipManager(listOf(shouldNotDisplayProvider, shouldDisplayProvider))
|
||||
assertEquals(shouldDisplayProvider.tip, manager.getTip())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test first with shouldDisplay even if tip is null`() {
|
||||
val shouldDisplayProvider = object : TipProvider {
|
||||
override val tip: Tip? = null
|
||||
override val shouldDisplay = true
|
||||
}
|
||||
val shouldNotDisplayProvider = object : TipProvider {
|
||||
override val tip = mockk<Tip>()
|
||||
override val shouldDisplay = false
|
||||
}
|
||||
val manager = FenixTipManager(listOf(shouldNotDisplayProvider, shouldDisplayProvider))
|
||||
assertEquals(shouldDisplayProvider.tip, manager.getTip())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test returns null with empty list`() {
|
||||
val manager = FenixTipManager(emptyList())
|
||||
assertNull(manager.getTip())
|
||||
}
|
||||
}
|
@ -1,125 +0,0 @@
|
||||
/* 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.home.tips
|
||||
|
||||
import android.content.SharedPreferences
|
||||
import android.view.LayoutInflater
|
||||
import androidx.core.view.isGone
|
||||
import androidx.core.view.isVisible
|
||||
import io.mockk.MockKAnnotations
|
||||
import io.mockk.Runs
|
||||
import io.mockk.every
|
||||
import io.mockk.impl.annotations.MockK
|
||||
import io.mockk.just
|
||||
import io.mockk.mockk
|
||||
import io.mockk.spyk
|
||||
import io.mockk.verify
|
||||
import mozilla.components.support.test.robolectric.testContext
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mozilla.fenix.BrowserDirection
|
||||
import org.mozilla.fenix.HomeActivity
|
||||
import org.mozilla.fenix.components.tips.Tip
|
||||
import org.mozilla.fenix.components.tips.TipType
|
||||
import org.mozilla.fenix.databinding.ButtonTipItemBinding
|
||||
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
|
||||
import org.mozilla.fenix.home.sessioncontrol.SessionControlInteractor
|
||||
import org.mozilla.fenix.utils.Settings
|
||||
|
||||
@RunWith(FenixRobolectricTestRunner::class)
|
||||
class ButtonTipViewHolderTest {
|
||||
|
||||
@MockK private lateinit var activity: HomeActivity
|
||||
@MockK private lateinit var interactor: SessionControlInteractor
|
||||
@MockK private lateinit var settings: Settings
|
||||
@MockK private lateinit var sharedPrefs: SharedPreferences
|
||||
@MockK private lateinit var sharedPrefsEditor: SharedPreferences.Editor
|
||||
private lateinit var viewHolder: ButtonTipViewHolder
|
||||
private lateinit var binding: ButtonTipItemBinding
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
MockKAnnotations.init(this)
|
||||
val view = spyk(
|
||||
LayoutInflater.from(testContext)
|
||||
.inflate(ButtonTipViewHolder.LAYOUT_ID, null)
|
||||
)
|
||||
|
||||
viewHolder = ButtonTipViewHolder(view, interactor, settings)
|
||||
binding = ButtonTipItemBinding.bind(view)
|
||||
every { view.context } returns activity
|
||||
every { activity.openToBrowserAndLoad(any(), any(), any()) } just Runs
|
||||
every { interactor.onCloseTip(any()) } just Runs
|
||||
every { settings.preferences } returns sharedPrefs
|
||||
every { sharedPrefs.edit() } returns sharedPrefsEditor
|
||||
every { sharedPrefsEditor.putBoolean(any(), any()) } returns sharedPrefsEditor
|
||||
every { sharedPrefsEditor.apply() } just Runs
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `text is displayed based on given tip`() {
|
||||
viewHolder.bind(defaultTip())
|
||||
|
||||
assertEquals("Tip Title", binding.tipHeaderText.text)
|
||||
assertEquals("Tip description", binding.tipDescriptionText.text)
|
||||
assertEquals("button", binding.tipButton.text)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `learn more is hidden if learnMoreURL is null`() {
|
||||
viewHolder.bind(defaultTip(learnMoreUrl = null))
|
||||
|
||||
assertTrue(binding.tipLearnMore.isGone)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `learn more is visible if learnMoreURL is not null`() {
|
||||
viewHolder.bind(defaultTip(learnMoreUrl = "https://learnmore.com"))
|
||||
|
||||
assertTrue(binding.tipLearnMore.isVisible)
|
||||
|
||||
binding.tipLearnMore.performClick()
|
||||
verify {
|
||||
activity.openToBrowserAndLoad(
|
||||
searchTermOrURL = "https://learnmore.com",
|
||||
newTab = true,
|
||||
from = BrowserDirection.FromHome
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `tip button invokes tip action`() {
|
||||
val action = mockk<() -> Unit>(relaxed = true)
|
||||
viewHolder.bind(defaultTip(action))
|
||||
|
||||
binding.tipButton.performClick()
|
||||
verify { action() }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `close button invokes onCloseTip`() {
|
||||
val tip = defaultTip()
|
||||
viewHolder.bind(tip)
|
||||
|
||||
binding.tipClose.performClick()
|
||||
verify { interactor.onCloseTip(tip) }
|
||||
verify { sharedPrefsEditor.putBoolean("tipIdentifier", false) }
|
||||
}
|
||||
|
||||
private fun defaultTip(
|
||||
action: () -> Unit = mockk(),
|
||||
learnMoreUrl: String? = null
|
||||
) = Tip(
|
||||
type = TipType.Button("button", action),
|
||||
identifier = "tipIdentifier",
|
||||
title = "Tip Title",
|
||||
description = "Tip description",
|
||||
learnMoreURL = learnMoreUrl
|
||||
)
|
||||
}
|
Loading…
Reference in New Issue