diff --git a/vector/src/main/java/im/vector/app/core/ui/views/AbstractFooteredTextView.kt b/vector/src/main/java/im/vector/app/core/ui/views/AbstractFooteredTextView.kt
new file mode 100644
index 0000000000..85be24fcd8
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/core/ui/views/AbstractFooteredTextView.kt
@@ -0,0 +1,149 @@
+package im.vector.app.core.ui.views
+
+import android.graphics.Canvas
+import android.graphics.Rect
+import android.text.Layout
+import android.text.Spannable
+import android.text.Spanned
+import android.view.View
+import androidx.appcompat.widget.AppCompatTextView
+import androidx.core.text.getSpans
+import androidx.core.text.toSpanned
+import androidx.core.view.ViewCompat.LAYOUT_DIRECTION_RTL
+import im.vector.app.R
+import im.vector.app.features.html.HtmlCodeSpan
+import io.noties.markwon.core.spans.EmphasisSpan
+import kotlin.math.ceil
+import kotlin.math.max
+
+/**
+ * TextView that reserves space at the bottom for overlaying it with a footer, e.g. in a FrameLayout or RelativeLayout
+ */
+interface AbstractFooteredTextView {
+
+    fun getAppCompatTextView(): AppCompatTextView
+    fun setMeasuredDimensionExposed(measuredWidth: Int, measuredHeight: Int)
+
+    val footerState: FooterState
+
+    class FooterState {
+        var footerHeight: Int = 0
+        var footerWidth: Int = 0
+        //var widthLimit: Float = 0f
+
+        // Some Rect to use during draw, since we should not alloc it during draw
+        val testBounds = Rect()
+
+        // Workaround to RTL languages with non-RTL content messages aligning left instead of start
+        var requiredHorizontalCanvasMove = 0f
+    }
+
+    fun updateDimensionsWithFooter(widthMeasureSpec: Int, heightMeasureSpec: Int) = with(getAppCompatTextView()) {
+        // Default case
+        footerState.requiredHorizontalCanvasMove = 0f
+
+        // Get max available width
+        //val widthMode = MeasureSpec.getMode(widthMeasureSpec)
+        val widthSize = View.MeasureSpec.getSize(widthMeasureSpec)
+        //val widthLimit = if (widthMode == MeasureSpec.AT_MOST) { widthSize.toFloat() } else { Float.MAX_VALUE }
+        val widthLimit = widthSize.toFloat()
+        /*
+        // Sometimes, widthLimit is not the actual limit, so remember it... ?
+        if (this.widthLimit > widthLimit) {
+            widthLimit = this.widthLimit
+        } else {
+            this.widthLimit = widthLimit
+        }
+         */
+
+        val lastLine = layout.lineCount - 1
+
+        // Let's check if the last line's text has the same RTL behaviour as the layout direction.
+        val viewIsRtl = layoutDirection == LAYOUT_DIRECTION_RTL
+        val looksLikeRtl = layout.getParagraphDirection(lastLine) == Layout.DIR_RIGHT_TO_LEFT
+        /*
+        val lastVisibleCharacter = layout.getLineVisibleEnd(lastLine) - 1
+        val looksLikeRtl = layout.isRtlCharAt(lastVisibleCharacter)
+         */
+
+        // Get required width for all lines
+        var maxLineWidth = 0f
+        for (i in 0 until layout.lineCount) {
+            // For some reasons, the getLineWidth is not working too well with RTL lines when rendering replies.
+            // -> https://github.com/SchildiChat/SchildiChat-android/issues/74
+            // However, the bounds method is a little generous sometimes (reserving too much space),
+            // so we don't want to use it over getLineWidth() unless required.
+            maxLineWidth = if (layout.getParagraphDirection(i) == Layout.DIR_RIGHT_TO_LEFT) {
+                layout.getLineBounds(i, footerState.testBounds)
+                max((footerState.testBounds.right - footerState.testBounds.left).toFloat(), maxLineWidth)
+            } else {
+                max(layout.getLineWidth(i), maxLineWidth)
+            }
+        }
+
+        // Fix wrap_content in multi-line texts by using maxLineWidth instead of measuredWidth here
+        // (compare WrapWidthTextView.kt)
+        var newWidth = ceil(maxLineWidth).toInt()
+        var newHeight = measuredHeight
+
+        val widthLastLine = layout.getLineWidth(lastLine)
+
+        // Required width if putting footer in the same line as the last line
+        val widthWithHorizontalFooter = (
+                if (looksLikeRtl == viewIsRtl)
+                    widthLastLine
+                else
+                    (maxLineWidth + resources.getDimensionPixelSize(R.dimen.sc_footer_rtl_mismatch_extra_padding))
+                ) + footerState.footerWidth
+
+        // If the last line is a multi-line code block, we have never space in the last line (as the black background always uses full width)
+        val forceNewlineFooter: Boolean
+        // For italic text, we need some extra space due to a wrap_content bug: https://stackoverflow.com/q/4353836
+        val addItalicPadding: Boolean
+
+        if (text is Spannable || text is Spanned) {
+            val span = text.toSpanned()
+            // If not found, -1+1 = 0
+            val lastLineStart = span.lastIndexOf("\n") + 1
+            val lastLineCodeSpans = span.getSpans<HtmlCodeSpan>(lastLineStart)
+            forceNewlineFooter = lastLineCodeSpans.any { it.isBlock }
+            addItalicPadding = span.getSpans<EmphasisSpan>().isNotEmpty()
+        } else {
+            forceNewlineFooter = false
+            addItalicPadding = false
+        }
+
+        // Is there space for a horizontal footer?
+        if (widthWithHorizontalFooter <= widthLimit && !forceNewlineFooter) {
+            // Reserve extra horizontal footer space if necessary
+            if (widthWithHorizontalFooter > newWidth) {
+                newWidth = ceil(widthWithHorizontalFooter).toInt()
+
+                if (viewIsRtl) {
+                    footerState.requiredHorizontalCanvasMove = widthWithHorizontalFooter - measuredWidth
+                }
+            }
+        } else {
+            // Reserve vertical footer space
+            newHeight += footerState.footerHeight
+            // Ensure enough width for footer bellow
+            newWidth = max(newWidth, footerState.footerWidth +
+                    resources.getDimensionPixelSize(R.dimen.sc_footer_padding_compensation) +
+                    2 * resources.getDimensionPixelSize(R.dimen.sc_footer_overlay_padding))
+        }
+
+        if (addItalicPadding) {
+            newWidth += resources.getDimensionPixelSize(R.dimen.italic_text_view_extra_padding)
+        }
+
+        //setMeasuredDimension(newWidth, newHeight)
+        Pair(newWidth, newHeight)
+    }
+
+    fun updateFooterOnPreDraw(canvas: Canvas?) {
+        // Workaround to RTL languages with non-RTL content messages aligning left instead of start
+        if (footerState.requiredHorizontalCanvasMove > 0f) {
+            canvas?.translate(footerState.requiredHorizontalCanvasMove, 0f)
+        }
+    }
+}
diff --git a/vector/src/main/java/im/vector/app/core/ui/views/FooteredEditorStyledTextView.kt b/vector/src/main/java/im/vector/app/core/ui/views/FooteredEditorStyledTextView.kt
new file mode 100644
index 0000000000..39692cdd03
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/core/ui/views/FooteredEditorStyledTextView.kt
@@ -0,0 +1,32 @@
+package im.vector.app.core.ui.views
+
+import android.content.Context
+import android.graphics.Canvas
+import android.util.AttributeSet
+import androidx.appcompat.widget.AppCompatTextView
+import io.element.android.wysiwyg.EditorStyledTextView
+
+class FooteredEditorStyledTextView @JvmOverloads constructor(
+        context: Context,
+        attrs: AttributeSet? = null,
+        defStyleAttr: Int = 0
+): EditorStyledTextView(context, attrs, defStyleAttr), AbstractFooteredTextView {
+
+    override val footerState: AbstractFooteredTextView.FooterState = AbstractFooteredTextView.FooterState()
+    override fun getAppCompatTextView(): AppCompatTextView = this
+    override fun setMeasuredDimensionExposed(measuredWidth: Int, measuredHeight: Int) = setMeasuredDimension(measuredWidth, measuredHeight)
+
+    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
+        // First, let super measure the content for our normal TextView use
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
+
+        val updatedMeasures = updateDimensionsWithFooter(widthMeasureSpec, heightMeasureSpec)
+        setMeasuredDimension(updatedMeasures.first, updatedMeasures.second)
+    }
+
+    override fun onDraw(canvas: Canvas?) {
+        updateFooterOnPreDraw(canvas)
+
+        super.onDraw(canvas)
+    }
+}
diff --git a/vector/src/main/java/im/vector/app/core/ui/views/FooteredTextView.kt b/vector/src/main/java/im/vector/app/core/ui/views/FooteredTextView.kt
index 712dfc4db3..50e6314a55 100644
--- a/vector/src/main/java/im/vector/app/core/ui/views/FooteredTextView.kt
+++ b/vector/src/main/java/im/vector/app/core/ui/views/FooteredTextView.kt
@@ -2,148 +2,29 @@ package im.vector.app.core.ui.views
 
 import android.content.Context
 import android.graphics.Canvas
