Linkify raw links in HTML message contents (#1102)
* Linkify links in HTML too: - Creates a `ClickableLinkText` for `String`. - Adds a `linkify` parameter to the original function, which is `true` by default. - Does the linkify logic inside that component, if `linkify` is true. * Add changelog * Make sure we don't linkify user mentions or room aliases. * Use remember to avoid re-processing the text for no reason.
This commit is contained in:
parent
af04cefb89
commit
bfd938a970
4 changed files with 83 additions and 50 deletions
|
|
@ -16,10 +16,6 @@
|
|||
|
||||
package io.element.android.features.messages.impl.timeline.components.event
|
||||
|
||||
import android.text.SpannableString
|
||||
import android.text.style.URLSpan
|
||||
import android.text.util.Linkify.PHONE_NUMBERS
|
||||
import android.text.util.Linkify.WEB_URLS
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
|
|
@ -28,20 +24,16 @@ import androidx.compose.foundation.layout.height
|
|||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.SpanStyle
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.core.text.util.LinkifyCompat
|
||||
import io.element.android.features.messages.impl.timeline.components.html.HtmlDocument
|
||||
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemTextBasedContent
|
||||
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemTextBasedContentProvider
|
||||
import io.element.android.libraries.designsystem.components.ClickableLinkText
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||
import io.element.android.libraries.theme.LinkColor
|
||||
import io.element.android.libraries.designsystem.text.toAnnotatedString
|
||||
|
||||
@Composable
|
||||
|
|
@ -69,14 +61,11 @@ fun TimelineItemTextView(
|
|||
}
|
||||
} else {
|
||||
Box(modifier) {
|
||||
val linkStyle = SpanStyle(
|
||||
color = LinkColor,
|
||||
)
|
||||
val styledText = remember(content.body) {
|
||||
content.body.linkify(linkStyle) + extraPadding.getStr(16.sp).toAnnotatedString()
|
||||
val textWithPadding = remember(content.body) {
|
||||
content.body + extraPadding.getStr(16.sp).toAnnotatedString()
|
||||
}
|
||||
ClickableLinkText(
|
||||
text = styledText,
|
||||
text = textWithPadding,
|
||||
linkAnnotationTag = "URL",
|
||||
onClick = onTextClicked,
|
||||
onLongClick = onTextLongClicked,
|
||||
|
|
@ -86,31 +75,6 @@ fun TimelineItemTextView(
|
|||
}
|
||||
}
|
||||
|
||||
private fun String.linkify(
|
||||
linkStyle: SpanStyle,
|
||||
) = buildAnnotatedString {
|
||||
append(this@linkify)
|
||||
val spannable = SpannableString(this@linkify)
|
||||
LinkifyCompat.addLinks(spannable, WEB_URLS or PHONE_NUMBERS)
|
||||
|
||||
val spans = spannable.getSpans(0, spannable.length, URLSpan::class.java)
|
||||
for (span in spans) {
|
||||
val start = spannable.getSpanStart(span)
|
||||
val end = spannable.getSpanEnd(span)
|
||||
addStyle(
|
||||
start = start,
|
||||
end = end,
|
||||
style = linkStyle,
|
||||
)
|
||||
addStringAnnotation(
|
||||
tag = "URL",
|
||||
annotation = span.url,
|
||||
start = start,
|
||||
end = end
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
internal fun TimelineItemTextViewLightPreview(@PreviewParameter(TimelineItemTextBasedContentProvider::class) content: TimelineItemTextBasedContent) =
|
||||
|
|
|
|||
|
|
@ -104,10 +104,7 @@ private fun HtmlBody(
|
|||
when (val node = nodes.next()) {
|
||||
is TextNode -> {
|
||||
if (!node.isBlank) {
|
||||
Text(
|
||||
text = node.text(),
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
)
|
||||
ClickableLinkText(text = node.text(), interactionSource = interactionSource)
|
||||
}
|
||||
}
|
||||
is Element -> {
|
||||
|
|
@ -579,7 +576,7 @@ private fun HtmlText(
|
|||
) {
|
||||
val inlineContentMap = persistentMapOf<String, InlineTextContent>()
|
||||
ClickableLinkText(
|
||||
text = text,
|
||||
annotatedString = text,
|
||||
linkAnnotationTag = "URL",
|
||||
style = style,
|
||||
modifier = modifier,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue