Extend workaround for extra new lines in timeline (#8187)

* Extend workaround for extra new lines in timeline

Closes vector-im/element-android#8179

Caused by noties/Markwon#423

* Refactor

Co-authored-by: Yoan Pintas <y.pintas@gmail.com>

---------

Co-authored-by: Yoan Pintas <y.pintas@gmail.com>
This commit is contained in:
jonnyandrew 2023-03-06 16:03:53 +00:00 committed by GitHub
parent 8595bd2be8
commit 29f2bf25fc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 50 additions and 6 deletions

1
changelog.d/8187.bugfix Normal file
View File

@ -0,0 +1 @@
Extend workaround for extra new lines in timeline

View File

@ -20,6 +20,7 @@ import android.graphics.Canvas
import android.graphics.Paint
import android.text.Layout
import android.text.Spanned
import android.text.style.StrikethroughSpan
import androidx.core.text.getSpans
import im.vector.app.features.html.HtmlCodeSpan
import io.element.android.wysiwyg.spans.InlineCodeSpan
@ -28,6 +29,7 @@ import io.mockk.mockk
import io.mockk.slot
import io.mockk.verify
import io.noties.markwon.core.spans.EmphasisSpan
import io.noties.markwon.core.spans.LinkSpan
import io.noties.markwon.core.spans.OrderedListItemSpan
import io.noties.markwon.core.spans.StrongEmphasisSpan
import me.gujun.android.span.style.CustomTypefaceSpan
@ -59,6 +61,8 @@ private fun Any.readTags(): SpanTags {
StrongEmphasisSpan::class -> "bold"
EmphasisSpan::class, CustomTypefaceSpan::class -> "italic"
InlineCodeSpan::class -> "inline code"
StrikethroughSpan::class -> "strikethrough"
LinkSpan::class -> "link"
else -> if (this::class.qualifiedName!!.startsWith("android.widget")) {
null
} else {

View File

@ -73,6 +73,30 @@ class EventHtmlRendererTest {
result shouldBeEqualTo "__italic__ **bold**"
}
// https://github.com/noties/Markwon/issues/423
@Test
fun doesNotIntroduceExtraNewLines() {
// Given initial render (required to trigger bug)
"""Some <i>italic</i>""".renderAsTestSpan()
val results = arrayOf(
"""Some <i>italic</i>""".renderAsTestSpan(),
"""Some <b>bold</b>""".renderAsTestSpan(),
"""Some <code>code</code>""".renderAsTestSpan(),
"""Some <a href="link">link</a>""".renderAsTestSpan(),
"""Some <del>strikethrough</del>""".renderAsTestSpan(),
"""Some <span>span</span>""".renderAsTestSpan(),
)
results shouldBeEqualTo arrayOf(
"Some [italic]italic[/italic]",
"Some [bold]bold[/bold]",
"Some [inline code]code[/inline code]",
"Some [link]link[/link]",
"Some \n[strikethrough]strikethrough[/strikethrough]", // FIXME
"Some \nspan", // FIXME
)
}
@Test
fun processesHtmlWithinCodeBlocks() {
val result = """<code><i>italic</i> <b>bold</b></code>""".renderAsTestSpan()

View File

@ -31,6 +31,9 @@ import android.graphics.Typeface
import android.graphics.drawable.Drawable
import android.text.Spannable
import android.text.SpannableStringBuilder
import android.text.style.StrikethroughSpan
import android.text.style.URLSpan
import android.text.style.UnderlineSpan
import android.widget.TextView
import androidx.core.text.toSpannable
import com.bumptech.glide.Glide
@ -46,6 +49,8 @@ import io.noties.markwon.Markwon
import io.noties.markwon.MarkwonPlugin
import io.noties.markwon.MarkwonSpansFactory
import io.noties.markwon.PrecomputedFutureTextSetterCompat
import io.noties.markwon.core.spans.EmphasisSpan
import io.noties.markwon.core.spans.StrongEmphasisSpan
import io.noties.markwon.ext.latex.JLatexMathPlugin
import io.noties.markwon.ext.latex.JLatexMathTheme
import io.noties.markwon.html.HtmlPlugin
@ -154,14 +159,24 @@ class EventHtmlRenderer @Inject constructor(
/**
* Workaround for https://github.com/noties/Markwon/issues/423
*/
private val removeLeadingNewlineForInlineCode = object : AbstractMarkwonPlugin() {
private val removeLeadingNewlineForInlineElement = object : AbstractMarkwonPlugin() {
override fun afterSetText(textView: TextView) {
super.afterSetText(textView)
val text = SpannableStringBuilder(textView.text.toSpannable())
val inlineCodeSpans = text.getSpans(0, textView.length(), InlineCodeSpan::class.java).toList()
val legacyInlineCodeSpans = text.getSpans(0, textView.length(), HtmlCodeSpan::class.java).filter { !it.isBlock }
val spans = inlineCodeSpans + legacyInlineCodeSpans
val length = textView.length()
val spans = arrayOf(
InlineCodeSpan::class.java,
EmphasisSpan::class.java,
CustomTypefaceSpan::class.java,
StrongEmphasisSpan::class.java,
UnderlineSpan::class.java,
URLSpan::class.java,
StrikethroughSpan::class.java
).map { text.getSpans(0, length, it) }
.toTypedArray()
.plus(text.getSpans(0, length, HtmlCodeSpan::class.java).filter { !it.isBlock }.toTypedArray())
.flatten()
if (spans.isEmpty()) return
@ -179,11 +194,11 @@ class EventHtmlRenderer @Inject constructor(
private val markwon = Markwon.builder(context)
.usePlugin(HtmlRootTagPlugin())
.usePlugin(HtmlPlugin.create(htmlConfigure))
.usePlugin(removeLeadingNewlineForInlineCode)
.usePlugin(removeLeadingNewlineForInlineElement)
.usePlugin(glidePlugin)
.apply {
if (vectorPreferences.latexMathsIsEnabled()) {
// If latex maths is enabled in app preferences, refomat it so Markwon recognises it
// If latex maths is enabled in app preferences, reformat it so Markwon recognises it
// It needs to be in this specific format: https://noties.io/Markwon/docs/v4/ext-latex
latexPlugins.forEach(::usePlugin)
}