-import android.graphics.Rect
-import android.text.Layout
-import android.text.Spannable
-import android.text.Spanned
 import android.util.AttributeSet
 import androidx.appcompat.widget.AppCompatTextView
-import androidx.core.text.getSpans
-import androidx.core.text.toSpanned
-import im.vector.app.R
-import im.vector.app.features.html.HtmlCodeSpan
-import io.noties.markwon.core.spans.EmphasisSpan
-import kotlin.math.ceil
-import kotlin.math.max
 
-/**
- * TextView that reserves space at the bottom for overlaying it with a footer, e.g. in a FrameLayout or RelativeLayout
- */
 class FooteredTextView @JvmOverloads constructor(
         context: Context,
         attrs: AttributeSet? = null,
         defStyleAttr: Int = 0
-): AppCompatTextView(context, attrs, defStyleAttr) {
+): AppCompatTextView(context, attrs, defStyleAttr), AbstractFooteredTextView {
 
-    var footerHeight: Int = 0
-    var footerWidth: Int = 0
-    //var widthLimit: Float = 0f
-
-    // Some Rect to use during draw, since we should not alloc it during draw
-    private val testBounds = Rect()
-
-    // Workaround to RTL languages with non-RTL content messages aligning left instead of start
-    private var requiredHorizontalCanvasMove = 0f
+    override val footerState: AbstractFooteredTextView.FooterState = AbstractFooteredTextView.FooterState()
+    override fun getAppCompatTextView(): AppCompatTextView = this
+    override fun setMeasuredDimensionExposed(measuredWidth: Int, measuredHeight: Int) = setMeasuredDimension(measuredWidth, measuredHeight)
 
     override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
         // First, let super measure the content for our normal TextView use
         super.onMeasure(widthMeasureSpec, heightMeasureSpec)
 
-        // Default case
-        requiredHorizontalCanvasMove = 0f
-
-        // Get max available width
-        //val widthMode = MeasureSpec.getMode(widthMeasureSpec)
-        val widthSize = MeasureSpec.getSize(widthMeasureSpec)
-        //val widthLimit = if (widthMode == MeasureSpec.AT_MOST) { widthSize.toFloat() } else { Float.MAX_VALUE }
-        val widthLimit = widthSize.toFloat()
-        /*
-        // Sometimes, widthLimit is not the actual limit, so remember it... ?
-        if (this.widthLimit > widthLimit) {
-            widthLimit = this.widthLimit
-        } else {
-            this.widthLimit = widthLimit
-        }
-         */
-
-        val lastLine = layout.lineCount - 1
-
-        // Let's check if the last line's text has the same RTL behaviour as the layout direction.
-        val viewIsRtl = layoutDirection == LAYOUT_DIRECTION_RTL
-        val looksLikeRtl = layout.getParagraphDirection(lastLine) == Layout.DIR_RIGHT_TO_LEFT
-        /*
-        val lastVisibleCharacter = layout.getLineVisibleEnd(lastLine) - 1
-        val looksLikeRtl = layout.isRtlCharAt(lastVisibleCharacter)
-         */
-
-        // Get required width for all lines
-        var maxLineWidth = 0f
-        for (i in 0 until layout.lineCount) {
-            // For some reasons, the getLineWidth is not working too well with RTL lines when rendering replies.
-            // -> https://github.com/SchildiChat/SchildiChat-android/issues/74
-            // However, the bounds method is a little generous sometimes (reserving too much space),
-            // so we don't want to use it over getLineWidth() unless required.
-            maxLineWidth = if (layout.getParagraphDirection(i) == Layout.DIR_RIGHT_TO_LEFT) {
-                layout.getLineBounds(i, testBounds)
-                max((testBounds.right - testBounds.left).toFloat(), maxLineWidth)
-            } else {
-                max(layout.getLineWidth(i), maxLineWidth)
-            }
-        }
-
-        // Fix wrap_content in multi-line texts by using maxLineWidth instead of measuredWidth here
-        // (compare WrapWidthTextView.kt)
-        var newWidth = ceil(maxLineWidth).toInt()
-        var newHeight = measuredHeight
-
-        val widthLastLine = layout.getLineWidth(lastLine)
-
-        // Required width if putting footer in the same line as the last line
-        val widthWithHorizontalFooter = (
-                if (looksLikeRtl == viewIsRtl)
-                    widthLastLine
-                else
-                    (maxLineWidth + resources.getDimensionPixelSize(R.dimen.sc_footer_rtl_mismatch_extra_padding))
-                ) + footerWidth
-
-        // If the last line is a multi-line code block, we have never space in the last line (as the black background always uses full width)
-        val forceNewlineFooter: Boolean
-        // For italic text, we need some extra space due to a wrap_content bug: https://stackoverflow.com/q/4353836
-        val addItalicPadding: Boolean
-
-        if (text is Spannable || text is Spanned) {
-            val span = text.toSpanned()
-            // If not found, -1+1 = 0
-            val lastLineStart = span.lastIndexOf("\n") + 1
-            val lastLineCodeSpans = span.getSpans<HtmlCodeSpan>(lastLineStart)
-            forceNewlineFooter = lastLineCodeSpans.any { it.isBlock }
-            addItalicPadding = span.getSpans<EmphasisSpan>().isNotEmpty()
-        } else {
-            forceNewlineFooter = false
-            addItalicPadding = false
-        }
-
-        // Is there space for a horizontal footer?
-        if (widthWithHorizontalFooter <= widthLimit && !forceNewlineFooter) {
-            // Reserve extra horizontal footer space if necessary
-            if (widthWithHorizontalFooter > newWidth) {
-                newWidth = ceil(widthWithHorizontalFooter).toInt()
-
-                if (viewIsRtl) {
-                    requiredHorizontalCanvasMove = widthWithHorizontalFooter - measuredWidth
-                }
-            }
-        } else {
-            // Reserve vertical footer space
-            newHeight += footerHeight
-            // Ensure enough width for footer bellow
-            newWidth = max(newWidth, footerWidth +
-                    resources.getDimensionPixelSize(R.dimen.sc_footer_padding_compensation) +
-                    2 * resources.getDimensionPixelSize(R.dimen.sc_footer_overlay_padding))
-        }
-
-        if (addItalicPadding) {
-            newWidth += resources.getDimensionPixelSize(R.dimen.italic_text_view_extra_padding)
-        }
-
-        setMeasuredDimension(newWidth, newHeight)
+        val updatedMeasures = updateDimensionsWithFooter(widthMeasureSpec, heightMeasureSpec)
+        setMeasuredDimension(updatedMeasures.first, updatedMeasures.second)
     }
 
     override fun onDraw(canvas: Canvas?) {
-        // Workaround to RTL languages with non-RTL content messages aligning left instead of start
-        if (requiredHorizontalCanvasMove > 0f) {
-            canvas?.translate(requiredHorizontalCanvasMove, 0f)
-        }
+        updateFooterOnPreDraw(canvas)
 
         super.onDraw(canvas)
     }
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageAudioItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageAudioItem.kt
index 1a611ea677..c6e09319bf 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageAudioItem.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageAudioItem.kt
@@ -31,7 +31,7 @@ import im.vector.app.R
 import im.vector.app.core.epoxy.ClickListener
 import im.vector.app.core.epoxy.onClick
 import im.vector.app.core.extensions.setTextOrHide
