mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2025-01-01 12:28:33 +01:00
Ensure received pills spans do not overlap
This commit is contained in:
parent
62bae67080
commit
38b93c527b
@ -16,6 +16,7 @@
|
|||||||
package im.vector.matrix.android.api.session.room.send
|
package im.vector.matrix.android.api.session.room.send
|
||||||
|
|
||||||
import android.text.SpannableString
|
import android.text.SpannableString
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility class to detect special span in CharSequence and turn them into
|
* Utility class to detect special span in CharSequence and turn them into
|
||||||
@ -23,12 +24,17 @@ import android.text.SpannableString
|
|||||||
*
|
*
|
||||||
* For now only support UserMentionSpans (TODO rooms, room aliases, etc...)
|
* For now only support UserMentionSpans (TODO rooms, room aliases, etc...)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
object TextPillsUtils {
|
object TextPillsUtils {
|
||||||
|
|
||||||
|
private data class MentionLinkSpec(val span: UserMentionSpan, val start: Int, val end: Int)
|
||||||
|
|
||||||
private const val MENTION_SPAN_TO_HTML_TEMPLATE = "<a href=\"https://matrix.to/#/%1\$s\">%2\$s</a>"
|
private const val MENTION_SPAN_TO_HTML_TEMPLATE = "<a href=\"https://matrix.to/#/%1\$s\">%2\$s</a>"
|
||||||
|
|
||||||
private const val MENTION_SPAN_TO_MD_TEMPLATE = "[%2\$s](https://matrix.to/#/%1\$s)"
|
private const val MENTION_SPAN_TO_MD_TEMPLATE = "[%2\$s](https://matrix.to/#/%1\$s)"
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Detects if transformable spans are present in the text.
|
* Detects if transformable spans are present in the text.
|
||||||
* @return the transformed String or null if no Span found
|
* @return the transformed String or null if no Span found
|
||||||
@ -49,14 +55,17 @@ object TextPillsUtils {
|
|||||||
val spannableString = SpannableString.valueOf(text)
|
val spannableString = SpannableString.valueOf(text)
|
||||||
val pills = spannableString
|
val pills = spannableString
|
||||||
?.getSpans(0, text.length, UserMentionSpan::class.java)
|
?.getSpans(0, text.length, UserMentionSpan::class.java)
|
||||||
|
?.map { MentionLinkSpec(it, spannableString.getSpanStart(it), spannableString.getSpanEnd(it)) }
|
||||||
|
?.toMutableList()
|
||||||
?.takeIf { it.isNotEmpty() }
|
?.takeIf { it.isNotEmpty() }
|
||||||
?: return null
|
?: return null
|
||||||
|
|
||||||
|
//we need to prune overlaps!
|
||||||
|
pruneOverlaps(pills)
|
||||||
|
|
||||||
return buildString {
|
return buildString {
|
||||||
var currIndex = 0
|
var currIndex = 0
|
||||||
pills.forEachIndexed { _, urlSpan ->
|
pills.forEachIndexed { _, (urlSpan, start, end) ->
|
||||||
val start = spannableString.getSpanStart(urlSpan)
|
|
||||||
val end = spannableString.getSpanEnd(urlSpan)
|
|
||||||
// We want to replace with the pill with a html link
|
// We want to replace with the pill with a html link
|
||||||
append(text, currIndex, start)
|
append(text, currIndex, start)
|
||||||
append(String.format(template, urlSpan.userId, urlSpan.displayName))
|
append(String.format(template, urlSpan.userId, urlSpan.displayName))
|
||||||
@ -64,4 +73,57 @@ object TextPillsUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun pruneOverlaps(links: MutableList<MentionLinkSpec>) {
|
||||||
|
Collections.sort(links, COMPARATOR)
|
||||||
|
var len = links.size
|
||||||
|
var i = 0
|
||||||
|
while (i < len - 1) {
|
||||||
|
val a = links[i]
|
||||||
|
val b = links[i + 1]
|
||||||
|
var remove = -1
|
||||||
|
|
||||||
|
//test if there is an overlap
|
||||||
|
if (b.start in a.start until a.end) {
|
||||||
|
|
||||||
|
when {
|
||||||
|
b.end <= a.end ->
|
||||||
|
//b is inside a -> b should be removed
|
||||||
|
remove = i + 1
|
||||||
|
a.end - a.start > b.end - b.start ->
|
||||||
|
//overlap and a is bigger -> b should be removed
|
||||||
|
remove = i + 1
|
||||||
|
a.end - a.start < b.end - b.start ->
|
||||||
|
//overlap and a is smaller -> a should be removed
|
||||||
|
remove = i
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (remove != -1) {
|
||||||
|
links.removeAt(remove)
|
||||||
|
len--
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val COMPARATOR = Comparator<MentionLinkSpec> { (_, startA, endA), (_, startB, endB) ->
|
||||||
|
if (startA < startB) {
|
||||||
|
return@Comparator -1
|
||||||
|
}
|
||||||
|
|
||||||
|
if (startA > startB) {
|
||||||
|
return@Comparator 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if (endA < endB) {
|
||||||
|
return@Comparator 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if (endA > endB) {
|
||||||
|
-1
|
||||||
|
} else 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user