Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .idea/codeInsightSettings.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ package com.adevinta.spark.catalog.examples.samples.text
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.SnackbarDuration
import androidx.compose.material3.Text
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
Expand All @@ -38,6 +39,7 @@ import com.adevinta.spark.components.text.TextLinkButton
import com.adevinta.spark.icons.Link
import com.adevinta.spark.icons.SparkIcons
import com.adevinta.spark.res.annotatedStringResource
import kotlinx.collections.immutable.persistentMapOf
import kotlinx.coroutines.launch

private const val TextLinksExampleSourceUrl = "$SampleSourceUrl/TextLinkExamples.kt"
Expand All @@ -50,28 +52,35 @@ public val TextLinksExamples: List<Example> = listOf(
sourceUrl = TextLinksExampleSourceUrl,
) { snackbarHostState ->
val scope = rememberCoroutineScope()
Box(
contentAlignment = Alignment.Center,
modifier = Modifier.fillMaxSize(),
) {

TextLink(
style = SparkTheme.typography.subhead,
text = annotatedStringResource(id = R.string.spark_text_link_short_example_),
lineHeight = 40.sp,
onClickLabel = "Aller au site web",
onClick = {
scope.launch {
snackbarHostState.showSnackbar(
message = "https://kotlinlang.org",
actionLabel = "Action",
duration = SnackbarDuration.Short,
intent = SnackbarIntent.Success,
)
}
},
)
}
TextLink(
style = SparkTheme.typography.subhead,
text = annotatedStringResource(id = R.string.spark_text_link_short_example_),
lineHeight = 40.sp,
onClickLabel = "Aller au site web",
onClick = {
scope.launch {
snackbarHostState.showSnackbar(
message = "https://kotlinlang.org",
actionLabel = "Action",
duration = SnackbarDuration.Short,
intent = SnackbarIntent.Success,
)
}
},
)
Text(
text = annotatedStringResource(
com.adevinta.spark.R.string.spark_annotatedStringResource_test_args,
persistentMapOf("who" to "Bob"),
),
)
Text(
text = annotatedStringResource(
com.adevinta.spark.R.string.spark_annotatedStringResource_test_new_args,
"Bob",
),
)
},
Example(
id = "paragraph",
Expand Down
4 changes: 2 additions & 2 deletions catalog/src/main/res/values-fr/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -127,9 +127,9 @@

<string name="icons_screen_search_helper">Rechercher une icΓ΄ne Spark</string>

<string name="spark_text_link_paragraph_example_"><annotation color="neutral" typography="body1">Ceci est la </annotation><annotation color="main" typography="body1"><u><b>Politique de confidentialitΓ©</b></u></annotation><annotation color="neutral" typography="body1">d’Adevinta ainsi que de nombreuses informations supplΓ©mentaires qui pourraient vous intΓ©resser ou dont je devrais vous informer et que vous ignorez peut-Γͺtre</annotation></string>
<string name="spark_text_link_paragraph_example_">&lt;annotation color="neutral" typography="body1">Ceci est la &lt;/annotation>&lt;annotation color="main" typography="body1">&lt;u>&lt;b>Politique de confidentialitΓ©&lt;/b>&lt;/u>&lt;/annotation>&lt;annotation color="neutral" typography="body1">d’Adevinta ainsi que de nombreuses informations supplΓ©mentaires qui pourraient vous intΓ©resser ou dont je devrais vous informer et que vous ignorez peut-Γͺtre&lt;/annotation></string>

<string name="spark_text_link_short_example_"><annotation color="neutral" typography="display2">Apprendre la programmation Kotlin </annotation><annotation color="success" typography="display3"><u><b>https://kotlinlang.org</b></u></annotation></string>
<string name="spark_text_link_short_example_">&lt;annotation color="neutral" typography="display2">Apprendre la programmation Kotlin &lt;/annotation>&lt;annotation color="success" typography="display3">&lt;u>&lt;b>https://kotlinlang.org&lt;/b>&lt;/u>&lt;/annotation></string>

<!--region Divider-->
<string name="component_divider_description">Le composant Divider/SΓ©parateur fournit une ligne fine et discrΓ¨te qui sΓ©pare et distingue les sections de contenu afin de renforcer la hiΓ©rarchie visuelle.\\u2028Voici quelques utilisations courantes:\nSΓ©parer les sections sur une page.\nSΓ©parer les Γ©lΓ©ments d’une liste.\nCrΓ©er un contraste visuel entre les deux cΓ΄tΓ©s d’une page.</string>
Expand Down
4 changes: 2 additions & 2 deletions catalog/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -128,9 +128,9 @@

<string name="icons_screen_search_helper">Search Spark Icon</string>

<string name="spark_text_link_paragraph_example_"><annotation color="neutral" typography="body1">This is Adevinta </annotation><annotation color="main" typography="body1"><u><b>Privacy &amp; Policy</b></u></annotation><annotation color="neutral" typography="body1"> also lots of extra information you may be interested in or should I inform you about that extra information. you might not be aware of it</annotation></string>
<string name="spark_text_link_paragraph_example_">&lt;annotation color="neutral" typography="body1">This is Adevinta &lt;/annotation>&lt;annotation color="main" typography="body1">&lt;u>&lt;b>Privacy &amp; Policy&lt;/b>&lt;/u>&lt;/annotation>&lt;annotation color="neutral" typography="body1"> also lots of extra information you may be interested in or should I inform you about that extra information. you might not be aware of it&lt;/annotation></string>

<string name="spark_text_link_short_example_"><annotation color="neutral" typography="display2">Learn Kotlin Programming </annotation><annotation color="success" typography="display3"><u><b>https://kotlinlang.org</b></u></annotation></string>
<string name="spark_text_link_short_example_">&lt;annotation color="neutral" typography="display2">Learn Kotlin Programming &lt;/annotation>&lt;annotation color="success" typography="display3">&lt;u>&lt;b>https://kotlinlang.org&lt;/b>&lt;/u>&lt;/annotation></string>

<!--region Divider-->
<string name="component_divider_description">The Divider component provides a thin, unobtrusive line that separates and distinguishes sections of content to reinforce visual hierarchy.
A few common uses are:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,16 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.res.pluralStringResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.StringAnnotation
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.fromHtml
import androidx.compose.ui.text.style.BaselineShift
import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.tooling.preview.Preview
Expand Down Expand Up @@ -114,39 +118,17 @@ public fun annotatedStringResource(@StringRes id: Int, formatArgs: PersistentMap
* @param formatArgs the format arguments
* @return the [AnnotatedString] data associated with the resource
*/
@Deprecated(
message = "Use the annotatedStringResource with PersistentMap overload instead",
replaceWith = ReplaceWith("annotatedStringResource(id, persistentMapOf(formatArgs))"),
)
//@Deprecated(
// message = "Use the annotatedStringResource with PersistentMap overload instead",
// replaceWith = ReplaceWith("annotatedStringResource(id, persistentMapOf(formatArgs))"),
//)
@Composable
public fun annotatedStringResource(@StringRes id: Int, vararg formatArgs: Any): AnnotatedString {
val resources = resources()
val density = LocalDensity.current
val colors = SparkTheme.colors
val typography = SparkTheme.typography
return remember(id, formatArgs) {
val text = resources.getText(id, *formatArgs)
text.asAnnotatedString(density, colors, typography)
}
}

private fun Resources.buildSpannedStringWithArgs(
@StringRes id: Int,
args: PersistentMap<String, String>,
): SpannedString = buildSpannedString {
append(getText(id))
getSpans<Annotation>().filter { it.key == "variable" }
.forEach { replace(getSpanStart(it), getSpanEnd(it), args.getValue(it.value)) }
}

private fun Resources.buildSpannedStringWithArgs(
@PluralsRes id: Int,
count: Int,
args: PersistentMap<String, String>,
): SpannedString = buildSpannedString {
append(getQuantityText(id, count))
getSpans<Annotation>().filter { it.key == "variable" }
.forEach { replace(getSpanStart(it), getSpanEnd(it), args.getValue(it.value)) }
val string = stringResource(id, *formatArgs)
return AnnotatedString.fromHtml(string).asAnnotatedString(density, colors, typography)
}

/**
Expand All @@ -157,15 +139,11 @@ private fun Resources.buildSpannedStringWithArgs(
*/
@Composable
public fun annotatedStringResource(@StringRes id: Int): AnnotatedString {
val resources = resources()
val density = LocalDensity.current

val colors = SparkTheme.colors
val typography = SparkTheme.typography
return remember(id) {
val text = resources.getText(id)
text.asAnnotatedString(density, colors, typography)
}
val string = stringResource(id)
return AnnotatedString.fromHtml(string).asAnnotatedString(density, colors, typography)
}

/**
Expand All @@ -181,14 +159,11 @@ public fun annotatedPluralStringResource(
@PluralsRes id: Int,
count: Int,
): AnnotatedString {
val resources = resources()
val density = LocalDensity.current
val colors = SparkTheme.colors
val typography = SparkTheme.typography
return remember(id) {
val text = resources.getQuantityText(id, count)
text.asAnnotatedString(density, colors, typography)
}
val string = pluralStringResource(id, count)
return AnnotatedString.fromHtml(string).asAnnotatedString(density, colors, typography)
}

/**
Expand Down Expand Up @@ -233,14 +208,30 @@ public fun annotatedPluralStringResource(
count: Int,
vararg formatArgs: Any,
): AnnotatedString {
val resources = resources()
val density = LocalDensity.current
val colors = SparkTheme.colors
val typography = SparkTheme.typography
return remember(id) {
val text = resources.getQuantityText(id, count, *formatArgs)
text.asAnnotatedString(density, colors, typography)
}
val string = pluralStringResource(id, count, *formatArgs)
return AnnotatedString.fromHtml(string).asAnnotatedString(density, colors, typography)
}

private fun Resources.buildSpannedStringWithArgs(
@StringRes id: Int,
args: PersistentMap<String, String>,
): SpannedString = buildSpannedString {
append(getText(id))
getSpans<Annotation>().filter { it.key == "variable" }
.forEach { replace(getSpanStart(it), getSpanEnd(it), args.getValue(it.value)) }
}

private fun Resources.buildSpannedStringWithArgs(
@PluralsRes id: Int,
count: Int,
args: PersistentMap<String, String>,
): SpannedString = buildSpannedString {
append(getQuantityText(id, count))
getSpans<Annotation>().filter { it.key == "variable" }
.forEach { replace(getSpanStart(it), getSpanEnd(it), args.getValue(it.value)) }
}

@Composable
Expand Down Expand Up @@ -284,12 +275,29 @@ private fun Spanned.toHtmlWithoutParagraphs(): String = toHtml()
.substringAfter("<p dir=\"ltr\">")
.substringBeforeLast("</p>")

private fun CharSequence.asAnnotatedString(
@Suppress("UNCHECKED_CAST") // We're sure that we can only get a StringAnnotation
private fun AnnotatedString.asAnnotatedString(
density: Density,
colors: SparkColors,
typography: SparkTypography,
): AnnotatedString {
return mapAnnotations {
when(it.item) {
is StringAnnotation -> SparkStringAnnotations.toStyleAnnotation(
annotation = it as AnnotatedString.Range<StringAnnotation>,
colors = colors,
typography = typography
)
else -> it
}
}
}

private fun SpannedString.asAnnotatedString(
density: Density,
colors: SparkColors,
typography: SparkTypography,
): AnnotatedString {
if (this !is Spanned) return AnnotatedString(this.toString())
return buildAnnotatedString {
append(this@asAnnotatedString.toString())
getSpans(0, length, Any::class.java).forEach {
Expand Down Expand Up @@ -326,8 +334,8 @@ private fun AnnotatedString.Builder.buildWithSpan(
is SuperscriptSpan -> SpanStyle(baselineShift = BaselineShift.Superscript)
is SubscriptSpan -> SpanStyle(baselineShift = BaselineShift.Subscript)
is ForegroundColorSpan -> SpanStyle(color = Color(it.foregroundColor))
is Annotation -> SparkStringAnnotations.toSpanStyle(annotation = it, colors, typography) ?: return
else -> return
// is Annotation -> SparkStringAnnotations.toSpanStyle(annotation = it, colors, typography) ?: return
else -> return/**/
}
addStyle(span, start, end)
}
Expand Down Expand Up @@ -368,5 +376,11 @@ private fun AnnotatedStringResourcePreview() {
persistentMapOf("who" to "Bob"),
),
)
Text(
text = annotatedStringResource(
R.string.spark_annotatedStringResource_test_new_args,
"Bob",
),
)
}
}
Loading