-import im.vector.app.core.ui.views.FooteredTextView
+import im.vector.app.core.ui.views.AbstractFooteredTextView
 import im.vector.app.core.utils.TextUtils
 import im.vector.app.features.home.room.detail.timeline.helper.AudioMessagePlaybackTracker
 import im.vector.app.features.home.room.detail.timeline.helper.ContentDownloadStateTrackerBinder
@@ -224,7 +224,7 @@ abstract class MessageAudioItem : AbsMessageItem<MessageAudioItem.Holder>() {
         val audioPlaybackTime by bind<TextView>(R.id.audioPlaybackTime)
         val progressLayout by bind<ViewGroup>(R.id.messageFileUploadProgressLayout)
         val fileSize by bind<TextView>(R.id.fileSize)
-        val captionView by bind<FooteredTextView>(R.id.messageCaptionView)
+        val captionView by bind<AbstractFooteredTextView>(R.id.messageCaptionView)
         val audioPlaybackDuration by bind<TextView>(R.id.audioPlaybackDuration)
         val audioSeekBar by bind<SeekBar>(R.id.audioSeekBar)
     }
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageFileItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageFileItem.kt
index a00d69b72d..828854f129 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageFileItem.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageFileItem.kt
@@ -30,7 +30,7 @@ import com.airbnb.epoxy.EpoxyModelClass
 import im.vector.app.R
 import im.vector.app.core.epoxy.onClick
 import im.vector.app.core.extensions.setTextOrHide
