1
0
Fork 0

Add helper for underlining text (#12520)

master
Tiger Oakes 2020-07-15 22:38:46 -07:00 committed by GitHub
parent a0491b702e
commit d4bb432e24
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 152 additions and 45 deletions

View File

@ -0,0 +1,19 @@
/* 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.ext
import android.text.style.UnderlineSpan
import android.widget.TextView
import androidx.core.text.toSpannable
/**
* Adds an underline effect to the text displayed in the TextView.
*/
fun TextView.addUnderline() {
val currentText = text
text = currentText.toSpannable().apply {
setSpan(UnderlineSpan(), 0, currentText.length, 0)
}
}

View File

@ -4,13 +4,12 @@
package org.mozilla.fenix.home.sessioncontrol.viewholders package org.mozilla.fenix.home.sessioncontrol.viewholders
import android.text.SpannableString
import android.text.method.LinkMovementMethod import android.text.method.LinkMovementMethod
import android.text.style.UnderlineSpan
import android.view.View import android.view.View
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.synthetic.main.private_browsing_description.view.* import kotlinx.android.synthetic.main.private_browsing_description.view.*
import org.mozilla.fenix.R import org.mozilla.fenix.R
import org.mozilla.fenix.ext.addUnderline
import org.mozilla.fenix.home.sessioncontrol.TabSessionInteractor import org.mozilla.fenix.home.sessioncontrol.TabSessionInteractor
class PrivateBrowsingDescriptionViewHolder( class PrivateBrowsingDescriptionViewHolder(
@ -24,13 +23,9 @@ class PrivateBrowsingDescriptionViewHolder(
view.private_session_description.text = resources.getString( view.private_session_description.text = resources.getString(
R.string.private_browsing_placeholder_description_2, appName R.string.private_browsing_placeholder_description_2, appName
) )
val commonMythsText = view.private_session_common_myths.text.toString()
val textWithLink = SpannableString(commonMythsText).apply {
setSpan(UnderlineSpan(), 0, commonMythsText.length, 0)
}
with(view.private_session_common_myths) { with(view.private_session_common_myths) {
movementMethod = LinkMovementMethod.getInstance() movementMethod = LinkMovementMethod.getInstance()
text = textWithLink addUnderline()
setOnClickListener { setOnClickListener {
interactor.onPrivateBrowsingLearnMoreClicked() interactor.onPrivateBrowsingLearnMoreClicked()
} }

View File

@ -6,8 +6,8 @@ package org.mozilla.fenix.home.sessioncontrol.viewholders.onboarding
import android.widget.TextView import android.widget.TextView
import androidx.annotation.DrawableRes import androidx.annotation.DrawableRes
import androidx.appcompat.content.res.AppCompatResources
import mozilla.components.support.ktx.android.content.getColorFromAttr import mozilla.components.support.ktx.android.content.getColorFromAttr
import mozilla.components.support.ktx.android.content.getDrawableWithTint
import mozilla.components.support.ktx.android.view.putCompoundDrawablesRelative import mozilla.components.support.ktx.android.view.putCompoundDrawablesRelative
import org.mozilla.fenix.R import org.mozilla.fenix.R
import org.mozilla.fenix.ext.setBounds import org.mozilla.fenix.ext.setBounds
@ -16,9 +16,9 @@ import org.mozilla.fenix.ext.setBounds
* Sets the drawableStart of a header in an onboarding card. * Sets the drawableStart of a header in an onboarding card.
*/ */
fun TextView.setOnboardingIcon(@DrawableRes id: Int) { fun TextView.setOnboardingIcon(@DrawableRes id: Int) {
val icon = AppCompatResources.getDrawable(context, id) val icon = context.getDrawableWithTint(id, context.getColorFromAttr(R.attr.onboardingSelected))?.apply {
val size = context.resources.getDimensionPixelSize(R.dimen.onboarding_header_icon_height_width) val size = context.resources.getDimensionPixelSize(R.dimen.onboarding_header_icon_height_width)
icon?.setBounds(size) setBounds(size)
icon?.setTint(context.getColorFromAttr(R.attr.onboardingSelected)) }
putCompoundDrawablesRelative(start = icon) putCompoundDrawablesRelative(start = icon)
} }

View File

@ -5,11 +5,11 @@
package org.mozilla.fenix.home.sessioncontrol.viewholders.onboarding package org.mozilla.fenix.home.sessioncontrol.viewholders.onboarding
import android.view.View import android.view.View
import androidx.appcompat.content.res.AppCompatResources
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.navigation.Navigation import androidx.navigation.Navigation
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.synthetic.main.onboarding_manual_signin.view.* import kotlinx.android.synthetic.main.onboarding_manual_signin.view.*
import mozilla.components.support.ktx.android.content.getDrawableWithTint
import mozilla.components.support.ktx.android.view.putCompoundDrawablesRelativeWithIntrinsicBounds import mozilla.components.support.ktx.android.view.putCompoundDrawablesRelativeWithIntrinsicBounds
import org.mozilla.fenix.R import org.mozilla.fenix.R
import org.mozilla.fenix.components.metrics.Event import org.mozilla.fenix.components.metrics.Event
@ -34,8 +34,10 @@ class OnboardingManualSignInViewHolder(view: View) : RecyclerView.ViewHolder(vie
val appName = context.getString(R.string.app_name) val appName = context.getString(R.string.app_name)
headerText.text = context.getString(R.string.onboarding_firefox_account_header, appName) headerText.text = context.getString(R.string.onboarding_firefox_account_header, appName)
val icon = AppCompatResources.getDrawable(context, R.drawable.ic_onboarding_firefox_accounts) val icon = context.getDrawableWithTint(
icon?.setTint(ContextCompat.getColor(context, R.color.white_color)) R.drawable.ic_onboarding_firefox_accounts,
ContextCompat.getColor(context, R.color.white_color)
)
headerText.putCompoundDrawablesRelativeWithIntrinsicBounds(start = icon) headerText.putCompoundDrawablesRelativeWithIntrinsicBounds(start = icon)
} }

View File

@ -4,13 +4,12 @@
package org.mozilla.fenix.home.sessioncontrol.viewholders.onboarding package org.mozilla.fenix.home.sessioncontrol.viewholders.onboarding
import android.text.SpannableString
import android.text.style.UnderlineSpan
import android.view.View import android.view.View
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.synthetic.main.onboarding_whats_new.view.* import kotlinx.android.synthetic.main.onboarding_whats_new.view.*
import org.mozilla.fenix.R import org.mozilla.fenix.R
import org.mozilla.fenix.components.metrics.Event import org.mozilla.fenix.components.metrics.Event
import org.mozilla.fenix.ext.addUnderline
import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.components
import org.mozilla.fenix.home.sessioncontrol.OnboardingInteractor import org.mozilla.fenix.home.sessioncontrol.OnboardingInteractor
@ -25,12 +24,7 @@ class OnboardingWhatsNewViewHolder(
val appName = view.context.getString(R.string.app_name) val appName = view.context.getString(R.string.app_name)
view.description_text.text = view.context.getString(R.string.onboarding_whats_new_description, appName) view.description_text.text = view.context.getString(R.string.onboarding_whats_new_description, appName)
val getAnswersText = view.get_answers.text.toString() view.get_answers.addUnderline()
val textWithLink = SpannableString(getAnswersText).apply {
setSpan(UnderlineSpan(), 0, getAnswersText.length, 0)
}
view.get_answers.text = textWithLink
view.get_answers.setOnClickListener { view.get_answers.setOnClickListener {
interactor.onWhatsNewGetAnswersClicked() interactor.onWhatsNewGetAnswersClicked()
view.context.components.analytics.metrics.track(Event.OnboardingWhatsNew) view.context.components.analytics.metrics.track(Event.OnboardingWhatsNew)

View File

@ -1,7 +1,5 @@
package org.mozilla.fenix.home.tips package org.mozilla.fenix.home.tips
import android.text.SpannableString
import android.text.style.UnderlineSpan
import android.view.View import android.view.View
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.synthetic.main.button_tip_item.view.* import kotlinx.android.synthetic.main.button_tip_item.view.*
@ -11,6 +9,7 @@ import org.mozilla.fenix.R
import org.mozilla.fenix.components.metrics.Event import org.mozilla.fenix.components.metrics.Event
import org.mozilla.fenix.components.tips.Tip import org.mozilla.fenix.components.tips.Tip
import org.mozilla.fenix.components.tips.TipType import org.mozilla.fenix.components.tips.TipType
import org.mozilla.fenix.ext.addUnderline
import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.settings import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.home.sessioncontrol.SessionControlInteractor import org.mozilla.fenix.home.sessioncontrol.SessionControlInteractor
@ -36,12 +35,7 @@ class ButtonTipViewHolder(
if (tip.learnMoreURL == null) { if (tip.learnMoreURL == null) {
tip_learn_more.visibility = View.GONE tip_learn_more.visibility = View.GONE
} else { } else {
val learnMoreText = context.getString(R.string.search_suggestions_onboarding_learn_more_link) tip_learn_more.addUnderline()
val textWithLink = SpannableString(learnMoreText).apply {
setSpan(UnderlineSpan(), 0, learnMoreText.length, 0)
}
tip_learn_more.text = textWithLink
tip_learn_more.setOnClickListener { tip_learn_more.setOnClickListener {
(context as HomeActivity).openToBrowserAndLoad( (context as HomeActivity).openToBrowserAndLoad(

View File

@ -4,9 +4,7 @@
package org.mozilla.fenix.settings.logins package org.mozilla.fenix.settings.logins
import android.text.SpannableString
import android.text.method.LinkMovementMethod import android.text.method.LinkMovementMethod
import android.text.style.UnderlineSpan
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.FrameLayout import android.widget.FrameLayout
@ -14,8 +12,8 @@ import androidx.core.view.isVisible
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import kotlinx.android.extensions.LayoutContainer import kotlinx.android.extensions.LayoutContainer
import kotlinx.android.synthetic.main.component_saved_logins.view.* import kotlinx.android.synthetic.main.component_saved_logins.view.*
import kotlinx.android.synthetic.main.component_saved_logins.view.progress_bar
import org.mozilla.fenix.R import org.mozilla.fenix.R
import org.mozilla.fenix.ext.addUnderline
import org.mozilla.fenix.utils.Settings import org.mozilla.fenix.utils.Settings
/** /**
@ -39,13 +37,9 @@ class SavedLoginsView(
itemAnimator = null itemAnimator = null
} }
val learnMoreText = view.saved_passwords_empty_learn_more.text.toString()
val textWithLink = SpannableString(learnMoreText).apply {
setSpan(UnderlineSpan(), 0, learnMoreText.length, 0)
}
with(view.saved_passwords_empty_learn_more) { with(view.saved_passwords_empty_learn_more) {
movementMethod = LinkMovementMethod.getInstance() movementMethod = LinkMovementMethod.getInstance()
text = textWithLink addUnderline()
setOnClickListener { interactor.onLearnMore() } setOnClickListener { interactor.onLearnMore() }
} }

View File

@ -5,17 +5,16 @@
package org.mozilla.fenix.trackingprotectionexceptions package org.mozilla.fenix.trackingprotectionexceptions
import android.text.method.LinkMovementMethod import android.text.method.LinkMovementMethod
import android.text.style.UnderlineSpan
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.FrameLayout import android.widget.FrameLayout
import androidx.core.text.toSpannable
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import kotlinx.android.extensions.LayoutContainer import kotlinx.android.extensions.LayoutContainer
import kotlinx.android.synthetic.main.component_exceptions.* import kotlinx.android.synthetic.main.component_exceptions.*
import mozilla.components.concept.engine.content.blocking.TrackingProtectionException import mozilla.components.concept.engine.content.blocking.TrackingProtectionException
import org.mozilla.fenix.R import org.mozilla.fenix.R
import org.mozilla.fenix.ext.addUnderline
/** /**
* Interface for the ExceptionsViewInteractor. This interface is implemented by objects that want * Interface for the ExceptionsViewInteractor. This interface is implemented by objects that want
@ -62,10 +61,7 @@ class ExceptionsView(
} }
with(exceptions_learn_more) { with(exceptions_learn_more) {
val learnMoreText = text addUnderline()
text = learnMoreText.toSpannable().apply {
setSpan(UnderlineSpan(), 0, learnMoreText.length, 0)
}
movementMethod = LinkMovementMethod.getInstance() movementMethod = LinkMovementMethod.getInstance()
setOnClickListener { interactor.onLearnMore() } setOnClickListener { interactor.onLearnMore() }

View File

@ -0,0 +1,39 @@
/* 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.sessioncontrol.viewholders
import android.view.LayoutInflater
import android.view.View
import io.mockk.mockk
import io.mockk.verify
import kotlinx.android.synthetic.main.private_browsing_description.view.*
import mozilla.components.support.test.robolectric.testContext
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
import org.mozilla.fenix.home.sessioncontrol.TabSessionInteractor
@RunWith(FenixRobolectricTestRunner::class)
class PrivateBrowsingDescriptionViewHolderTest {
private lateinit var view: View
private lateinit var interactor: TabSessionInteractor
@Before
fun setup() {
view = LayoutInflater.from(testContext)
.inflate(PrivateBrowsingDescriptionViewHolder.LAYOUT_ID, null)
interactor = mockk(relaxed = true)
}
@Test
fun `call interactor on click`() {
PrivateBrowsingDescriptionViewHolder(view, interactor)
view.private_session_common_myths.performClick()
verify { interactor.onPrivateBrowsingLearnMoreClicked() }
}
}

View File

@ -0,0 +1,74 @@
/* 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.sessioncontrol.viewholders.onboarding
import android.content.res.Resources
import android.text.Spanned
import android.view.LayoutInflater
import android.view.View
import androidx.core.text.HtmlCompat
import androidx.core.text.HtmlCompat.TO_HTML_PARAGRAPH_LINES_CONSECUTIVE
import io.mockk.every
import io.mockk.mockk
import io.mockk.mockkStatic
import io.mockk.unmockkStatic
import io.mockk.verify
import kotlinx.android.synthetic.main.onboarding_whats_new.view.*
import mozilla.components.support.ktx.android.content.res.resolveAttribute
import mozilla.components.support.test.robolectric.testContext
import org.junit.After
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.R
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
import org.mozilla.fenix.home.sessioncontrol.OnboardingInteractor
@RunWith(FenixRobolectricTestRunner::class)
class OnboardingWhatsNewViewHolderTest {
private lateinit var view: View
private lateinit var interactor: OnboardingInteractor
@Before
fun setup() {
mockkStatic("mozilla.components.support.ktx.android.content.res.ThemeKt")
view = LayoutInflater.from(testContext)
.inflate(OnboardingWhatsNewViewHolder.LAYOUT_ID, null)
interactor = mockk(relaxed = true)
every {
any<Resources.Theme>().resolveAttribute(R.attr.onboardingSelected)
} returns R.color.onboarding_illustration_selected_normal_theme
}
@After
fun teardown() {
unmockkStatic("mozilla.components.support.ktx.android.content.res.ThemeKt")
}
@Test
fun `sets and styles strings`() {
OnboardingWhatsNewViewHolder(view, interactor)
assertEquals(
"Have questions about the redesigned Firefox Preview? Want to know whats changed?",
view.description_text.text
)
val getAnswersHtml = HtmlCompat.toHtml(view.get_answers.text as Spanned, TO_HTML_PARAGRAPH_LINES_CONSECUTIVE)
assertTrue(getAnswersHtml, "<u>Get answers here</u>" in getAnswersHtml)
}
@Test
fun `call interactor on click`() {
OnboardingWhatsNewViewHolder(view, interactor)
view.get_answers.performClick()
verify { interactor.onWhatsNewGetAnswersClicked() }
}
}