84 lines
No EOL
2.9 KiB
Kotlin
84 lines
No EOL
2.9 KiB
Kotlin
package ani.dantotsu.others
|
|
|
|
import android.graphics.Color
|
|
import android.text.Spannable
|
|
import android.text.Spanned
|
|
import android.text.TextPaint
|
|
import android.text.style.CharacterStyle
|
|
import android.text.style.ClickableSpan
|
|
import android.view.View
|
|
import android.widget.TextView
|
|
import io.noties.markwon.AbstractMarkwonPlugin
|
|
import io.noties.markwon.utils.ColorUtils
|
|
import java.util.regex.Pattern
|
|
|
|
class SpoilerPlugin : AbstractMarkwonPlugin() {
|
|
override fun beforeSetText(textView: TextView, markdown: Spanned) {
|
|
applySpoilerSpans(markdown as Spannable)
|
|
}
|
|
|
|
private class RedditSpoilerSpan : CharacterStyle() {
|
|
private var revealed = false
|
|
override fun updateDrawState(tp: TextPaint) {
|
|
if (!revealed) {
|
|
// use the same text color
|
|
tp.bgColor = Color.DKGRAY
|
|
tp.color = Color.DKGRAY
|
|
} else {
|
|
// for example keep a bit of black background to remind that it is a spoiler
|
|
tp.bgColor = ColorUtils.applyAlpha(Color.DKGRAY, 25)
|
|
}
|
|
}
|
|
|
|
fun setRevealed(revealed: Boolean) {
|
|
this.revealed = revealed
|
|
}
|
|
}
|
|
|
|
// we also could make text size smaller (but then MetricAffectingSpan should be used)
|
|
private class HideSpoilerSyntaxSpan : CharacterStyle() {
|
|
override fun updateDrawState(tp: TextPaint) {
|
|
// set transparent color
|
|
tp.color = 0
|
|
}
|
|
}
|
|
|
|
companion object {
|
|
private val RE = Pattern.compile("\\|\\|.+?\\|\\|")
|
|
private fun applySpoilerSpans(spannable: Spannable) {
|
|
val text = spannable.toString()
|
|
val matcher = RE.matcher(text)
|
|
while (matcher.find()) {
|
|
val spoilerSpan = RedditSpoilerSpan()
|
|
val clickableSpan: ClickableSpan = object : ClickableSpan() {
|
|
override fun onClick(widget: View) {
|
|
spoilerSpan.setRevealed(true)
|
|
widget.postInvalidateOnAnimation()
|
|
}
|
|
|
|
override fun updateDrawState(ds: TextPaint) {
|
|
// no op
|
|
}
|
|
}
|
|
val s = matcher.start()
|
|
val e = matcher.end()
|
|
spannable.setSpan(spoilerSpan, s, e, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
|
spannable.setSpan(clickableSpan, s, e, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
|
|
|
// we also can hide original syntax
|
|
spannable.setSpan(
|
|
HideSpoilerSyntaxSpan(),
|
|
s,
|
|
s + 2,
|
|
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
|
|
)
|
|
spannable.setSpan(
|
|
HideSpoilerSyntaxSpan(),
|
|
e - 2,
|
|
e,
|
|
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
|
|
)
|
|
}
|
|
}
|
|
}
|
|
} |