-import im.vector.app.core.ui.views.FooteredTextView
+import im.vector.app.core.ui.views.AbstractFooteredTextView
 import im.vector.app.features.home.room.detail.timeline.helper.ContentDownloadStateTrackerBinder
 import im.vector.app.features.home.room.detail.timeline.helper.ContentUploadStateTrackerBinder
 import im.vector.app.features.home.room.detail.timeline.style.TimelineMessageLayout
@@ -154,7 +154,7 @@ abstract class MessageFileItem : AbsMessageItem<MessageFileItem.Holder>() {
         val fileImageWrapper by bind<ViewGroup>(R.id.messageFileImageView)
         val fileDownloadProgress by bind<ProgressBar>(R.id.messageFileProgressbar)
         val filenameView by bind<TextView>(R.id.messageFilenameView)
-        val captionView by bind<FooteredTextView>(R.id.messageCaptionView)
+        val captionView by bind<AbstractFooteredTextView>(R.id.messageCaptionView)
     }
 
     companion object {
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageImageVideoItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageImageVideoItem.kt
index bb9c67f3db..479f5d60d5 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageImageVideoItem.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageImageVideoItem.kt
@@ -34,17 +34,15 @@ import im.vector.app.core.epoxy.onClick
 import im.vector.app.core.extensions.setTextOrHide
 import im.vector.app.core.files.LocalFilesHelper
 import im.vector.app.core.glide.GlideApp
-import im.vector.app.core.ui.views.FooteredTextView
+import im.vector.app.core.ui.views.AbstractFooteredTextView
 import im.vector.app.core.utils.DimensionConverter
 import im.vector.app.features.home.room.detail.timeline.helper.ContentUploadStateTrackerBinder
 import im.vector.app.features.home.room.detail.timeline.style.TimelineMessageLayout
 import im.vector.app.features.home.room.detail.timeline.style.granularRoundedCorners
 import im.vector.app.features.home.room.detail.timeline.view.ScMessageBubbleWrapView
 import im.vector.app.features.media.ImageContentRenderer
-import im.vector.app.features.themes.defaultScBubbleAppearance
 import kotlin.math.round
 import org.matrix.android.sdk.api.session.room.model.message.MessageType
-import org.matrix.android.sdk.api.util.MimeTypes
 
 @EpoxyModelClass
 abstract class MessageImageVideoItem : AbsMessageItem<MessageImageVideoItem.Holder>() {
@@ -255,7 +253,7 @@ abstract class MessageImageVideoItem : AbsMessageItem<MessageImageVideoItem.Hold
     class Holder : AbsMessageItem.Holder(STUB_ID) {
         val progressLayout by bind<ViewGroup>(R.id.messageMediaUploadProgressLayout)
         val imageView by bind<ImageView>(R.id.messageThumbnailView)
-        val captionView by bind<FooteredTextView>(R.id.messageCaptionView)
+        val captionView by bind<AbstractFooteredTextView>(R.id.messageCaptionView)
         val playContentView by bind<ImageView>(R.id.messageMediaPlayView)
         val mediaContentView by bind<ViewGroup>(R.id.messageContentMedia)
     }
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 b047af0805..12f42780bc 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
@@ -17,23 +17,18 @@
 package im.vector.app.features.home.room.detail.timeline.item
 
 import android.text.Spanned
-import android.text.method.MovementMethod
 import android.view.ViewStub
 import androidx.appcompat.widget.AppCompatTextView
 import androidx.core.text.PrecomputedTextCompat
-import androidx.core.view.isVisible
 import androidx.core.widget.TextViewCompat
 import com.airbnb.epoxy.EpoxyAttribute
 import com.airbnb.epoxy.EpoxyModelClass
 import im.vector.app.R
 import im.vector.app.core.epoxy.onClick
 import im.vector.app.core.epoxy.onLongClickIgnoringLinks
-import im.vector.app.core.ui.views.FooteredTextView
+import im.vector.app.core.ui.views.AbstractFooteredTextView
 import im.vector.app.features.home.room.detail.timeline.TimelineEventController
-import im.vector.app.features.home.room.detail.timeline.reply.InReplyToView
 import im.vector.app.features.home.room.detail.timeline.style.TimelineMessageLayout
-import im.vector.app.features.home.room.detail.timeline.reply.PreviewReplyUiState
-import im.vector.app.features.home.room.detail.timeline.reply.ReplyPreviewRetriever
 import im.vector.app.features.home.room.detail.timeline.tools.findPillsAndProcess
 import im.vector.app.features.home.room.detail.timeline.url.AbstractPreviewUrlView
 import im.vector.app.features.home.room.detail.timeline.url.PreviewUrlRetriever
@@ -105,7 +100,7 @@ abstract class MessageTextItem : AbsMessageItem<MessageTextItem.Holder>() {
         holder.previewUrlView.delegate = previewUrlCallback
         holder.previewUrlView.renderMessageLayout(attributes.informationData.messageLayout)
 
-        val messageView: FooteredTextView = holder.messageView(useRichTextEditorStyle) //if (useRichTextEditorStyle) holder.richMessageView else holder.plainMessageView
+        val messageView: AbstractFooteredTextView = holder.messageView(useRichTextEditorStyle) //if (useRichTextEditorStyle) holder.richMessageView else holder.plainMessageView
         if (useBigFont) {
             messageView.textSize = 44F
         } else {
@@ -155,10 +150,10 @@ abstract class MessageTextItem : AbsMessageItem<MessageTextItem.Holder>() {
         lateinit var previewUrlView: AbstractPreviewUrlView // set to either previewUrlViewElement or previewUrlViewSc by layout
         private val richMessageStub by bind<ViewStub>(R.id.richMessageTextViewStub)
         private val plainMessageStub by bind<ViewStub>(R.id.plainMessageTextViewStub)
-        val richMessageView: FooteredTextView by lazy {
+        val richMessageView: AbstractFooteredTextView by lazy {
             richMessageStub.inflate().findViewById(R.id.messageTextView)
         }
-        val plainMessageView: FooteredTextView by lazy {
+        val plainMessageView: AbstractFooteredTextView by lazy {
             plainMessageStub.inflate().findViewById(R.id.messageTextView)
         }
         fun messageView(useRichTextEditorStyle: Boolean) = if (useRichTextEditorStyle) richMessageView else plainMessageView
diff --git a/vector/src/main/res/layout/item_timeline_event_text_message_plain_stub.xml b/vector/src/main/res/layout/item_timeline_event_text_message_plain_stub.xml
index 68d97bba43..5f506963a1 100644
--- a/vector/src/main/res/layout/item_timeline_event_text_message_plain_stub.xml
+++ b/vector/src/main/res/layout/item_timeline_event_text_message_plain_stub.xml
@@ -6,7 +6,8 @@
     but it also makes it align better for RTL texts in RTL locales - at least
     until the user pill is touched...
 -->
-<im.vector.app.core.ui.views.FooteredTextView android:id="@+id/messageTextView"
+<im.vector.app.core.ui.views.FooteredTextView
+    android:id="@+id/messageTextView"
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:tools="http://schemas.android.com/tools"
     style="@style/Widget.Vector.TextView.Body"
diff --git a/vector/src/main/res/layout/item_timeline_event_text_message_rich_stub.xml b/vector/src/main/res/layout/item_timeline_event_text_message_rich_stub.xml
index 59ed1bdcc4..23d1ffa09e 100644
--- a/vector/src/main/res/layout/item_timeline_event_text_message_rich_stub.xml
+++ b/vector/src/main/res/layout/item_timeline_event_text_message_rich_stub.xml
@@ -6,7 +6,8 @@
     but it also makes it align better for RTL texts in RTL locales - at least
     until the user pill is touched...
 -->
-<io.element.android.wysiwyg.EditorStyledTextView xmlns:android="http://schemas.android.com/apk/res/android"
+<io.element.android.wysiwyg.EditorStyledTextView
+    xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:tools="http://schemas.android.com/tools"
     android:id="@+id/messageTextView"
     style="@style/Widget.Vector.TextView.Body"