Bug 1840110 - Move LinkText to compose package

fenix/118.0
Alexandru2909 10 months ago committed by mergify[bot]
parent e234281893
commit 5395036521

@ -29,6 +29,7 @@ import org.mozilla.fenix.theme.FirefoxTheme
* @param clickableEndIndex [text] index at which the URL substring ends.
* @param onClick Callback to be invoked only when the URL substring is clicked.
*/
@Deprecated("Use LinkText instead", ReplaceWith("LinkText", "org.mozilla.fenix.compose.LinkText"))
@Composable
fun ClickableSubstringLink(
text: String,
@ -86,6 +87,7 @@ fun ClickableSubstringLink(
}
@Composable
@Suppress("Deprecation")
@Preview
private fun ClickableSubstringTextPreview() {
val text = "This text contains a link"

@ -0,0 +1,129 @@
/* 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.compose
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.text.ClickableText
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import mozilla.components.support.ktx.android.content.isScreenReaderEnabled
import org.mozilla.fenix.theme.FirefoxTheme
/**
* The tag used for links in the text for annotated strings.
*/
private const val URL_TAG = "URL_TAG"
/**
* Model containing link text, url and action.
*
* @property text Substring of the text passed to [LinkText] to be displayed as clickable link.
* @property url Url the link should point to.
* @property onClick Callback to be invoked when link is clicked.
*/
data class LinkTextState(
val text: String,
val url: String,
val onClick: (String) -> Unit,
)
/**
* A composable for displaying text that contains a clickable link text.
*
* @param text The complete text.
* @param linkTextState The clickable part of the text.
*/
@Composable
fun LinkText(
text: String,
linkTextState: LinkTextState,
) {
val context = LocalContext.current
val annotatedString = buildAnnotatedString {
val startIndex = text.indexOf(linkTextState.text, ignoreCase = true)
val endIndex = startIndex + linkTextState.text.length
append(text)
addStyle(
style = SpanStyle(color = FirefoxTheme.colors.textAccent),
start = startIndex,
end = endIndex,
)
addStringAnnotation(
tag = URL_TAG,
annotation = linkTextState.url,
start = startIndex,
end = endIndex,
)
}
// When using UrlAnnotation, talkback shows links in a separate dialog and
// opens them in the default browser. Since this component allows the caller to define the
// onClick behaviour - e.g. to open the link in in-app custom tab, here StringAnnotation is used
// and modifier is enabled with Role.Button when screen reader is enabled.
ClickableText(
text = annotatedString,
style = FirefoxTheme.typography.body2.copy(
textAlign = TextAlign.Center,
color = FirefoxTheme.colors.textSecondary,
),
modifier = Modifier.clickable(
enabled = context.isScreenReaderEnabled,
role = Role.Button,
onClickLabel = linkTextState.text,
onClick = { linkTextState.onClick(linkTextState.url) },
),
onClick = {
if (!context.isScreenReaderEnabled) {
val range: AnnotatedString.Range<String>? =
annotatedString.getStringAnnotations(URL_TAG, it, it).firstOrNull()
range?.let { stringAnnotation ->
linkTextState.onClick(stringAnnotation.item)
}
}
},
)
}
@Preview
@Composable
private fun LinkTextEndPreview() {
val state = LinkTextState(
text = "click here",
url = "www.mozilla.com",
onClick = {},
)
FirefoxTheme {
Box(modifier = Modifier.background(color = FirefoxTheme.colors.layer1)) {
LinkText(text = "This is normal text, click here", linkTextState = state)
}
}
}
@Preview
@Composable
private fun LinkTextMiddlePreview() {
val state = LinkTextState(
text = "clickable text",
url = "www.mozilla.com",
onClick = {},
)
FirefoxTheme {
Box(modifier = Modifier.background(color = FirefoxTheme.colors.layer1)) {
LinkText(text = "This is clickable text, followed by normal text", linkTextState = state)
}
}
}

@ -507,6 +507,7 @@ fun PocketStoriesCategories(
* @param linkTextColor [Color] of the link text.
*/
@OptIn(ExperimentalComposeUiApi::class)
@Suppress("Deprecation")
@Composable
fun PoweredByPocketHeader(
onLearnMoreClicked: (String) -> Unit,

@ -5,6 +5,7 @@
package org.mozilla.fenix.onboarding.view
import androidx.compose.ui.layout.ContentScale
import org.mozilla.fenix.compose.LinkTextState
import org.mozilla.fenix.nimbus.OnboardingCardData
import org.mozilla.fenix.nimbus.OnboardingCardType
import org.mozilla.fenix.settings.SupportUtils

@ -6,7 +6,6 @@ package org.mozilla.fenix.onboarding.view
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.BoxWithConstraints
import androidx.compose.foundation.layout.BoxWithConstraintsScope
@ -16,7 +15,6 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.text.ClickableText
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.Icon
import androidx.compose.material.IconButton
@ -28,18 +26,14 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import mozilla.components.support.ktx.android.content.isScreenReaderEnabled
import org.mozilla.fenix.R
import org.mozilla.fenix.compose.LinkText
import org.mozilla.fenix.compose.LinkTextState
import org.mozilla.fenix.compose.annotation.LightDarkPreview
import org.mozilla.fenix.compose.button.PrimaryButton
import org.mozilla.fenix.compose.button.SecondaryButton
@ -62,11 +56,6 @@ private const val IMAGE_HEIGHT_RATIO_MEDIUM = 0.36f
*/
private const val IMAGE_HEIGHT_RATIO_SMALL = 0.28f
/**
* The tag used for links in the text for annotated strings.
*/
private const val URL_TAG = "URL_TAG"
/**
* A composable for displaying onboarding page content.
*
@ -190,64 +179,6 @@ private fun DescriptionText(
}
}
/**
* A composable for displaying text that contains a clickable link text.
*
* @param text The complete text.
* @param linkTextState The clickable part of the text.
*/
@Composable
private fun LinkText(
text: String,
linkTextState: LinkTextState,
) {
val context = LocalContext.current
val annotatedString = buildAnnotatedString {
val startIndex = text.indexOf(linkTextState.text, ignoreCase = true)
val endIndex = startIndex + linkTextState.text.length
append(text)
addStyle(
style = SpanStyle(color = FirefoxTheme.colors.textAccent),
start = startIndex,
end = endIndex,
)
addStringAnnotation(
tag = URL_TAG,
annotation = linkTextState.url,
start = startIndex,
end = endIndex,
)
}
// When using UrlAnnotation, talkback shows links in a separate dialog and
// opens them in the default browser. Since this component allows the caller to define the
// onClick behaviour - e.g. to open the link in in-app custom tab, here StringAnnotation is used
// and modifier is enabled with Role.Button when screen reader is enabled.
ClickableText(
text = annotatedString,
style = FirefoxTheme.typography.body2.copy(
textAlign = TextAlign.Center,
color = FirefoxTheme.colors.textSecondary,
),
modifier = Modifier.clickable(
enabled = context.isScreenReaderEnabled,
role = Role.Button,
onClickLabel = linkTextState.text,
onClick = { linkTextState.onClick(linkTextState.url) },
),
onClick = {
if (!context.isScreenReaderEnabled) {
val range: AnnotatedString.Range<String>? =
annotatedString.getStringAnnotations(URL_TAG, it, it).firstOrNull()
range?.let { stringAnnotation ->
linkTextState.onClick(stringAnnotation.item)
}
}
},
)
}
/**
* Calculates the image height to be set. The ratio is selected based on parent height.
*/

@ -5,6 +5,7 @@
package org.mozilla.fenix.onboarding.view
import androidx.annotation.DrawableRes
import org.mozilla.fenix.compose.LinkTextState
/**
* Model containing data for [OnboardingPage].
@ -27,15 +28,6 @@ data class OnboardingPageState(
val onRecordImpressionEvent: () -> Unit = {},
)
/**
* Model containing link text, url and action.
*/
data class LinkTextState(
val text: String,
val url: String,
val onClick: (String) -> Unit,
)
/**
* Model containing text and action for a button.
*/

@ -113,6 +113,7 @@ fun WallpaperSettings(
}
@Composable
@Suppress("Deprecation")
private fun WallpaperGroupHeading(
collection: Wallpaper.Collection,
onLearnMoreClick: (String, String) -> Unit,

@ -320,6 +320,7 @@ private fun SettingsCard(
}
}
@Suppress("Deprecation")
@Composable
private fun ReviewQualityInfo(
modifier: Modifier = Modifier,

@ -8,6 +8,7 @@ import androidx.compose.ui.layout.ContentScale
import org.junit.Assert.assertEquals
import org.junit.Test
import org.mozilla.fenix.R
import org.mozilla.fenix.compose.LinkTextState
import org.mozilla.fenix.settings.SupportUtils
class JunoOnboardingMapperTest {

Loading…
Cancel
Save