diff --git a/dependencies.gradle b/dependencies.gradle index a4e2c60387..58133c3eef 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -14,7 +14,7 @@ def kotlinCoroutines = "1.5.1" def dagger = "2.38.1" def retrofit = "2.9.0" def arrow = "0.8.2" -def markwon = "4.6.2" +def markwon = "4.3.1" def moshi = "1.12.0" def lifecycle = "2.2.0" def rxBinding = "3.1.0" @@ -90,6 +90,8 @@ ext.libs = [ ], markwon : [ 'core' : "io.noties.markwon:core:$markwon", + 'extLatex' : "io.noties.markwon:ext-latex:$markwon", + 'inlineParser' : "io.noties.markwon:inline-parser:$markwon", 'html' : "io.noties.markwon:html:$markwon" ], airbnb : [ diff --git a/vector/build.gradle b/vector/build.gradle index d60f928f2c..9d25914e8e 100644 --- a/vector/build.gradle +++ b/vector/build.gradle @@ -390,6 +390,8 @@ dependencies { implementation libs.google.material implementation 'me.gujun.android:span:1.7' implementation libs.markwon.core + implementation libs.markwon.extLatex + implementation libs.markwon.inlineParser implementation libs.markwon.html implementation 'com.googlecode.htmlcompressor:htmlcompressor:1.5.2' implementation 'me.saket:better-link-movement-method:2.2.0' diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MessageItemFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MessageItemFactory.kt index 287cd014e9..fd675d90fa 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MessageItemFactory.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MessageItemFactory.kt @@ -484,6 +484,7 @@ class MessageItemFactory @Inject constructor( } .useBigFont(linkifiedBody.length <= MAX_NUMBER_OF_EMOJI_FOR_BIG_FONT * 2 && containsOnlyEmojis(linkifiedBody.toString())) .canUseTextFuture(canUseTextFuture) + .markwonPlugins(htmlRenderer.get().plugins) .searchForPills(isFormatted) .previewUrlRetriever(callback?.getPreviewUrlRetriever()) .imageContentRenderer(imageContentRenderer) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageTextItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageTextItem.kt index c6dce5a9ce..a53e80362d 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageTextItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageTextItem.kt @@ -16,6 +16,7 @@ package im.vector.app.features.home.room.detail.timeline.item +import android.text.Spanned import android.text.method.MovementMethod import androidx.appcompat.widget.AppCompatTextView import androidx.core.text.PrecomputedTextCompat @@ -31,6 +32,7 @@ import im.vector.app.features.home.room.detail.timeline.url.PreviewUrlRetriever import im.vector.app.features.home.room.detail.timeline.url.PreviewUrlUiState import im.vector.app.features.home.room.detail.timeline.url.PreviewUrlView import im.vector.app.features.media.ImageContentRenderer +import io.noties.markwon.MarkwonPlugin @EpoxyModelClass(layout = R.layout.item_timeline_event_base) abstract class MessageTextItem : AbsMessageItem() { @@ -59,6 +61,9 @@ abstract class MessageTextItem : AbsMessageItem() { @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash) var movementMethod: MovementMethod? = null + @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash) + var markwonPlugins: (List)? = null + private val previewUrlViewUpdater = PreviewUrlViewUpdater() override fun bind(holder: Holder) { @@ -92,6 +97,7 @@ abstract class MessageTextItem : AbsMessageItem() { } else { null } + markwonPlugins?.forEach { plugin -> plugin.beforeSetText(holder.messageView, message as Spanned) } super.bind(holder) holder.messageView.movementMethod = movementMethod @@ -104,6 +110,7 @@ abstract class MessageTextItem : AbsMessageItem() { } else { holder.messageView.text = message } + markwonPlugins?.forEach { plugin -> plugin.afterSetText(holder.messageView) } } override fun unbind(holder: Holder) { diff --git a/vector/src/main/java/im/vector/app/features/html/EventHtmlRenderer.kt b/vector/src/main/java/im/vector/app/features/html/EventHtmlRenderer.kt index d3b3be6a3e..cc7c999067 100644 --- a/vector/src/main/java/im/vector/app/features/html/EventHtmlRenderer.kt +++ b/vector/src/main/java/im/vector/app/features/html/EventHtmlRenderer.kt @@ -21,7 +21,11 @@ import android.text.Spannable import androidx.core.text.toSpannable import im.vector.app.core.resources.ColorProvider import io.noties.markwon.Markwon +import io.noties.markwon.MarkwonPlugin +import io.noties.markwon.ext.latex.JLatexMathPlugin +import io.noties.markwon.ext.latex.JLatexMathTheme import io.noties.markwon.html.HtmlPlugin +import io.noties.markwon.inlineparser.MarkwonInlineParserPlugin import org.commonmark.node.Node import timber.log.Timber import javax.inject.Inject @@ -37,8 +41,15 @@ class EventHtmlRenderer @Inject constructor(htmlConfigure: MatrixHtmlPluginConfi private val markwon = Markwon.builder(context) .usePlugin(HtmlPlugin.create(htmlConfigure)) + .usePlugin(MarkwonInlineParserPlugin.create()) + .usePlugin(JLatexMathPlugin.create(44F) { builder -> + builder.inlinesEnabled(true) + builder.theme().inlinePadding(JLatexMathTheme.Padding.symmetric(24, 8)) + }) .build() + val plugins: List = markwon.plugins + fun parse(text: String): Node { return markwon.parse(text) }