Show target domains for non-mention/non-hashtag links where the target domain is not provided or differs from the domain in the text (#2698)

* Show target domains for non-mention/non-hashtag links where the target domain is not provided or differs from the domain in the text.
Addresses #2694

* Add link signifier to the marked-up domain

* Back down on validating hashtags and mentions, don't markup _any_ urls where the text starts with #/@
This commit is contained in:
Levi Bard 2022-09-17 19:06:07 +02:00 committed by GitHub
commit 687cffd540
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 123 additions and 1 deletions

View file

@ -57,7 +57,9 @@ fun getDomain(urlString: String?): String {
* @param listener to notify about particular spans that are clicked
*/
fun setClickableText(view: TextView, content: CharSequence, mentions: List<Mention>, tags: List<HashTag>?, listener: LinkListener) {
view.text = SpannableStringBuilder.valueOf(content).apply {
val spannableContent = markupHiddenUrls(view.context, content, mentions, tags, listener)
view.text = spannableContent.apply {
getSpans(0, content.length, URLSpan::class.java).forEach {
setClickableText(it, this, mentions, tags, listener)
}
@ -65,6 +67,29 @@ fun setClickableText(view: TextView, content: CharSequence, mentions: List<Menti
view.movementMethod = LinkMovementMethod.getInstance()
}
@VisibleForTesting
fun markupHiddenUrls(context: Context, content: CharSequence, mentions: List<Mention>, tags: List<HashTag>?, listener: LinkListener): SpannableStringBuilder {
val spannableContent = SpannableStringBuilder.valueOf(content)
val originalSpans = spannableContent.getSpans(0, content.length, URLSpan::class.java)
val obscuredLinkSpans = originalSpans.filter {
val text = spannableContent.subSequence(spannableContent.getSpanStart(it), spannableContent.getSpanEnd(it))
val firstCharacter = text[0]
firstCharacter != '#' &&
firstCharacter != '@' &&
getDomain(text.toString()) != getDomain(it.url)
}
for (span in obscuredLinkSpans) {
val start = spannableContent.getSpanStart(span)
val end = spannableContent.getSpanEnd(span)
val originalText = spannableContent.subSequence(start, end)
val replacementText = context.getString(R.string.url_domain_notifier, originalText, getDomain(span.url))
spannableContent.replace(start, end, replacementText) // this also updates the span locations
}
return spannableContent
}
@VisibleForTesting
fun setClickableText(
span: URLSpan,