package com.keylesspalace.tusky.util
import android.content.Context
import android.text.Spannable
import android.text.SpannableStringBuilder
import android.text.Spanned
import android.text.style.CharacterStyle
import android.text.style.DynamicDrawableSpan
import android.text.style.ForegroundColorSpan
import android.text.style.ImageSpan
import android.text.style.URLSpan
import com.keylesspalace.tusky.util.twittertext.Regex
import com.mikepenz.iconics.IconicsDrawable
import com.mikepenz.iconics.typeface.library.googlematerial.GoogleMaterial
import java.util.regex.Pattern
/**
* @see
* Tag#HASHTAG_RE.
*/
private const val HASHTAG_SEPARATORS = "_\\u00B7\\u30FB\\u200c"
internal const val TAG_PATTERN_STRING = "(?
* Account#MENTION_RE
*/
private const val USERNAME_PATTERN_STRING = "[a-z0-9_]+([a-z0-9_.-]+[a-z0-9_]+)?"
internal const val MENTION_PATTERN_STRING = "(? = defaultFinders) {
// Strip all existing colour spans.
for (spanClass in spanClasses) {
clearSpans(spanClass)
}
for (finder in finders) {
// before running the regular expression, check if there is even a chance of it finding something
if (this.contains(finder.searchString)) {
val matcher = finder.pattern.matcher(this)
while (matcher.find()) {
// we found a match
val start = matcher.start(1)
val end = matcher.end(1)
// only add a span if there is no other one yet (e.g. the #anchor part of an url might match as hashtag, but must be ignored)
if (this.getSpans(start, end, URLSpan::class.java).isEmpty()) {
this.setSpan(
getSpan(finder.type, this, colour, start, end),
start,
end,
Spanned.SPAN_INCLUSIVE_EXCLUSIVE
)
}
}
}
}
}
private fun Spannable.clearSpans(spanClass: Class) {
for (span in getSpans(0, length, spanClass)) {
removeSpan(span)
}
}
/**
* Replaces text of the form [iconics name] with their spanned counterparts (ImageSpan).
*/
fun addDrawables(text: CharSequence, color: Int, size: Int, context: Context): Spannable {
val builder = SpannableStringBuilder(text)
val pattern = Pattern.compile("\\[iconics ([0-9a-z_]+)]")
val matcher = pattern.matcher(builder)
while (matcher.find()) {
val resourceName = matcher.group(1)
?: continue
val drawable = IconicsDrawable(context, GoogleMaterial.getIcon(resourceName))
drawable.setBounds(0, 0, size, size)
drawable.setTint(color)
builder.setSpan(ImageSpan(drawable, DynamicDrawableSpan.ALIGN_BASELINE), matcher.start(), matcher.end(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
}
return builder
}
private fun getSpan(
matchType: FoundMatchType,
string: CharSequence,
colour: Int,
start: Int,
end: Int
): CharacterStyle {
return when (matchType) {
FoundMatchType.HTTP_URL, FoundMatchType.HTTPS_URL -> NoUnderlineURLSpan(string.substring(start, end))
FoundMatchType.MENTION -> MentionSpan(string.substring(start, end))
else -> ForegroundColorSpan(colour)
}
}