From c8d8891a071ee428d423ca15799fd21ec5becc2c Mon Sep 17 00:00:00 2001 From: Levi Bard Date: Wed, 11 Dec 2024 17:53:32 +0100 Subject: [PATCH] Preserve the case of hashtags from content when possible (#4802) https://social.tchncs.de/@KazuShuSora/113621293051641672 --- .../keylesspalace/tusky/util/LinkHelper.kt | 42 ++++++++++++++----- 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/com/keylesspalace/tusky/util/LinkHelper.kt b/app/src/main/java/com/keylesspalace/tusky/util/LinkHelper.kt index a9a9ae099..ccb37039c 100644 --- a/app/src/main/java/com/keylesspalace/tusky/util/LinkHelper.kt +++ b/app/src/main/java/com/keylesspalace/tusky/util/LinkHelper.kt @@ -105,16 +105,38 @@ fun setClickableText( trailingHashtagView?.visible(showHashtagBar) if (showHashtagBar) { - trailingHashtagView?.apply { - text = SpannableStringBuilder().apply { - tags?.forEachIndexed { index, tag -> - val text = "#${tag.name}" - append(text, getCustomSpanForTag(text, tags, URLSpan(tag.url), listener), 0) - if (index != tags.lastIndex) { - append(" ") - } - } - } + trailingHashtagView?.apply { text = buildTrailingHashtagText(tags, trailingHashtags, listener) } + } +} + +/** + * Build a spanned string containing trailing and out-of-band hashtags for the trailing hashtag view + * @param tagsFromServer The list of hashtags from the server + * @param trailingHashtagsFromContent The list of trailing hashtags scraped from the post content + * @param listener to notify about particular spans that are clicked + */ +private fun buildTrailingHashtagText(tagsFromServer: List?, trailingHashtagsFromContent: List, listener: LinkListener): SpannableStringBuilder { + return SpannableStringBuilder().apply { + // we apply the tags scraped from the content first to preserve the casing + // (tags from the server are often downcased) + val additionalTags = tagsFromServer?.let { + it.filter { serverTag -> trailingHashtagsFromContent.none { serverTag.name.equals(it.name, ignoreCase = true) } } + } ?: emptyList() + appendTags(trailingHashtagsFromContent.plus(additionalTags), listener) + } +} + +/** + * Append space-separated url spans for a list of hashtags + * @param tags The tags to append + * @param listener to notify about particular spans that are clicked + */ +private fun SpannableStringBuilder.appendTags(tags: List, listener: LinkListener) { + tags.forEachIndexed { index, tag -> + val text = "#${tag.name}" + append(text, getCustomSpanForTag(text, tags, URLSpan(tag.url), listener), 0) + if (index != tags.lastIndex) { + append(" ") } } }