From a29d5f791f3c373ebfc2372d381a3ceae10fb623 Mon Sep 17 00:00:00 2001
From: Andreas Hatziiliou <andreas.hatziiliou@savoirfairelinux.com>
Date: Thu, 3 Oct 2024 15:12:29 -0400
Subject: [PATCH] message_bar: unify layout to be more coherent

The goal of this patch is to make the messagebar (and more broadly
the chatViewFooter) more coherent in its behavior and look/feel.

GitLab: #1846
GitLab: #1848
GitLab: #1639
GitLab: #1420
Change-Id: I0d0ed207df9eba50f724c69fa49f956dc8aaa573
---
 .../mainview/components/ChatViewFooter.qml    |   2 +-
 .../mainview/components/ChatViewHeader.qml    |  54 +-
 .../components/FilesToSendContainer.qml       |   3 +-
 src/app/mainview/components/MessageBar.qml    | 861 ++----------------
 .../components/MessageBarTextArea.qml         | 127 +--
 .../mainview/components/MessageFormatBar.qml  | 693 ++++++++++++++
 .../mainview/components/MessageListView.qml   | 200 ++--
 .../components/MessagesResearchPanel.qml      |   1 -
 src/app/net/jami/Constants/JamiTheme.qml      |   3 +
 tests/qml/src/tst_ChatViewFooter.qml          |   8 +-
 10 files changed, 968 insertions(+), 984 deletions(-)
 create mode 100644 src/app/mainview/components/MessageFormatBar.qml

diff --git a/src/app/mainview/components/ChatViewFooter.qml b/src/app/mainview/components/ChatViewFooter.qml
index 70dc63c50..baa3a13e8 100644
--- a/src/app/mainview/components/ChatViewFooter.qml
+++ b/src/app/mainview/components/ChatViewFooter.qml
@@ -148,7 +148,7 @@ Rectangle {
 
             Layout.alignment: Qt.AlignHCenter
             Layout.preferredWidth: footerColumnLayout.width
-            Layout.leftMargin: 0
+            Layout.leftMargin: marginSize
             Layout.rightMargin: marginSize
             Layout.bottomMargin: marginSize
             Layout.preferredHeight: height
diff --git a/src/app/mainview/components/ChatViewHeader.qml b/src/app/mainview/components/ChatViewHeader.qml
index a05419068..1c5c1f426 100644
--- a/src/app/mainview/components/ChatViewHeader.qml
+++ b/src/app/mainview/components/ChatViewHeader.qml
@@ -23,7 +23,6 @@ import net.jami.Adapters 1.1
 import net.jami.Constants 1.1
 import net.jami.Enums 1.1
 import net.jami.Models 1.1
-
 import "../../commoncomponents"
 
 Rectangle {
@@ -61,9 +60,7 @@ Rectangle {
     }
 
     property bool addMemberVisibility: {
-        return swarmDetailsVisibility
-                && !CurrentConversation.isCoreDialog
-                && !CurrentConversation.isRequest;
+        return swarmDetailsVisibility && !CurrentConversation.isCoreDialog && !CurrentConversation.isRequest;
     }
 
     property bool swarmDetailsVisibility: {
@@ -81,8 +78,10 @@ Rectangle {
         anchors.rightMargin: 10 + layoutManager.qwkSystemButtonSpacing.right
         spacing: 16
 
-        JamiPushButton { QWKSetParentHitTestVisible {}
+        JamiPushButton {
             id: backToWelcomeViewButton
+            QWKSetParentHitTestVisible {
+            }
 
             Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
             Layout.leftMargin: 8
@@ -109,8 +108,10 @@ Rectangle {
 
             color: JamiTheme.transparentColor
 
-            ColumnLayout { QWKSetParentHitTestVisible {}
+            ColumnLayout {
                 id: userNameOrIdColumnLayout
+                QWKSetParentHitTestVisible {
+                }
                 objectName: "userNameOrIdColumnLayout"
 
                 height: parent.height
@@ -148,31 +149,34 @@ Rectangle {
             }
         }
 
-        JamiPushButton { QWKSetParentHitTestVisible {}
+        JamiPushButton {
             id: startAudioCallButton
+            QWKSetParentHitTestVisible {
+            }
 
-            visible: interactionButtonsVisibility &&
-                     (!addMemberVisibility || UtilsAdapter.getAppValue(Settings.EnableExperimentalSwarm))
+            visible: interactionButtonsVisibility && (!addMemberVisibility || UtilsAdapter.getAppValue(Settings.EnableExperimentalSwarm))
             source: JamiResources.place_audiocall_24dp_svg
             toolTipText: JamiStrings.startAudioCall
 
             onClicked: CallAdapter.placeAudioOnlyCall()
         }
 
-        JamiPushButton { QWKSetParentHitTestVisible {}
+        JamiPushButton {
             id: startVideoCallButton
+            QWKSetParentHitTestVisible {
+            }
 
-            visible: interactionButtonsVisibility &&
-                     CurrentAccount.videoEnabled_Video &&
-                     (!addMemberVisibility || UtilsAdapter.getAppValue(Settings.EnableExperimentalSwarm))
+            visible: interactionButtonsVisibility && CurrentAccount.videoEnabled_Video && (!addMemberVisibility || UtilsAdapter.getAppValue(Settings.EnableExperimentalSwarm))
             source: JamiResources.videocam_24dp_svg
             toolTipText: JamiStrings.startVideoCall
 
             onClicked: CallAdapter.placeCall()
         }
 
-        JamiPushButton { QWKSetParentHitTestVisible {}
+        JamiPushButton {
             id: inviteMembersButton
+            QWKSetParentHitTestVisible {
+            }
 
             checkable: true
             checked: extrasPanel.isOpen(ChatView.AddMemberPanel)
@@ -183,8 +187,10 @@ Rectangle {
             onClicked: extrasPanel.switchToPanel(ChatView.AddMemberPanel)
         }
 
-        JamiPushButton { QWKSetParentHitTestVisible {}
+        JamiPushButton {
             id: selectExtensionsButton
+            QWKSetParentHitTestVisible {
+            }
 
             visible: PluginAdapter.chatHandlersListCount && interactionButtonsVisibility
             source: JamiResources.plugins_24dp_svg
@@ -193,27 +199,29 @@ Rectangle {
             onClicked: pluginSelector()
         }
 
-        JamiPushButton { QWKSetParentHitTestVisible {}
+        JamiPushButton {
             id: sendContactRequestButton
+            QWKSetParentHitTestVisible {
+            }
             objectName: "sendContactRequestButton"
 
             visible: CurrentConversation.isTemporary || CurrentConversation.isBanned
             source: JamiResources.add_people_24dp_svg
             toolTipText: JamiStrings.addToConversations
 
-            onClicked: CurrentConversation.isBanned ?
-                           MessagesAdapter.unbanConversation(CurrentConversation.id) :
-                           MessagesAdapter.sendConversationRequest()
+            onClicked: CurrentConversation.isBanned ? MessagesAdapter.unbanConversation(CurrentConversation.id) : MessagesAdapter.sendConversationRequest()
         }
 
-        JamiPushButton { QWKSetParentHitTestVisible {}
+        JamiPushButton {
             id: searchMessagesButton
+            QWKSetParentHitTestVisible {
+            }
             objectName: "searchMessagesButton"
 
             checkable: true
             checked: extrasPanel.isOpen(ChatView.MessagesResearchPanel)
             visible: root.swarmDetailsVisibility
-            source:  JamiResources.ic_baseline_search_24dp_svg
+            source: JamiResources.ic_baseline_search_24dp_svg
             toolTipText: JamiStrings.search
 
             onClicked: extrasPanel.switchToPanel(ChatView.MessagesResearchPanel)
@@ -226,8 +234,10 @@ Rectangle {
             }
         }
 
-        JamiPushButton { QWKSetParentHitTestVisible {}
+        JamiPushButton {
             id: detailsButton
+            QWKSetParentHitTestVisible {
+            }
             objectName: "detailsButton"
 
             checkable: true
diff --git a/src/app/mainview/components/FilesToSendContainer.qml b/src/app/mainview/components/FilesToSendContainer.qml
index 1cce7ad2f..9167b690e 100644
--- a/src/app/mainview/components/FilesToSendContainer.qml
+++ b/src/app/mainview/components/FilesToSendContainer.qml
@@ -28,7 +28,6 @@ Rectangle {
     property alias filesToSendListModel: repeater.model
     property alias filesToSendCount: repeater.count
     color: JamiTheme.primaryBackgroundColor
-
     LayoutMirroring.enabled: UtilsAdapter.isRTL
     LayoutMirroring.childrenInherit: true
 
@@ -51,7 +50,7 @@ Rectangle {
             layoutDirection: UtilsAdapter.isRTL ? Qt.RightToLeft : Qt.LeftToRight
 
             spacing: JamiTheme.filesToSendContainerSpacing
-            padding: JamiTheme.filesToSendContainerPadding
+            //padding: JamiTheme.filesToSendContainerPadding
 
             Repeater {
                 id: repeater
diff --git a/src/app/mainview/components/MessageBar.qml b/src/app/mainview/components/MessageBar.qml
index a728ce50f..e9da7dc6a 100644
--- a/src/app/mainview/components/MessageBar.qml
+++ b/src/app/mainview/components/MessageBar.qml
@@ -24,11 +24,10 @@ import net.jami.Models 1.1
 import net.jami.Enums 1.1
 import net.jami.Constants 1.1
 import "../../commoncomponents"
-
 import "qrc:/js/markdownedition.js" as MDE
 
-RowLayout {
-    id: root
+Rectangle {
+    id: rectangle
 
     property alias text: messageBarTextArea.text
     property alias fileContainer: dataTransferSendContainer
@@ -38,11 +37,10 @@ RowLayout {
     property bool animate: false
     property bool showDefault: !UtilsAdapter.getAppValue(Settings.Key.ShowSendOption)
     property bool showTypo: UtilsAdapter.getAppValue(Settings.Key.ShowMardownOption)
-    property bool chatViewEnterIsNewLine: UtilsAdapter.getAppValue(Settings.Key.ChatViewEnterIsNewLine)
     property bool showTypoSecond: false
     property bool showPreview: false
-    property bool multiLine: messageBarTextArea.tooMuch
 
+    property bool maximized: (showTypo || dataTransferSendContainer.visible)
     property int messageBarLayoutMaximumWidth: 486
 
     readonly property bool isFullScreen: visibility === Window.FullScreen
@@ -54,126 +52,73 @@ RowLayout {
     signal showMapClicked
     signal emojiButtonClicked
 
-    property real rectHeight: (showTypo || multiLine) ? messageBarTextArea.height + 25 + 4 * marginSize + 1 : textAreaObj.height + 1 * marginSize + 1
-
-    height: rectHeight + (dataTransferSendContainer.visible ?  dataTransferSendContainer.height + (!showTypo ? 40 : - marginSize) : 0 )
+    onSendMessageButtonClicked: {
+        messageBarTextArea.restoreVisibilityAfterSend();
+        messageBarTextArea.forceActiveFocus();
+    }
 
     onShowTypoChanged: {
         messageBarTextArea.forceActiveFocus();
     }
 
-    Rectangle {
-        Layout.preferredHeight: parent.height
-        Layout.preferredWidth: childrenRect.width
-        visible: !CurrentConversation.isSip
-        color: JamiTheme.transparentColor
-        ComboBox {
-            id: showMoreButton
-            focus: true
-            width: JamiTheme.chatViewFooterButtonSize
-            height: JamiTheme.chatViewFooterButtonSize
-            anchors.bottom: parent.bottom
-            anchors.bottomMargin: marginSize / 2
-
-            // Used to choose the correct color for the button.
-            readonly property bool highlight: down || hovered
-
-            background: Rectangle {
-                implicitWidth: showMoreButton.width
-                implicitHeight: showMoreButton.height
-                radius: 5
-                color: showMoreButton.highlight ?
-                           JamiTheme.hoveredButtonColor :
-                           JamiTheme.transparentColor
-            }
-
-            MaterialToolTip {
-                id: toolTipMoreButton
+    Layout.fillWidth: true
+    Layout.alignment: Qt.AlignBottom
+    height: Math.min(JamiTheme.chatViewFooterTextAreaMaximumHeight + 2 * marginSize, colLayout.height + 2 * marginSize)
 
-                parent: showMoreButton
-                visible: showMoreButton.hovered && (text.length > 0)
-                delay: Qt.styleHints.mousePressAndHoldInterval
-                text: showMoreButton.down ? JamiStrings.showLess : JamiStrings.showMore
-            }
-
-            indicator: ResponsiveImage {
-
-                width: 25
-                height: 25
-
-                anchors.verticalCenter: parent.verticalCenter
-                anchors.horizontalCenter: parent.horizontalCenter
-
-                source: JamiResources.more_menu_black_24dp_svg
-
-                color: showMoreButton.highlight ?
-                           JamiTheme.chatViewFooterImgHoverColor :
-                           JamiTheme.chatViewFooterImgColor;
-            }
+    radius: 5
+    color: JamiTheme.transparentColor
+    border.color: JamiTheme.chatViewFooterRectangleBorderColor
+    border.width: 2
 
-            Component {
-                id: sharePopupComp
-                ShareMenu {
-                    id: sharePopup
-                    onAudioRecordMessageButtonClicked: root.audioRecordMessageButtonClicked()
-                    onVideoRecordMessageButtonClicked: root.videoRecordMessageButtonClicked()
-                    onShowMapClicked: root.showMapClicked()
-                    modelList: listViewMoreButton.menuMoreButton
-                    y: showMoreButton.y + 31
-                    x: showMoreButton.x - 3
-                }
-            }
-
-            popup: ShareMenu {
-                id: sharePopup
-                onAudioRecordMessageButtonClicked: root.audioRecordMessageButtonClicked()
-                onVideoRecordMessageButtonClicked: root.videoRecordMessageButtonClicked()
-                onShowMapClicked: root.showMapClicked()
-                modelList: listViewMoreButton.menuMoreButton
-                y: showMoreButton.y + 31
-                x: showMoreButton.x - 3
-            }
+    onWidthChanged: {
+        if (width < JamiTheme.showTypoSecondToggleWidth) {
+            showTypoSecond = false;
+        } else {
+            showTypoSecond = true;
         }
     }
 
-    Rectangle {
-        id: rectangle
+    GridLayout {
+        id: colLayout
+        columns: 2
+        rows: 3
 
-        Layout.fillWidth: true
-        Layout.fillHeight: true
-
-        radius: 5
-        color: JamiTheme.transparentColor
-        border.color: JamiTheme.chatViewFooterRectangleBorderColor
-        border.width: 2
-
-        onWidthChanged: {
-            height = Qt.binding(() => root.height);
-            if (width < JamiTheme.messageBarMinimumWidth) {
-                showTypoSecond = false;
-            } else {
-                showTypoSecond = true;
-            }
+        anchors {
+            left: parent.left
+            right: parent.right
+            top: parent.top
+            margins: marginSize
         }
 
-        GridLayout {
-            id: rowLayout
+        Rectangle {
+            id: messageRow
 
-            columns: 2
-            rows: 3
-            columnSpacing: 0
-            rowSpacing: 0
+            property bool isExpanding: !(showTypo && dataTransferSendContainer.visible) && (textAreaObj.textWidth >= rectangle.width - formatRow.width - 8 * marginSize)
 
-            anchors.fill: parent
+            Layout.fillWidth: true
+            Layout.row: maximized || isExpanding ? 0 : 2
+            Layout.column: 0
+            Layout.columnSpan: maximized || isExpanding ? 2 : 1
 
+            Layout.alignment: Qt.AlignTop
+            Layout.rightMargin: marginSize / 2
+            Layout.leftMargin: marginSize / 2
+            Layout.preferredHeight: Math.max(messageBarTextArea.contentHeight + 4, 36)
+            Layout.maximumHeight: JamiTheme.messageBarMaximumHeight
+            color: JamiTheme.transparentColor
 
             MessageBarTextArea {
                 id: messageBarTextArea
-
                 objectName: "messageBarTextArea"
-                maxWidth: rectangle.width - messageBarRowLayout.width - 35
-                Layout.row: 0
-                Layout.column: 0
+
+                placeholderText: JamiStrings.writeTo.arg(CurrentConversation.title)
+
+                anchors {
+                    right: (showTypo) ? previewButton.left : messageRow.right
+                    left: parent.left
+                    verticalCenter: parent.verticalCenter
+                    top: parent.top
+                }
 
                 // forward activeFocus to the actual text area object
                 onActiveFocusChanged: {
@@ -181,24 +126,10 @@ RowLayout {
                         textAreaObj.forceActiveFocus();
                 }
 
-                placeholderText: JamiStrings.writeTo.arg(CurrentConversation.title)
-
-                Layout.alignment: showTypo ? Qt.AlignLeft : Qt.AlignBottom
-                Layout.fillWidth: true
-                Layout.margins: marginSize / 2
-                Layout.topMargin: 0
-                Layout.minimumHeight: JamiTheme.chatViewFooterPreferredHeight
-                Layout.preferredHeight: contentHeight
-                Layout.maximumHeight: JamiTheme.chatViewFooterTextAreaMaximumHeight - marginSize / 2
-
                 onSendMessagesRequired: {
                     sendMessageButtonClicked();
                 }
-                onTextChanged: {
-                    if (!text) {
-                        messageBarTextArea.heightBinding();
-                    }
-                }
+
                 property var markdownShortCut: {
                     "Bold": function () {
                         if (!showPreview) {
@@ -326,657 +257,59 @@ RowLayout {
                 }
             }
 
-            FilesToSendContainer {
-                        id: dataTransferSendContainer
-
-                        objectName: "dataTransferSendContainer"
-                        visible: filesToSendCount > 0
-
-                        Layout.alignment: Qt.AlignCenter
-                        Layout.fillWidth: true
-                        Layout.rightMargin: marginSize / 2
-                        Layout.leftMargin: marginSize / 2
-                        Layout.row: 1
-                        Layout.column: 0
-                        Layout.columnSpan: 2
-                        Layout.preferredHeight: filesToSendCount ? JamiTheme.layoutWidthFileTransfer : 0
-                    }
-
-            Row {
-                id: messageBarRowLayout
-
-                Layout.row: dataTransferSendContainer.visible ? 3 : (showTypo || multiLine ? 2 : 0)
-                Layout.column: showTypo || multiLine ? 0 : 1
-                Layout.alignment: showTypo || multiLine ? Qt.AlignRight : Qt.AlignBottom
-                Layout.columnSpan: showTypo || multiLine ? 2 : 1
-                Layout.topMargin: dataTransferSendContainer.visible ? 0 : marginSize
-                Layout.rightMargin: 0
-
-                Row {
-                    anchors.bottom: parent.bottom
-                    anchors.bottomMargin: marginSize / 2
-
-                    Row {
-                        id: listViewTypo
-                        height: JamiTheme.chatViewFooterButtonSize
-
-                        ListView {
-                            id: listViewTypoFirst
-
-                            objectName: "listViewTypoFirst"
-
-                            visible: showTypo
-                            width: contentWidth + 2 * leftMargin
-
-                            Behavior on width  {
-                                NumberAnimation {
-                                    duration: JamiTheme.longFadeDuration / 2
-                                }
-                            }
-
-                            height: JamiTheme.chatViewFooterButtonSize
-                            orientation: ListView.Horizontal
-                            interactive: false
-                            spacing: 5
-
-                            property list<Action> menuTypoActionsFirst: [
-                                Action {
-                                    id: boldAction
-                                    property string iconSrc: JamiResources.bold_black_24dp_svg
-                                    property string shortcutText: JamiStrings.bold
-                                    property string shortcutKey: "Ctrl+B"
-                                    property bool isStyle: MDE.isStyle(messageBarTextArea, root.text, "**", "**")
-                                    onTriggered: MDE.addStyle(messageBarTextArea, root.text, "**", "**")
-                                },
-                                Action {
-                                    id: italicAction
-                                    property string iconSrc: JamiResources.italic_black_24dp_svg
-                                    property string shortcutText: JamiStrings.italic
-                                    property string shortcutKey: "Ctrl+I"
-                                    property bool isStyle: MDE.isStyle(messageBarTextArea, root.text, "*", "*")
-                                    onTriggered: MDE.addStyle(messageBarTextArea, root.text, "*", "*")
-                                },
-                                Action {
-                                    id: strikethroughAction
-                                    property string iconSrc: JamiResources.s_barre_black_24dp_svg
-                                    property string shortcutText: JamiStrings.strikethrough
-                                    property string shortcutKey: "Shift+Alt+X"
-                                    property bool isStyle: MDE.isStyle(messageBarTextArea, root.text, "~~", "~~")
-                                    onTriggered: MDE.addStyle(messageBarTextArea, root.text, "~~", "~~")
-                                },
-                                Action {
-                                    id: titleAction
-                                    property string iconSrc: JamiResources.title_black_24dp_svg
-                                    property string shortcutText: JamiStrings.heading
-                                    property string shortcutKey: "Ctrl+Alt+H"
-                                    property bool isStyle: MDE.isPrefixSyle(messageBarTextArea, root.text, "### ", false)
-                                    onTriggered: MDE.addPrefixStyle(messageBarTextArea, root.text, "### ", false)
-                                },
-                                Action {
-                                    id: linkAction
-                                    property string iconSrc: JamiResources.link_web_black_24dp_svg
-                                    property string shortcutText: JamiStrings.link
-                                    property string shortcutKey: "Ctrl+Alt+K"
-                                    property bool isStyle: MDE.isStyle(messageBarTextArea, root.text, "[", "](url)")
-                                    onTriggered: MDE.addStyle(messageBarTextArea, root.text, "[", "](url)")
-                                },
-                                Action {
-                                    id: codeAction
-                                    property string iconSrc: JamiResources.code_black_24dp_svg
-                                    property string shortcutText: JamiStrings.code
-                                    property string shortcutKey: "Ctrl+Alt+C"
-                                    property bool isStyle: MDE.isStyle(messageBarTextArea, root.text, "```", "```")
-                                    onTriggered: MDE.addStyle(messageBarTextArea, root.text, "```", "```")
-                                }
-                            ]
-
-                            model: menuTypoActionsFirst
-
-                            delegate: PushButton {
-                                anchors.verticalCenter: parent ? parent.verticalCenter : undefined
-                                preferredSize: JamiTheme.chatViewFooterRealButtonSize
-                                imageContainerWidth: 15
-                                imageContainerHeight: 15
-                                radius: 5
-
-                                hoverEnabled: !showPreview
-                                enabled: !showPreview
-
-                                toolTipText: modelData.shortcutText
-                                shortcutKey: modelData.shortcutKey
-                                hasShortcut: true
-
-                                source: modelData.iconSrc
-                                focusPolicy: Qt.TabFocus
-
-                                normalColor: {
-                                    if (showPreview) {
-                                        return JamiTheme.primaryBackgroundColor;
-                                    } else if (modelData.isStyle) {
-                                        return JamiTheme.hoveredButtonColor;
-                                    } else {
-                                        return JamiTheme.primaryBackgroundColor;
-                                    }
-                                }
-                                imageColor: {
-                                    if (showPreview) {
-                                        return JamiTheme.chatViewFooterImgDisableColor;
-                                    } else if (hovered) {
-                                        return JamiTheme.chatViewFooterImgHoverColor;
-                                    } else if (modelData.isStyle) {
-                                        return JamiTheme.chatViewFooterImgHoverColor;
-                                    } else {
-                                        return JamiTheme.chatViewFooterImgColor;
-                                    }
-                                }
-                                hoveredColor: JamiTheme.hoveredButtonColor
-                                pressedColor: hoveredColor
-
-                                action: modelData
-                            }
-                        }
-
-                        Rectangle {
-                            height: JamiTheme.chatViewFooterButtonSize
-                            color: JamiTheme.primaryBackgroundColor
-                            visible: showTypo && showTypoSecond
-                            width: 2
-
-                            Rectangle {
-                                anchors.verticalCenter: parent.verticalCenter
-                                width: 2
-                                height: JamiTheme.chatViewFooterButtonSize / 2
-                                color: showPreview ? JamiTheme.chatViewFooterImgDisableColor : JamiTheme.chatViewFooterSeparateLineColor
-                            }
-                        }
-
-                        Rectangle {
-                            z: -1
-                            radius: 0
-                            color: JamiTheme.primaryBackgroundColor
-                            width: JamiTheme.chatViewFooterButtonSize
-                            height: JamiTheme.chatViewFooterButtonSize
-
-                            visible: showTypo && !showTypoSecond
-
-                            ComboBox {
-                                id: showMoreTypoButton
-                                width: JamiTheme.chatViewFooterRealButtonSize
-                                height: width
-                                anchors.verticalCenter: parent.verticalCenter
-                                anchors.horizontalCenter: parent.horizontalCenter
-
-                                enabled: !showPreview
-                                hoverEnabled: !showPreview
-
-                                MaterialToolTip {
-                                    id: toolTip
-                                    parent: showMoreTypoButton
-                                    visible: showMoreTypoButton.hovered && (text.length > 0)
-                                    delay: Qt.styleHints.mousePressAndHoldInterval
-                                    text: markdownPopup.visible ? JamiStrings.showLess : JamiStrings.showMore
-                                }
-
-                                background: Rectangle {
-                                    implicitWidth: showMoreTypoButton.width
-                                    implicitHeight: showMoreTypoButton.height
-                                    radius: 5
-                                    color: showPreview ? JamiTheme.transparentColor : (parent && parent.hovered ? JamiTheme.hoveredButtonColor : JamiTheme.transparentColor)
-                                }
-
-                                indicator: ResponsiveImage {
-                                    containerHeight: 20
-                                    containerWidth: 20
-                                    width: 18
-                                    height: 18
-
-                                    anchors.verticalCenter: parent.verticalCenter
-                                    anchors.horizontalCenter: parent.horizontalCenter
-
-                                    source: JamiResources.more_vert_24dp_svg
-
-                                    color: showPreview ? JamiTheme.chatViewFooterImgDisableColor : (parent && parent.hovered ? JamiTheme.chatViewFooterImgHoverColor : JamiTheme.chatViewFooterImgColor)
-                                }
-
-                                popup: MarkdownPopup {
-                                    id: markdownPopup
-                                    y: 1.5 * parent.height
-                                    x: -parent.width * 2
-                                    width: 105
-                                    height: JamiTheme.chatViewFooterButtonSize
-
-                                    menuTypoActionsSecond: listViewTypoSecond.menuTypoActionsSecond
-                                }
-                            }
-                        }
-
-                        ListView {
-                            id: listViewTypoSecond
-                            visible: showTypo && showTypoSecond
-                            width: contentWidth + 2 * leftMargin
-
-                            height: JamiTheme.chatViewFooterButtonSize
-                            orientation: ListView.Horizontal
-                            interactive: false
-                            spacing: 10
-
-                            Rectangle {
-                                anchors.fill: parent
-                                color: JamiTheme.transparentColor
-                                z: -1
-                            }
-
-                            property list<Action> menuTypoActionsSecond: [
-                                Action {
-                                    id: quoteAction
-                                    property string iconSrc: JamiResources.quote_black_24dp_svg
-                                    property string shortcutText: JamiStrings.quote
-                                    property string shortcutKey: "Shift+Alt+9"
-                                    property bool isStyle: MDE.isPrefixSyle(messageBarTextArea, root.text, "> ", false)
-                                    onTriggered: MDE.addPrefixStyle(messageBarTextArea, root.text, "> ", false)
-                                },
-                                Action {
-                                    id: unorderedListAction
-                                    property string iconSrc: JamiResources.bullet_point_black_24dp_svg
-                                    property string shortcutText: JamiStrings.unorderedList
-                                    property string shortcutKey: "Shift+Alt+8"
-                                    property bool isStyle: MDE.isPrefixSyle(messageBarTextArea, root.text, "- ", false)
-                                    onTriggered: MDE.addPrefixStyle(messageBarTextArea, root.text, "- ", false)
-                                },
-                                Action {
-                                    id: orderedListAction
-                                    property string iconSrc: JamiResources.bullet_number_black_24dp_svg
-                                    property string shortcutText: JamiStrings.orderedList
-                                    property string shortcutKey: "Shift+Alt+7"
-                                    property bool isStyle: MDE.isPrefixSyle(messageBarTextArea, root.text, "", true)
-                                    onTriggered: MDE.addPrefixStyle(messageBarTextArea, root.text, "", true)
-                                }
-                            ]
-
-                            model: menuTypoActionsSecond
-
-                            delegate: PushButton {
-                                anchors.verticalCenter: parent ? parent.verticalCenter : undefined
-                                preferredSize: JamiTheme.chatViewFooterRealButtonSize
-                                imageContainerWidth: 20
-                                imageContainerHeight: 20
-                                radius: 5
-
-                                hoverEnabled: !showPreview
-                                enabled: !showPreview
-
-                                toolTipText: modelData.shortcutText
-                                shortcutKey: modelData.shortcutKey
-                                hasShortcut: modelData.hasShortcut ? true : false
-                                source: modelData.iconSrc
-                                focusPolicy: Qt.TabFocus
-
-                                normalColor: {
-                                    if (showPreview) {
-                                        return JamiTheme.primaryBackgroundColor;
-                                    } else if (modelData.normalColor) {
-                                        return modelData.normalColor;
-                                    } else if (modelData.isStyle) {
-                                        return JamiTheme.hoveredButtonColor;
-                                    } else {
-                                        return JamiTheme.primaryBackgroundColor;
-                                    }
-                                }
-                                imageColor: {
-                                    if (showPreview) {
-                                        return JamiTheme.chatViewFooterImgDisableColor;
-                                    } else if (hovered) {
-                                        return JamiTheme.chatViewFooterImgHoverColor;
-                                    } else if (modelData.isStyle) {
-                                        return JamiTheme.chatViewFooterImgHoverColor;
-                                    } else {
-                                        return JamiTheme.chatViewFooterImgColor;
-                                    }
-                                }
-                                hoveredColor: JamiTheme.hoveredButtonColor
-                                pressedColor: hoveredColor
-
-                                action: modelData
-                            }
-                        }
-                    }
-
-                    PushButton {
-                        id: typoButton
-
-                        preferredSize: JamiTheme.chatViewFooterButtonSize
-                        imageContainerWidth: 24
-                        imageContainerHeight: 24
+            PushButton {
+                id: previewButton
 
-                        radius: JamiTheme.chatViewFooterButtonRadius
-
-                        hoverEnabled: !showPreview
-                        enabled: !showPreview
-
-                        toolTipText: showTypo ? JamiStrings.hideFormatting : JamiStrings.showFormatting
-                        source: JamiResources.text_edit_black_24dp_svg
-
-                        normalColor: showPreview ? JamiTheme.primaryBackgroundColor : (showTypo ? JamiTheme.hoveredButtonColor : JamiTheme.primaryBackgroundColor)
-                        imageColor: showPreview ? JamiTheme.chatViewFooterImgDisableColor : (hovered || showTypo ? JamiTheme.chatViewFooterImgHoverColor : JamiTheme.chatViewFooterImgColor)
-                        hoveredColor: JamiTheme.hoveredButtonColor
-                        pressedColor: hoveredColor
-
-                        onClicked: {
-                            showTypo = !showTypo;
-                            messageBarTextArea.isShowTypo = showTypo;
-                            if (messageBar.width < messageBarLayoutMaximumWidth + sendMessageButton.width + 2 * JamiTheme.preferredMarginSize)
-                                showTypoSecond = false;
-                            if (!showDefault)
-                                showDefault = true;
-                            UtilsAdapter.setAppValue(Settings.Key.ShowMardownOption, showTypo);
-                            UtilsAdapter.setAppValue(Settings.Key.ShowSendOption, !showDefault);
-                        }
-                    }
-                }
-
-                Row {
-                    anchors.bottom: parent.bottom
-                    anchors.bottomMargin: marginSize / 2
-
-                    ListView {
-                        id: listViewAction
-
-                        width: contentWidth + 2 * leftMargin
-
-                        Behavior on width  {
-                            NumberAnimation {
-                                duration: JamiTheme.longFadeDuration / 2
-                            }
-                        }
-
-                        height: JamiTheme.chatViewFooterButtonSize
-                        orientation: ListView.Horizontal
-                        interactive: false
-
-                        leftMargin: 5
-                        rightMargin: 5
-                        spacing: 5
-
-                        property list<Action> menuActions: [
-                            Action {
-                                id: sendFile
-                                property string iconSrc: JamiResources.link_black_24dp_svg
-                                property string toolTip: JamiStrings.sendFile
-                                property bool show: true
-                                property bool needWebEngine: false
-                                property bool needVideoDevice: false
-                                property bool noSip: false
-                                onTriggered: function clickAction() {
-                                    sendFileButtonClicked();
-                                    textAreaObj.forceActiveFocus();
-                                }
-                            },
-                            Action {
-                                id: addEmoji
-                                property string iconSrc: JamiResources.emoji_black_24dp_svg
-                                property string toolTip: JamiStrings.addEmoji
-                                property bool show: true
-                                property bool needWebEngine: true
-                                property bool needVideoDevice: false
-                                property bool noSip: true
-                                onTriggered: function clickAction() {
-                                    emojiButtonClicked();
-                                }
-                            }
-                        ]
-
-                        ListModel {
-                            id: listActions
-                            Component.onCompleted: {
-                                for (var i = 0; i < listViewAction.menuActions.length; i++) {
-                                    append({
-                                            "menuAction": listViewAction.menuActions[i]
-                                        });
-                                }
-                            }
-                        }
-
-                        model: SortFilterProxyModel {
-                            sourceModel: listActions
-                            filters: [
-                                ExpressionFilter {
-                                    expression: menuAction.show === true
-                                    enabled: root.showDefault
-                                },
-                                ExpressionFilter {
-                                    expression: menuAction.needWebEngine === false
-                                    enabled: !WITH_WEBENGINE
-                                },
-                                ExpressionFilter {
-                                    expression: menuAction.noSip === true
-                                    enabled: CurrentConversation.isSip
-                                },
-                                ExpressionFilter {
-                                    expression: menuAction.needVideoDevice === false
-                                    enabled: VideoDevices.listSize === 0
-                                }
-                            ]
-                        }
-
-                        delegate: PushButton {
-                            id: buttonDelegate
-                            anchors.verticalCenter: parent ? parent.verticalCenter : undefined
-                            preferredSize: JamiTheme.chatViewFooterButtonSize
-                            imageContainerWidth: 25
-                            imageContainerHeight: 25
-                            radius: 5
-
-                            hoverEnabled: !showPreview
-                            enabled: !showPreview
-
-                            toolTipText: modelData.toolTip
-                            source: modelData.iconSrc
-
-                            normalColor: JamiTheme.primaryBackgroundColor
-                            imageColor: showPreview ? JamiTheme.chatViewFooterImgDisableColor : (hovered ? JamiTheme.chatViewFooterImgHoverColor : JamiTheme.chatViewFooterImgColor)
-                            hoveredColor: JamiTheme.hoveredButtonColor
-                            pressedColor: hoveredColor
-
-                            action: modelData
-                        }
-                    }
-
-                    ListView {
-                        id: listViewMoreButton
-
-                        width: 0
-                        Behavior on width  {
-                            NumberAnimation {
-                                duration: JamiTheme.longFadeDuration / 2
-                            }
-                        }
-
-                        height: JamiTheme.chatViewFooterButtonSize
-                        orientation: ListView.Horizontal
-                        interactive: false
-
-                        leftMargin: 10
-                        rightMargin: 10
-                        spacing: 10
-
-                        property list<Action> menuMoreButton: [
-                            Action {
-                                id: leaveAudioMessage
-                                property string iconSrc: JamiResources.message_audio_black_24dp_svg
-                                property string toolTip: JamiStrings.leaveAudioMessage
-                                property bool show: false
-                                property bool needWebEngine: false
-                                property bool needVideoDevice: false
-                                property bool noSip: false
-                                onTriggered: function clickAction() {
-                                    audioRecordMessageButtonClicked();
-                                }
-                            },
-                            Action {
-                                id: leaveVideoMessage
-                                property string iconSrc: JamiResources.message_video_black_24dp_svg
-                                property string toolTip: JamiStrings.leaveVideoMessage
-                                property bool show: false
-                                property bool needWebEngine: false
-                                property bool needVideoDevice: true
-                                property bool noSip: false
-                                onTriggered: function clickAction() {
-                                    videoRecordMessageButtonClicked();
-                                }
-                            },
-                            Action {
-                                id: shareLocation
-                                property string iconSrc: JamiResources.localisation_sharing_send_pin_svg
-                                property string toolTip: JamiStrings.shareLocation
-                                property bool show: false
-                                property bool needWebEngine: true
-                                property bool needVideoDevice: false
-                                property bool noSip: false
-                                onTriggered: function clickAction() {
-                                    showMapClicked();
-                                }
-                            }
-                        ]
-
-                        ListModel {
-                            id: listMoreButton
-                            Component.onCompleted: {
-                                for (var i = 0; i < listViewMoreButton.menuMoreButton.length; i++) {
-                                    append({
-                                            "menuAction": listViewMoreButton.menuMoreButton[i]
-                                        });
-                                }
-                            }
-                        }
-
-                        model: SortFilterProxyModel {
-                            sourceModel: listMoreButton
-                            filters: [
-                                ExpressionFilter {
-                                    expression: menuAction.show === true
-                                    enabled: showDefault
-                                },
-                                ExpressionFilter {
-                                    expression: menuAction.needWebEngine === false
-                                    enabled: !WITH_WEBENGINE
-                                },
-                                ExpressionFilter {
-                                    expression: menuAction.noSip === true
-                                    enabled: CurrentConversation.isSip
-                                },
-                                ExpressionFilter {
-                                    expression: menuAction.needVideoDevice === false
-                                    enabled: VideoDevices.listSize === 0
-                                }
-                            ]
-                        }
-
-                        delegate: PushButton {
-                            id: buttonDelegateMoreButton
-                            anchors.verticalCenter: parent ? parent.verticalCenter : undefined
-                            preferredSize: JamiTheme.chatViewFooterRealButtonSize
-                            imageContainerWidth: 20
-                            imageContainerHeight: 20
-                            radius: 5
-
-                            toolTipText: modelData.toolTip
-                            source: modelData.iconSrc
-
-                            normalColor: JamiTheme.chatViewFooterListColor
-                            imageColor: JamiTheme.chatViewFooterImgHoverColor
-                            hoveredColor: JamiTheme.hoveredButtonColor
-                            pressedColor: hoveredColor
-
-                            action: modelData
-                        }
-                    }
-                }
-            }
+                visible: showTypo && messageBarTextArea.text
+                anchors.top: parent.top
+                anchors.right: parent.right
+                preferredSize: JamiTheme.chatViewFooterButtonSize
+                imageContainerWidth: 25
+                imageContainerHeight: 25
+                radius: 5
+                source: JamiResources.preview_black_24dp_svg
+                normalColor: showPreview ? hoveredColor : JamiTheme.primaryBackgroundColor
+                imageColor: (hovered || showPreview) ? JamiTheme.chatViewFooterImgHoverColor : JamiTheme.chatViewFooterImgColor
+                hoveredColor: JamiTheme.hoveredButtonColor
+                pressedColor: hoveredColor
+                toolTipText: showPreview ? JamiStrings.continueEditing : JamiStrings.showPreview
+                Layout.margins: marginSize / 2
 
-            Rectangle {
-                color: JamiTheme.transparentColor
-                visible: showTypo
-                height: 50
-                width: previewButton.width + marginSize
-                Layout.row: showTypo ? 0 : 0
-                Layout.column: showTypo ? 1 : 1
-
-                PushButton {
-                    id: previewButton
-                    anchors.verticalCenter: parent.verticalCenter
-                    anchors.right: parent.right
-                    anchors.rightMargin: marginSize
-                    preferredSize: JamiTheme.chatViewFooterButtonSize
-                    imageContainerWidth: 25
-                    imageContainerHeight: 25
-                    radius: 5
-                    source: JamiResources.preview_black_24dp_svg
-                    normalColor: showPreview ? hoveredColor : JamiTheme.primaryBackgroundColor
-                    imageColor: (hovered || showPreview) ? JamiTheme.chatViewFooterImgHoverColor : JamiTheme.chatViewFooterImgColor
-                    hoveredColor: JamiTheme.hoveredButtonColor
-                    pressedColor: hoveredColor
-                    toolTipText: showPreview ? JamiStrings.continueEditing : JamiStrings.showPreview
-
-
-                    onClicked: {
-                        showPreview = !showPreview;
-                        messageBarTextArea.showPreview = showPreview;
-                    }
+                onClicked: {
+                    showPreview = !showPreview;
+                    messageBarTextArea.showPreview = showPreview;
+                    messageBarTextArea.forceActiveFocus();
                 }
             }
         }
-    }
-
-    Rectangle {
-        Layout.preferredHeight: parent.height
-        Layout.preferredWidth: childrenRect.width
-        visible: sendButtonVisibility
-        color: JamiTheme.transparentColor
-        PushButton {
-            id: sendMessageButton
 
-            objectName: "sendMessageButton"
-            anchors.bottom: parent.bottom
-            anchors.bottomMargin: marginSize / 2
-
-            enabled: sendButtonVisibility
-            hoverEnabled: enabled
-
-            width: scale * JamiTheme.chatViewFooterButtonSize
-            height: JamiTheme.chatViewFooterButtonSize
-
-            radius: JamiTheme.chatViewFooterButtonRadius
-            preferredSize: JamiTheme.chatViewFooterButtonIconSize - 6
-            imageContainerWidth: 25
-            imageContainerHeight: 25
-
-            toolTipText: JamiStrings.send
-
-            mirror: UtilsAdapter.isRTL
-
-            source: JamiResources.send_black_24dp_svg
-
-            normalColor: enabled ? JamiTheme.chatViewFooterSendButtonColor : JamiTheme.chatViewFooterSendButtonDisableColor
-            imageColor: enabled ? JamiTheme.chatViewFooterSendButtonImgColor : JamiTheme.chatViewFooterSendButtonImgColorDisable
-            hoveredColor: JamiTheme.buttonTintedBlueHovered
-            pressedColor: hoveredColor
-
-            opacity: 1
-            scale: opacity
-
-            Behavior on opacity  {
-                enabled: animate
-                NumberAnimation {
-                    duration: JamiTheme.shortFadeDuration
-                    easing.type: Easing.InOutQuad
-                }
-            }
+        FilesToSendContainer {
+            id: dataTransferSendContainer
+
+            objectName: "dataTransferSendContainer"
+            visible: filesToSendCount > 0
+            height: visible ? JamiTheme.layoutWidthFileTransfer : 0
+            Layout.rightMargin: marginSize / 2
+            Layout.leftMargin: marginSize / 2
+            Layout.fillWidth: true
+            Layout.alignment: Qt.AlignBottom
+            Layout.preferredHeight: filesToSendCount ? JamiTheme.layoutWidthFileTransfer : 0
+            Layout.row: 1
+            Layout.column: 0
+            Layout.columnSpan: 2
+        }
 
-            onClicked: {
-                root.showPreview = false;
-                sendMessageButtonClicked();
-                root.height = root.rectHeight;
-            }
+        MessageFormatBar {
+            id: formatRow
+            color: JamiTheme.transparentColor
+            Layout.alignment: Qt.AlignBottom
+            Layout.fillWidth: maximized ? true : false
+            Layout.rightMargin: marginSize / 2
+            Layout.leftMargin: marginSize / 2
+            Layout.preferredHeight: JamiTheme.chatViewFooterButtonSize
+            Layout.row: 2
+            Layout.column: maximized ? 0 : 1
+            Layout.columnSpan: maximized ? 2 : 1
         }
     }
 }
diff --git a/src/app/mainview/components/MessageBarTextArea.qml b/src/app/mainview/components/MessageBarTextArea.qml
index 3c81acad8..ada46a915 100644
--- a/src/app/mainview/components/MessageBarTextArea.qml
+++ b/src/app/mainview/components/MessageBarTextArea.qml
@@ -17,23 +17,20 @@
  */
 import QtQuick
 import QtQuick.Controls
+import QtQuick.Layouts
+
 import net.jami.Adapters 1.1
 import net.jami.Constants 1.1
 import net.jami.Enums 1.1
 import net.jami.Models 1.1
-import "../../commoncomponents"
-import QtQuick.Layouts
+
 import SortFilterProxyModel 0.2
 
+import "../../commoncomponents"
+
 JamiFlickable {
     id: root
 
-    property int maxWidth: 330
-    property bool tooMuch: {
-        if (maxWidth > 0)
-            return textArea.contentWidth > maxWidth;
-        return false;
-    }
     property alias text: textArea.text
     property var textAreaObj: textArea
     property alias placeholderText: textArea.placeholderText
@@ -42,16 +39,15 @@ JamiFlickable {
     property alias selectionEnd: textArea.selectionEnd
     property bool showPreview: false
     property bool isShowTypo: UtilsAdapter.getAppValue(Settings.Key.ShowMardownOption)
+    property int textWidth: textArea.contentWidth
 
-    ScrollBar.vertical.visible: textArea.text
-    ScrollBar.horizontal.visible: textArea.text
+    // Used to cache the editable text when showing the preview message
+    // and also to debounce the textChanged signal's effect on the composing status.
+    property string cachedText
+    property string debounceText
 
     signal sendMessagesRequired
 
-    function heightBinding() {
-        textArea.height = Qt.binding(() => textArea.lineCount === 1 ? 35 : textArea.paintedHeight);
-    }
-
     function selectText(start, end) {
         textArea.select(start, end);
     }
@@ -60,16 +56,16 @@ JamiFlickable {
         textArea.insert(textArea.cursorPosition, text);
     }
 
+    function pasteText() {
+        textArea.paste();
+    }
+
     function clearText() {
-        var multiLine = textArea.lineCount !== 1;
         textArea.clear();
-        if (multiLine) {
-            heightBinding();
-        }
     }
 
-    function pasteText() {
-        textArea.paste();
+    function restoreVisibilityAfterSend() {
+        showPreview = false;
     }
 
     LineEditContextMenu {
@@ -84,94 +80,55 @@ JamiFlickable {
         }
     }
 
+    ScrollBar.vertical.visible: text
+    ScrollBar.horizontal.visible: text
+
+    boundsMovement: Flickable.StopAtBounds
+    boundsBehavior: Flickable.DragOverBounds
     interactive: true
-    attachedFlickableMoving: textAreaPreview.height > height || textArea.height > height || root.moving
 
-    contentHeight: showPreview ? textAreaPreview.height : textArea.height
+    function resetEditableText() {
+        textArea.text = cachedText;
+        textArea.update();
+    }
 
     onShowPreviewChanged: {
         if (showPreview) {
-            textAreaPreview.height = textArea.lineCount === 1 ? textArea.height : textAreaPreview.paintedHeight;
+            cachedText = textArea.text;
+            MessagesAdapter.parseMessage("", textArea.text, false, "", "");
+        } else {
+            textArea.textFormatChanged.disconnect(resetEditableText);
+            textArea.textFormatChanged.connect(resetEditableText);
         }
-        heightBinding();
     }
 
-    TextArea {
-        id: textAreaPreview
-
-        onWidthChanged: root.height = this.height
-
-        overwriteMode: false
-        readOnly: true
-
-        height: textArea.lineCount === 1 ? textArea.height : this.paintedHeight
-        width: textArea.width
-
-        visible: showPreview
-        leftPadding: JamiTheme.scrollBarHandleSize
-        rightPadding: JamiTheme.scrollBarHandleSize
-        topPadding: 0
-        bottomPadding: 0
-
-        Connections {
-            target: textArea
-            function onTextChanged() {
-                MessagesAdapter.parseMessage("", textArea.text, false, "", "");
+    Connections {
+        target: MessagesAdapter
+        function onMessageParsed(messageId, messageText) {
+            if (messageId === "") {
+                textArea.text = messageText;
+                textArea.update();
             }
         }
-
-        Connections {
-            target: MessagesAdapter
-            function onMessageParsed(messageId, messageText) {
-                if (messageId === "") {
-                    textAreaPreview.text = messageText;
-                }
-            }
-        }
-
-        verticalAlignment: TextEdit.AlignVCenter
-
-        font.pointSize: JamiTheme.textFontSize + 2
-        font.hintingPreference: Font.PreferNoHinting
-
-        color: JamiTheme.textColor
-        wrapMode: TextEdit.Wrap
-        textFormat: TextEdit.RichText
-        placeholderTextColor: JamiTheme.messageBarPlaceholderTextColor
-        horizontalAlignment: Text.AlignLeft
-
-        background: Rectangle {
-            border.width: 0
-            color: "transparent"
-        }
     }
 
     TextArea.flickable: TextArea {
         id: textArea
 
-        visible: !showPreview
-
+        readOnly: showPreview
         leftPadding: JamiTheme.scrollBarHandleSize
         rightPadding: JamiTheme.scrollBarHandleSize
-        topPadding: 0
-        bottomPadding: 0
-
         persistentSelection: true
-
-        height: textArea.lineCount === 1 ? 35 : textArea.paintedHeight
-
         verticalAlignment: TextEdit.AlignVCenter
-
         font.pointSize: JamiTheme.textFontSize + 2
         font.hintingPreference: Font.PreferNoHinting
-
         color: JamiTheme.textColor
         wrapMode: TextEdit.Wrap
-        selectByMouse: true
-        textFormat: TextEdit.PlainText
+        selectByMouse: !showPreview
+        textFormat: showPreview ? TextEdit.RichText : TextEdit.PlainText
+
         placeholderTextColor: JamiTheme.messageBarPlaceholderTextColor
         horizontalAlignment: Text.AlignLeft
-        property var cacheText: ""
 
         background: Rectangle {
             border.width: 0
@@ -184,8 +141,8 @@ JamiFlickable {
         }
 
         onTextChanged: {
-            if (text != cacheText) {
-                cacheText = text;
+            if (text !== debounceText && !showPreview) {
+                debounceText = text;
                 MessagesAdapter.userIsComposing(text ? true : false);
             }
         }
diff --git a/src/app/mainview/components/MessageFormatBar.qml b/src/app/mainview/components/MessageFormatBar.qml
new file mode 100644
index 000000000..dfcdc687a
--- /dev/null
+++ b/src/app/mainview/components/MessageFormatBar.qml
@@ -0,0 +1,693 @@
+/*
+ * Copyright (C) 2020-2024 Savoir-faire Linux Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+import QtQuick
+import QtQuick.Layouts
+import QtQuick.Controls
+import SortFilterProxyModel 0.2
+import net.jami.Adapters 1.1
+import net.jami.Models 1.1
+import net.jami.Enums 1.1
+import net.jami.Constants 1.1
+import "../../commoncomponents"
+import "qrc:/js/markdownedition.js" as MDE
+
+Rectangle {
+    id: messageBarRowLayout
+    Layout.preferredWidth: showTypo ? firstRow.width + secondRow.width : secondRow.width
+    LayoutMirroring.enabled: UtilsAdapter.isRTL
+    LayoutMirroring.childrenInherit: true
+
+    Row {
+        id: firstRow
+        anchors.left: messageBarRowLayout.left
+        anchors.bottom: messageBarRowLayout.bottom
+
+        Row {
+            id: listViewTypo
+            height: JamiTheme.chatViewFooterButtonSize
+
+            ListView {
+                id: listViewTypoFirst
+                objectName: "listViewTypoFirst"
+
+                visible: showTypo
+                width: visible ? contentWidth + 2 * leftMargin : 0
+
+                Behavior on width {
+                    NumberAnimation {
+                        duration: JamiTheme.longFadeDuration / 2
+                    }
+                }
+
+                height: JamiTheme.chatViewFooterButtonSize
+                orientation: ListView.Horizontal
+                interactive: false
+
+                property list<Action> menuTypoActionsFirst: [
+                    Action {
+                        id: boldAction
+                        property string iconSrc: JamiResources.bold_black_24dp_svg
+                        property string shortcutText: JamiStrings.bold
+                        property string shortcutKey: "Ctrl+B"
+                        property bool isStyle: MDE.isStyle(messageBarTextArea, rectangle.text, "**", "**")
+                        onTriggered: MDE.addStyle(messageBarTextArea, rectangle.text, "**", "**")
+                    },
+                    Action {
+                        id: italicAction
+                        property string iconSrc: JamiResources.italic_black_24dp_svg
+                        property string shortcutText: JamiStrings.italic
+                        property string shortcutKey: "Ctrl+I"
+                        property bool isStyle: MDE.isStyle(messageBarTextArea, rectangle.text, "*", "*")
+                        onTriggered: MDE.addStyle(messageBarTextArea, rectangle.text, "*", "*")
+                    },
+                    Action {
+                        id: strikethroughAction
+                        property string iconSrc: JamiResources.s_barre_black_24dp_svg
+                        property string shortcutText: JamiStrings.strikethrough
+                        property string shortcutKey: "Shift+Alt+X"
+                        property bool isStyle: MDE.isStyle(messageBarTextArea, rectangle.text, "~~", "~~")
+                        onTriggered: MDE.addStyle(messageBarTextArea, rectangle.text, "~~", "~~")
+                    },
+                    Action {
+                        id: titleAction
+                        property string iconSrc: JamiResources.title_black_24dp_svg
+                        property string shortcutText: JamiStrings.heading
+                        property string shortcutKey: "Ctrl+Alt+H"
+                        property bool isStyle: MDE.isPrefixSyle(messageBarTextArea, rectangle.text, "### ", false)
+                        onTriggered: MDE.addPrefixStyle(messageBarTextArea, rectangle.text, "### ", false)
+                    },
+                    Action {
+                        id: linkAction
+                        property string iconSrc: JamiResources.link_web_black_24dp_svg
+                        property string shortcutText: JamiStrings.link
+                        property string shortcutKey: "Ctrl+Alt+K"
+                        property bool isStyle: MDE.isStyle(messageBarTextArea, rectangle.text, "[", "](url)")
+                        onTriggered: MDE.addStyle(messageBarTextArea, rectangle.text, "[", "](url)")
+                    },
+                    Action {
+                        id: codeAction
+                        property string iconSrc: JamiResources.code_black_24dp_svg
+                        property string shortcutText: JamiStrings.code
+                        property string shortcutKey: "Ctrl+Alt+C"
+                        property bool isStyle: MDE.isStyle(messageBarTextArea, rectangle.text, "```", "```")
+                        onTriggered: MDE.addStyle(messageBarTextArea, rectangle.text, "```", "```")
+                    }
+                ]
+
+                model: menuTypoActionsFirst
+
+                delegate: PushButton {
+                    anchors.verticalCenter: parent ? parent.verticalCenter : undefined
+                    preferredSize: JamiTheme.chatViewFooterButtonSize
+                    imageContainerWidth: 15
+                    imageContainerHeight: 15
+                    radius: 5
+
+                    hoverEnabled: !showPreview
+                    enabled: !showPreview
+
+                    toolTipText: modelData.shortcutText
+                    shortcutKey: modelData.shortcutKey
+                    hasShortcut: true
+
+                    source: modelData.iconSrc
+                    focusPolicy: Qt.TabFocus
+
+                    normalColor: {
+                        if (showPreview) {
+                            return JamiTheme.primaryBackgroundColor;
+                        } else if (modelData.isStyle) {
+                            return JamiTheme.hoveredButtonColor;
+                        } else {
+                            return JamiTheme.primaryBackgroundColor;
+                        }
+                    }
+                    imageColor: {
+                        if (showPreview) {
+                            return JamiTheme.chatViewFooterImgDisableColor;
+                        } else if (hovered) {
+                            return JamiTheme.chatViewFooterImgHoverColor;
+                        } else if (modelData.isStyle) {
+                            return JamiTheme.chatViewFooterImgHoverColor;
+                        } else {
+                            return JamiTheme.chatViewFooterImgColor;
+                        }
+                    }
+                    hoveredColor: JamiTheme.hoveredButtonColor
+                    pressedColor: hoveredColor
+
+                    action: modelData
+                }
+            }
+
+            Rectangle {
+                height: JamiTheme.chatViewFooterButtonSize
+                color: JamiTheme.primaryBackgroundColor
+                visible: showTypo && showTypoSecond
+                width: 5
+
+                Rectangle {
+                    anchors.verticalCenter: parent.verticalCenter
+                    anchors.horizontalCenter: parent.horizontalCenter
+                    width: 1
+                    height: JamiTheme.chatViewFooterButtonSize * 2 / 3
+                    color: showPreview ? JamiTheme.chatViewFooterImgDisableColor : JamiTheme.chatViewFooterSeparateLineColor
+                }
+            }
+
+            Rectangle {
+                z: -1
+                radius: 0
+                color: JamiTheme.primaryBackgroundColor
+                width: JamiTheme.chatViewFooterButtonSize
+                height: JamiTheme.chatViewFooterButtonSize
+
+                visible: showTypo && !showTypoSecond
+
+                ComboBox {
+                    id: showMoreTypoButton
+                    width: JamiTheme.chatViewFooterButtonSize
+                    height: width
+                    anchors.verticalCenter: parent.verticalCenter
+                    anchors.horizontalCenter: parent.horizontalCenter
+
+                    enabled: !showPreview
+                    hoverEnabled: !showPreview
+
+                    MaterialToolTip {
+                        id: toolTip
+                        parent: showMoreTypoButton
+                        visible: showMoreTypoButton.hovered && (text.length > 0)
+                        delay: Qt.styleHints.mousePressAndHoldInterval
+                        text: markdownPopup.visible ? JamiStrings.showLess : JamiStrings.showMore
+                    }
+
+                    background: Rectangle {
+                        implicitWidth: showMoreTypoButton.width
+                        implicitHeight: showMoreTypoButton.height
+                        radius: 5
+                        color: showPreview ? JamiTheme.transparentColor : (parent && parent.hovered ? JamiTheme.hoveredButtonColor : JamiTheme.transparentColor)
+                    }
+
+                    indicator: ResponsiveImage {
+                        containerHeight: 20
+                        containerWidth: 20
+                        width: 18
+                        height: 18
+
+                        anchors.verticalCenter: parent.verticalCenter
+                        anchors.horizontalCenter: parent.horizontalCenter
+
+                        source: JamiResources.more_vert_24dp_svg
+
+                        color: showPreview ? JamiTheme.chatViewFooterImgDisableColor : (parent && parent.hovered ? JamiTheme.chatViewFooterImgHoverColor : JamiTheme.chatViewFooterImgColor)
+                    }
+
+                    popup: MarkdownPopup {
+                        id: markdownPopup
+                        y: 1.5 * parent.height
+                        x: -parent.width * 2
+                        width: listViewTypoSecond.width + 10
+                        height: JamiTheme.chatViewFooterButtonSize
+
+                        menuTypoActionsSecond: listViewTypoSecond.menuTypoActionsSecond
+                    }
+                }
+            }
+
+            ListView {
+                id: listViewTypoSecond
+                visible: showTypo && showTypoSecond
+                width: contentWidth + 2 * leftMargin
+
+                height: JamiTheme.chatViewFooterButtonSize
+                orientation: ListView.Horizontal
+                interactive: false
+
+                Rectangle {
+                    anchors.fill: parent
+                    color: JamiTheme.transparentColor
+                    z: -1
+                }
+
+                property list<Action> menuTypoActionsSecond: [
+                    Action {
+                        id: quoteAction
+                        property string iconSrc: JamiResources.quote_black_24dp_svg
+                        property string shortcutText: JamiStrings.quote
+                        property string shortcutKey: "Shift+Alt+9"
+                        property bool isStyle: MDE.isPrefixSyle(messageBarTextArea, rectangle.text, "> ", false)
+                        onTriggered: MDE.addPrefixStyle(messageBarTextArea, rectangle.text, "> ", false)
+                    },
+                    Action {
+                        id: unorderedListAction
+                        property string iconSrc: JamiResources.bullet_point_black_24dp_svg
+                        property string shortcutText: JamiStrings.unorderedList
+                        property string shortcutKey: "Shift+Alt+8"
+                        property bool isStyle: MDE.isPrefixSyle(messageBarTextArea, rectangle.text, "- ", false)
+                        onTriggered: MDE.addPrefixStyle(messageBarTextArea, rectangle.text, "- ", false)
+                    },
+                    Action {
+                        id: orderedListAction
+                        property string iconSrc: JamiResources.bullet_number_black_24dp_svg
+                        property string shortcutText: JamiStrings.orderedList
+                        property string shortcutKey: "Shift+Alt+7"
+                        property bool isStyle: MDE.isPrefixSyle(messageBarTextArea, rectangle.text, "", true)
+                        onTriggered: MDE.addPrefixStyle(messageBarTextArea, rectangle.text, "", true)
+                    }
+                ]
+
+                model: menuTypoActionsSecond
+
+                delegate: PushButton {
+                    anchors.verticalCenter: parent ? parent.verticalCenter : undefined
+                    preferredSize: JamiTheme.chatViewFooterButtonSize
+                    imageContainerWidth: 20
+                    imageContainerHeight: 20
+                    radius: 5
+
+                    hoverEnabled: !showPreview
+                    enabled: !showPreview
+
+                    toolTipText: modelData.shortcutText
+                    shortcutKey: modelData.shortcutKey
+                    hasShortcut: modelData.hasShortcut ? true : false
+                    source: modelData.iconSrc
+                    focusPolicy: Qt.TabFocus
+
+                    normalColor: {
+                        if (showPreview) {
+                            return JamiTheme.primaryBackgroundColor;
+                        } else if (modelData.normalColor) {
+                            return modelData.normalColor;
+                        } else if (modelData.isStyle) {
+                            return JamiTheme.hoveredButtonColor;
+                        } else {
+                            return JamiTheme.primaryBackgroundColor;
+                        }
+                    }
+                    imageColor: {
+                        if (showPreview) {
+                            return JamiTheme.chatViewFooterImgDisableColor;
+                        } else if (hovered) {
+                            return JamiTheme.chatViewFooterImgHoverColor;
+                        } else if (modelData.isStyle) {
+                            return JamiTheme.chatViewFooterImgHoverColor;
+                        } else {
+                            return JamiTheme.chatViewFooterImgColor;
+                        }
+                    }
+                    hoveredColor: JamiTheme.hoveredButtonColor
+                    pressedColor: hoveredColor
+
+                    action: modelData
+                }
+            }
+        }
+    }
+
+    Row {
+        id: secondRow
+        anchors.right: messageBarRowLayout.right
+        anchors.bottom: messageBarRowLayout.bottom
+
+        PushButton {
+            id: typoButton
+
+            preferredSize: JamiTheme.chatViewFooterButtonSize
+            imageContainerWidth: 24
+            imageContainerHeight: 24
+
+            radius: JamiTheme.chatViewFooterButtonRadius
+
+            hoverEnabled: !showPreview
+            enabled: !showPreview
+
+            toolTipText: showTypo ? JamiStrings.hideFormatting : JamiStrings.showFormatting
+            source: JamiResources.text_edit_black_24dp_svg
+
+            normalColor: showPreview ? JamiTheme.primaryBackgroundColor : (showTypo ? JamiTheme.hoveredButtonColor : JamiTheme.primaryBackgroundColor)
+            imageColor: showPreview ? JamiTheme.chatViewFooterImgDisableColor : (hovered || showTypo ? JamiTheme.chatViewFooterImgHoverColor : JamiTheme.chatViewFooterImgColor)
+            hoveredColor: JamiTheme.hoveredButtonColor
+            pressedColor: hoveredColor
+
+            onClicked: {
+                showTypo = !showTypo;
+                messageBarTextArea.isShowTypo = showTypo;
+                if (messageBar.width < messageBarLayoutMaximumWidth + sendMessageButton.width + 2 * JamiTheme.preferredMarginSize)
+                    showTypoSecond = false;
+                if (!showDefault)
+                    showDefault = true;
+                UtilsAdapter.setAppValue(Settings.Key.ShowMardownOption, showTypo);
+                UtilsAdapter.setAppValue(Settings.Key.ShowSendOption, !showDefault);
+            }
+        }
+
+        ListView {
+            id: listViewMoreButton
+
+            width: 0
+            Behavior on width {
+                NumberAnimation {
+                    duration: JamiTheme.longFadeDuration / 2
+                }
+            }
+
+            height: JamiTheme.chatViewFooterButtonSize
+            orientation: ListView.Horizontal
+            interactive: false
+
+            leftMargin: 10
+            rightMargin: 10
+            property list<Action> menuMoreButton: [
+                Action {
+                    id: leaveAudioMessage
+                    property string iconSrc: JamiResources.message_audio_black_24dp_svg
+                    property string toolTip: JamiStrings.leaveAudioMessage
+                    property bool show: false
+                    property bool needWebEngine: false
+                    property bool needVideoDevice: false
+                    property bool noSip: false
+                    onTriggered: function clickAction() {
+                        audioRecordMessageButtonClicked();
+                    }
+                },
+                Action {
+                    id: leaveVideoMessage
+                    property string iconSrc: JamiResources.message_video_black_24dp_svg
+                    property string toolTip: JamiStrings.leaveVideoMessage
+                    property bool show: false
+                    property bool needWebEngine: false
+                    property bool needVideoDevice: true
+                    property bool noSip: false
+                    onTriggered: function clickAction() {
+                        videoRecordMessageButtonClicked();
+                    }
+                },
+                Action {
+                    id: shareLocation
+                    property string iconSrc: JamiResources.localisation_sharing_send_pin_svg
+                    property string toolTip: JamiStrings.shareLocation
+                    property bool show: false
+                    property bool needWebEngine: true
+                    property bool needVideoDevice: false
+                    property bool noSip: false
+                    onTriggered: function clickAction() {
+                        showMapClicked();
+                    }
+                }
+            ]
+
+            ListModel {
+                id: listMoreButton
+                Component.onCompleted: {
+                    for (var i = 0; i < listViewMoreButton.menuMoreButton.length; i++) {
+                        append({
+                                "menuAction": listViewMoreButton.menuMoreButton[i]
+                            });
+                    }
+                }
+            }
+
+            model: SortFilterProxyModel {
+                sourceModel: listMoreButton
+                filters: [
+                    ExpressionFilter {
+                        expression: menuAction.show === true
+                        enabled: showDefault
+                    },
+                    ExpressionFilter {
+                        expression: menuAction.needWebEngine === false
+                        enabled: !WITH_WEBENGINE
+                    },
+                    ExpressionFilter {
+                        expression: menuAction.noSip === true
+                        enabled: CurrentConversation.isSip
+                    },
+                    ExpressionFilter {
+                        expression: menuAction.needVideoDevice === false
+                        enabled: VideoDevices.listSize === 0
+                    }
+                ]
+            }
+
+            delegate: PushButton {
+                id: buttonDelegateMoreButton
+                anchors.verticalCenter: parent ? parent.verticalCenter : undefined
+                preferredSize: JamiTheme.chatViewFooterButtonSize
+                imageContainerWidth: 20
+                imageContainerHeight: 20
+                radius: 5
+                enabled: !showPreview
+                hoverEnabled: !showPreview
+                toolTipText: modelData.toolTip
+                source: modelData.iconSrc
+
+                normalColor: showPreview ? JamiTheme.primaryBackgroundColor : (showTypo ? JamiTheme.hoveredButtonColor : JamiTheme.primaryBackgroundColor)
+                imageColor: showPreview ? JamiTheme.chatViewFooterImgDisableColor : (hovered ? JamiTheme.chatViewFooterImgHoverColor : JamiTheme.chatViewFooterImgColor)
+                hoveredColor: JamiTheme.hoveredButtonColor
+                pressedColor: hoveredColor
+                action: modelData
+            }
+        }
+
+        Rectangle {
+            height: JamiTheme.chatViewFooterButtonSize
+            width: JamiTheme.chatViewFooterButtonSize
+            Layout.alignment: Qt.AlignRight
+            visible: !CurrentConversation.isSip
+            color: JamiTheme.transparentColor
+            ComboBox {
+                id: showMoreButton
+                focus: true
+                width: JamiTheme.chatViewFooterButtonSize
+                height: JamiTheme.chatViewFooterButtonSize
+                anchors.bottom: parent.bottom
+                enabled: !showPreview
+                hoverEnabled: !showPreview
+
+                // Used to choose the correct color for the button.
+                readonly property bool highlight: down || hovered
+
+                background: Rectangle {
+                    implicitWidth: showMoreButton.width
+                    implicitHeight: showMoreButton.height
+                    radius: 5
+                    color: showMoreButton.highlight ? JamiTheme.hoveredButtonColor : JamiTheme.transparentColor
+                }
+
+                MaterialToolTip {
+                    id: toolTipMoreButton
+
+                    parent: showMoreButton
+                    visible: showMoreButton.hovered && (text.length > 0)
+                    delay: Qt.styleHints.mousePressAndHoldInterval
+                    text: showMoreButton.down ? JamiStrings.showLess : JamiStrings.showMore
+                }
+
+                indicator: ResponsiveImage {
+
+                    width: 20
+                    height: 20
+
+                    anchors.verticalCenter: parent.verticalCenter
+                    anchors.horizontalCenter: parent.horizontalCenter
+
+                    source: JamiResources.more_menu_black_24dp_svg
+
+                    color: showPreview ? JamiTheme.chatViewFooterImgDisableColor : (hovered ? JamiTheme.chatViewFooterImgHoverColor : JamiTheme.chatViewFooterImgColor)
+                }
+
+                Component {
+                    id: sharePopupComp
+                    ShareMenu {
+                        id: sharePopup
+                        onAudioRecordMessageButtonClicked: rectangle.audioRecordMessageButtonClicked()
+                        onVideoRecordMessageButtonClicked: rectangle.videoRecordMessageButtonClicked()
+                        onShowMapClicked: rectangle.showMapClicked()
+                        modelList: listViewMoreButton.menuMoreButton
+                        y: showMoreButton.y + 31
+                        x: showMoreButton.x - 3
+                    }
+                }
+
+                popup: ShareMenu {
+                    id: sharePopup
+                    onAudioRecordMessageButtonClicked: rectangle.audioRecordMessageButtonClicked()
+                    onVideoRecordMessageButtonClicked: rectangle.videoRecordMessageButtonClicked()
+                    onShowMapClicked: rectangle.showMapClicked()
+                    modelList: listViewMoreButton.menuMoreButton
+                    y: showMoreButton.y + 31
+                    x: showMoreButton.x - 3
+                }
+            }
+        }
+
+        ListView {
+            id: listViewAction
+
+            width: contentWidth + 2 * leftMargin
+
+            Behavior on width {
+                NumberAnimation {
+                    duration: JamiTheme.longFadeDuration / 2
+                }
+            }
+
+            height: JamiTheme.chatViewFooterButtonSize
+            orientation: ListView.Horizontal
+            interactive: false
+
+            property list<Action> menuActions: [
+                Action {
+                    id: sendFile
+                    property string iconSrc: JamiResources.link_black_24dp_svg
+                    property string toolTip: JamiStrings.sendFile
+                    property bool show: true
+                    property bool needWebEngine: false
+                    property bool needVideoDevice: false
+                    property bool noSip: false
+                    onTriggered: function clickAction() {
+                        sendFileButtonClicked();
+                        textAreaObj.forceActiveFocus();
+                    }
+                },
+                Action {
+                    id: addEmoji
+                    property string iconSrc: JamiResources.emoji_black_24dp_svg
+                    property string toolTip: JamiStrings.addEmoji
+                    property bool show: true
+                    property bool needWebEngine: true
+                    property bool needVideoDevice: false
+                    property bool noSip: true
+                    onTriggered: function clickAction() {
+                        emojiButtonClicked();
+                    }
+                }
+            ]
+
+            ListModel {
+                id: listActions
+                Component.onCompleted: {
+                    for (var i = 0; i < listViewAction.menuActions.length; i++) {
+                        append({
+                                "menuAction": listViewAction.menuActions[i]
+                            });
+                    }
+                }
+            }
+
+            model: SortFilterProxyModel {
+                sourceModel: listActions
+                filters: [
+                    ExpressionFilter {
+                        expression: menuAction.show === true
+                        enabled: rectangle.showDefault
+                    },
+                    ExpressionFilter {
+                        expression: menuAction.needWebEngine === false
+                        enabled: !WITH_WEBENGINE
+                    },
+                    ExpressionFilter {
+                        expression: menuAction.noSip === true
+                        enabled: CurrentConversation.isSip
+                    },
+                    ExpressionFilter {
+                        expression: menuAction.needVideoDevice === false
+                        enabled: VideoDevices.listSize === 0
+                    }
+                ]
+            }
+
+            delegate: PushButton {
+                id: buttonDelegate
+                anchors.verticalCenter: parent ? parent.verticalCenter : undefined
+                preferredSize: JamiTheme.chatViewFooterButtonSize
+                imageContainerWidth: 25
+                imageContainerHeight: 25
+                radius: 5
+
+                hoverEnabled: !showPreview
+                enabled: !showPreview
+
+                toolTipText: modelData.toolTip
+                source: modelData.iconSrc
+
+                normalColor: JamiTheme.primaryBackgroundColor
+                imageColor: showPreview ? JamiTheme.chatViewFooterImgDisableColor : (hovered ? JamiTheme.chatViewFooterImgHoverColor : JamiTheme.chatViewFooterImgColor)
+                hoveredColor: JamiTheme.hoveredButtonColor
+                pressedColor: hoveredColor
+
+                action: modelData
+            }
+        }
+
+        Rectangle {
+            Layout.alignment: Qt.AlignRight
+            height: JamiTheme.chatViewFooterButtonSize
+            width: JamiTheme.chatViewFooterButtonSize
+            Layout.rightMargin: marginSize / 2
+            visible: true
+            color: JamiTheme.transparentColor
+
+            PushButton {
+                id: sendMessageButton
+
+                objectName: "sendMessageButton"
+                anchors.bottom: parent.bottom
+
+                enabled: sendButtonVisibility
+                hoverEnabled: enabled
+
+                width: scale * JamiTheme.chatViewFooterButtonSize
+                height: JamiTheme.chatViewFooterButtonSize
+
+                radius: JamiTheme.chatViewFooterButtonRadius
+                preferredSize: JamiTheme.chatViewFooterButtonIconSize - 6
+                imageContainerWidth: 25
+                imageContainerHeight: 25
+
+                toolTipText: JamiStrings.send
+
+                mirror: UtilsAdapter.isRTL
+
+                source: JamiResources.send_black_24dp_svg
+
+                normalColor: enabled ? JamiTheme.chatViewFooterSendButtonColor : JamiTheme.chatViewFooterSendButtonDisableColor
+                imageColor: enabled ? JamiTheme.chatViewFooterSendButtonImgColor : JamiTheme.chatViewFooterSendButtonImgColorDisable
+                hoveredColor: JamiTheme.buttonTintedBlueHovered
+                pressedColor: hoveredColor
+
+                opacity: 1
+                scale: opacity
+
+                Behavior on opacity {
+                    enabled: animate
+                    NumberAnimation {
+                        duration: JamiTheme.shortFadeDuration
+                        easing.type: Easing.InOutQuad
+                    }
+                }
+
+                onClicked: {
+                    rectangle.showPreview = false;
+                    sendMessageButtonClicked();
+                }
+            }
+        }
+    }
+}
diff --git a/src/app/mainview/components/MessageListView.qml b/src/app/mainview/components/MessageListView.qml
index 11961b2b4..fe7caf8aa 100644
--- a/src/app/mainview/components/MessageListView.qml
+++ b/src/app/mainview/components/MessageListView.qml
@@ -19,40 +19,37 @@ import QtQuick
 import QtQuick.Controls
 import QtQuick.Layouts
 import Qt.labs.qmlmodels
-
 import net.jami.Models 1.1
 import net.jami.Adapters 1.1
 import net.jami.Constants 1.1
-
 import "../../commoncomponents"
 
 JamiListView {
     id: root
 
     function getDistanceToBottom() {
-        const scrollDiff = ScrollBar.vertical.position -
-                         (1.0 - ScrollBar.vertical.size)
-        return Math.abs(scrollDiff) * contentHeight
+        const scrollDiff = ScrollBar.vertical.position - (1.0 - ScrollBar.vertical.size);
+        return Math.abs(scrollDiff) * contentHeight;
     }
 
     function loadMoreMsgsIfNeeded() {
         if (atYBeginning && !CurrentConversation.allMessagesLoaded) {
-            MessagesAdapter.loadMoreMessages()
+            MessagesAdapter.loadMoreMessages();
         }
     }
 
     function computeTimestampVisibility(item1, item1Index, item2, item2Index) {
         if (item1 && item2) {
             if (item1Index < item2Index) {
-                item1.showTime = item1.timestamp - item2.timestamp > JamiTheme.timestampIntervalTime
-                item1.showDay = item1.formattedDay !== item2.formattedDay
+                item1.showTime = item1.timestamp - item2.timestamp > JamiTheme.timestampIntervalTime;
+                item1.showDay = item1.formattedDay !== item2.formattedDay;
             } else {
-                item2.showTime = item2.timestamp - item1.timestamp > JamiTheme.timestampIntervalTime
-                item2.showDay = item2.formattedDay !== item1.formattedDay
+                item2.showTime = item2.timestamp - item1.timestamp > JamiTheme.timestampIntervalTime;
+                item2.showDay = item2.formattedDay !== item1.formattedDay;
             }
-            return true
+            return true;
         }
-        return false
+        return false;
     }
 
     function scrollToBottom() {
@@ -60,27 +57,28 @@ JamiListView {
     }
 
     function computeChatview(item, itemIndex) {
-        if (!root) return
-        var rootItem = root.itemAtIndex(0)
-        var pItem = root.itemAtIndex(itemIndex - 1)
-        var pItemIndex = itemIndex - 1
-        var nItem = root.itemAtIndex(itemIndex + 1)
-        var nItemIndex = itemIndex + 1
+        if (!root)
+            return;
+        var rootItem = root.itemAtIndex(0);
+        var pItem = root.itemAtIndex(itemIndex - 1);
+        var pItemIndex = itemIndex - 1;
+        var nItem = root.itemAtIndex(itemIndex + 1);
+        var nItemIndex = itemIndex + 1;
 
         // middle insertion
         if (pItem && nItem) {
-            computeTimestampVisibility(item, itemIndex, nItem, nItemIndex)
-            computeSequencing(item, nItem, root.itemAtIndex(itemIndex + 2))
+            computeTimestampVisibility(item, itemIndex, nItem, nItemIndex);
+            computeSequencing(item, nItem, root.itemAtIndex(itemIndex + 2));
         }
         // top buffer insertion = scroll up
         if (pItem && !nItem) {
-            computeTimestampVisibility(item, itemIndex, pItem, pItemIndex)
-            computeSequencing(root.itemAtIndex(itemIndex - 2), pItem, item)
+            computeTimestampVisibility(item, itemIndex, pItem, pItemIndex);
+            computeSequencing(root.itemAtIndex(itemIndex - 2), pItem, item);
         }
         // bottom buffer insertion = scroll down
         if (!pItem && nItem) {
-            computeTimestampVisibility(item, itemIndex, nItem, nItemIndex)
-            computeSequencing(item, nItem, root.itemAtIndex(itemIndex + 2))
+            computeTimestampVisibility(item, itemIndex, nItem, nItemIndex);
+            computeSequencing(item, nItem, root.itemAtIndex(itemIndex + 2));
         }
         // index 0 insertion = new message
         if (itemIndex === 0) {
@@ -88,57 +86,56 @@ JamiListView {
             // This needs to be done in a delayed fashion because the new message is inserted
             // at the top of the list and the list is not yet updated.
             Qt.callLater(() => {
-                var fItem = root.itemAtIndex(1)
-                if (fItem) {
-                    computeTimestampVisibility(item, 0, fItem, 1)
-                    computeSequencing(null, item, fItem)
-                    computeSequencing(item, fItem, root.itemAtIndex(2))
-                }
-            })
+                    var fItem = root.itemAtIndex(1);
+                    if (fItem) {
+                        computeTimestampVisibility(item, 0, fItem, 1);
+                        computeSequencing(null, item, fItem);
+                        computeSequencing(item, fItem, root.itemAtIndex(2));
+                    }
+                });
         }
         // top element
-        if(itemIndex === root.count - 1 && CurrentConversation.allMessagesLoaded) {
-            item.showTime = true
-            item.showDay = true
+        if (itemIndex === root.count - 1 && CurrentConversation.allMessagesLoaded) {
+            item.showTime = true;
+            item.showDay = true;
         }
     }
 
     function computeSequencing(pItem, item, nItem) {
         if (root === undefined || !item)
-            return
-
+            return;
         function isFirst() {
-            if (!nItem) return true
+            if (!nItem)
+                return true;
             else {
-                if (item.showTime || item.isReply ) {
-                    return true
+                if (item.showTime || item.isReply) {
+                    return true;
                 } else if (nItem.author !== item.author) {
-                    return true
+                    return true;
                 }
             }
-            return false
+            return false;
         }
-
         function isLast() {
-            if (!pItem) return true
+            if (!pItem)
+                return true;
             else {
                 if (pItem.showTime || pItem.isReply) {
-                    return true
+                    return true;
                 } else if (pItem.author !== item.author) {
-                    return true
+                    return true;
                 }
             }
-            return false
+            return false;
         }
-
         if (isLast() && isFirst())
-            item.seq = MsgSeq.single
+            item.seq = MsgSeq.single;
         if (!isLast() && isFirst())
-            item.seq = MsgSeq.first
+            item.seq = MsgSeq.first;
         if (isLast() && !isFirst())
-            item.seq = MsgSeq.last
+            item.seq = MsgSeq.last;
         if (!isLast() && !isFirst())
-            item.seq = MsgSeq.middle
+            item.seq = MsgSeq.middle;
     }
 
     // fade-in mechanism
@@ -151,12 +148,16 @@ JamiListView {
         SequentialAnimation {
             id: fadeAnimation
             NumberAnimation {
-                target: overlay; property: "opacity"
-                to: 1; duration: 0
+                target: overlay
+                property: "opacity"
+                to: 1
+                duration: 0
             }
             NumberAnimation {
-                target: overlay; property: "opacity"
-                to: 0; duration: 240
+                target: overlay
+                property: "opacity"
+                to: 0
+                duration: 240
             }
         }
     }
@@ -167,7 +168,7 @@ JamiListView {
         anchors.fill: parent
 
         function instantiateToast(dest) {
-            instantiate(JamiStrings.fileSaved.arg(dest), 1000, 400)
+            instantiate(JamiStrings.fileSaved.arg(dest), 1000, 400);
         }
     }
 
@@ -175,8 +176,8 @@ JamiListView {
         target: CurrentConversation
         function onScrollTo(id) {
             // Get the filtered index from the interaction ID.
-            var idx = MessagesAdapter.messageListModel.getDisplayIndex(id)
-            positionViewAtIndex(idx, ListView.Visible)
+            var idx = MessagesAdapter.messageListModel.getDisplayIndex(id);
+            positionViewAtIndex(idx, ListView.Visible);
         }
     }
 
@@ -203,8 +204,8 @@ JamiListView {
             roleValue: Interaction.Type.TEXT
 
             TextMessageDelegate {
-                Component.onCompleted:  {
-                    computeChatview(this, index)
+                Component.onCompleted: {
+                    computeChatview(this, index);
                 }
             }
         }
@@ -213,8 +214,8 @@ JamiListView {
             roleValue: Interaction.Type.CALL
 
             CallMessageDelegate {
-                Component.onCompleted:  {
-                    computeChatview(this, index)
+                Component.onCompleted: {
+                    computeChatview(this, index);
                 }
             }
         }
@@ -223,8 +224,8 @@ JamiListView {
             roleValue: Interaction.Type.CONTACT
 
             ContactMessageDelegate {
-                Component.onCompleted:  {
-                    computeChatview(this, index)
+                Component.onCompleted: {
+                    computeChatview(this, index);
                 }
             }
         }
@@ -234,8 +235,8 @@ JamiListView {
 
             GeneratedMessageDelegate {
                 font.bold: true
-                Component.onCompleted:  {
-                    computeChatview(this, index)
+                Component.onCompleted: {
+                    computeChatview(this, index);
                 }
             }
         }
@@ -244,12 +245,11 @@ JamiListView {
             roleValue: Interaction.Type.DATA_TRANSFER
 
             DataTransferMessageDelegate {
-                Component.onCompleted:  {
-                    computeChatview(this, index)
+                Component.onCompleted: {
+                    computeChatview(this, index);
                 }
             }
         }
-
     }
 
     onAtYBeginningChanged: loadMoreMsgsIfNeeded()
@@ -271,9 +271,8 @@ JamiListView {
         target: MessagesAdapter
 
         function onNewInteraction() {
-            if (root.getDistanceToBottom() < 80 &&
-                    !root.atYEnd) {
-                Qt.callLater(root.positionViewAtBeginning)
+            if (root.getDistanceToBottom() < 80 && !root.atYEnd) {
+                Qt.callLater(root.positionViewAtBeginning);
             }
         }
 
@@ -284,7 +283,7 @@ JamiListView {
         }
 
         function onFileCopied(dest) {
-            toastManager.instantiateToast(dest)
+            toastManager.instantiateToast(dest);
         }
     }
 
@@ -294,7 +293,7 @@ JamiListView {
         anchors.bottom: root.bottom
         anchors.bottomMargin: JamiTheme.chatViewScrollToBottomButtonBottomMargin
         anchors.horizontalCenter: root.horizontalCenter
-        visible:  1 - verticalScrollBar.position >= verticalScrollBar.size * 2
+        visible: 1 - verticalScrollBar.position >= verticalScrollBar.size * 2
 
         onClicked: scrollToBottom()
     }
@@ -326,36 +325,31 @@ JamiListView {
             Connections {
                 target: MessagesAdapter
 
-                function onCurrentConvComposingListChanged () {
-                    var typeIndicatorNameTextString = ""
-                    var nameList = MessagesAdapter.currentConvComposingList
-
+                function onCurrentConvComposingListChanged() {
+                    var typeIndicatorNameTextString = "";
+                    var nameList = MessagesAdapter.currentConvComposingList;
                     if (nameList.length > 4) {
-                        typeIndicatorNameText.text = ""
-                        typeIndicatorEndingText.text = JamiStrings.typeIndicatorMax
-                        typeIndicatorNameText.calculateWidth()
-                        return
+                        typeIndicatorNameText.text = "";
+                        typeIndicatorEndingText.text = JamiStrings.typeIndicatorMax;
+                        typeIndicatorNameText.calculateWidth();
+                        return;
                     }
                     if (nameList.length === 1) {
-                        typeIndicatorNameText.text = nameList[0]
-                        typeIndicatorEndingText.text =
-                                JamiStrings.typeIndicatorSingle.replace("{}", "")
-                        typeIndicatorNameText.calculateWidth()
-                        return
+                        typeIndicatorNameText.text = nameList[0];
+                        typeIndicatorEndingText.text = JamiStrings.typeIndicatorSingle.replace("{}", "");
+                        typeIndicatorNameText.calculateWidth();
+                        return;
                     }
-
                     for (var i = 0; i < nameList.length; i++) {
-                        typeIndicatorNameTextString += nameList[i]
-
+                        typeIndicatorNameTextString += nameList[i];
                         if (i === nameList.length - 2)
-                            typeIndicatorNameTextString += JamiStrings.typeIndicatorAnd
+                            typeIndicatorNameTextString += JamiStrings.typeIndicatorAnd;
                         else if (i !== nameList.length - 1)
-                            typeIndicatorNameTextString += ", "
+                            typeIndicatorNameTextString += ", ";
                     }
-                    typeIndicatorNameText.text = typeIndicatorNameTextString
-                    typeIndicatorEndingText.text =
-                            JamiStrings.typeIndicatorPlural.replace("{}", "")
-                    typeIndicatorNameText.calculateWidth()
+                    typeIndicatorNameText.text = typeIndicatorNameTextString;
+                    typeIndicatorEndingText.text = JamiStrings.typeIndicatorPlural.replace("{}", "");
+                    typeIndicatorNameText.calculateWidth();
                 }
             }
 
@@ -364,17 +358,13 @@ JamiListView {
 
                 property int textWidth: 0
 
-                function calculateWidth () {
+                function calculateWidth() {
                     if (!text)
-                        return 0
+                        return 0;
                     else {
-                        var textSize = JamiQmlUtils.getTextBoundingRect(font, text).width
-                        var typingContentWidth = typingDots.width + typingDots.anchors.leftMargin
-                                + typeIndicatorNameText.anchors.leftMargin
-                                + typeIndicatorEndingText.contentWidth
-                        typeIndicatorNameText.Layout.preferredWidth =
-                                Math.min(typeIndicatorContainer.width - 5 - typingContentWidth,
-                                         textSize)
+                        var textSize = JamiQmlUtils.getTextBoundingRect(font, text).width;
+                        var typingContentWidth = typingDots.width + typingDots.anchors.leftMargin + typeIndicatorNameText.anchors.leftMargin + typeIndicatorEndingText.contentWidth;
+                        typeIndicatorNameText.Layout.preferredWidth = Math.min(typeIndicatorContainer.width - 5 - typingContentWidth, textSize);
                     }
                 }
 
diff --git a/src/app/mainview/components/MessagesResearchPanel.qml b/src/app/mainview/components/MessagesResearchPanel.qml
index cbe1195e9..717b81218 100644
--- a/src/app/mainview/components/MessagesResearchPanel.qml
+++ b/src/app/mainview/components/MessagesResearchPanel.qml
@@ -98,7 +98,6 @@ Page {
                 underlineColor: CurrentConversation.color
                 underlineColorHovered: CurrentConversation.color
 
-
                 down: researchTabBar.currentIndex === 1
                 labelText: JamiStrings.files
                 Layout.fillWidth: true
diff --git a/src/app/net/jami/Constants/JamiTheme.qml b/src/app/net/jami/Constants/JamiTheme.qml
index 0735aa592..2f148072c 100644
--- a/src/app/net/jami/Constants/JamiTheme.qml
+++ b/src/app/net/jami/Constants/JamiTheme.qml
@@ -513,6 +513,9 @@ Item {
     // MessageBar
     property int messageBarMarginSize: 10
     property int messageBarMinimumWidth: 438
+    property int showTypoSecondToggleWidth: 540
+    property int messageBarMaximumHeight: 150
+    property int messageBarMinimumHeight: 36
 
     // InvitationView
     property real invitationViewAvatarSize: 112
diff --git a/tests/qml/src/tst_ChatViewFooter.qml b/tests/qml/src/tst_ChatViewFooter.qml
index a100fe858..37f16ed33 100644
--- a/tests/qml/src/tst_ChatViewFooter.qml
+++ b/tests/qml/src/tst_ChatViewFooter.qml
@@ -53,19 +53,19 @@ ColumnLayout {
                 var sendMessageButton = findChild(uut, "sendMessageButton")
                 var messageBarTextArea = findChild(uut, "messageBarTextArea")
 
-                compare(sendMessageButton.visible, false)
+                compare(sendMessageButton.enabled, false)
 
                 // Text in messageBarTextArea will cause sendMessageButton to show
                 messageBarTextArea.insertText("test")
-                compare(sendMessageButton.visible, true)
+                compare(sendMessageButton.enabled, true)
 
                 // Text cleared in messageBarTextArea will cause sendMessageButton to hide
                 messageBarTextArea.clearText()
-                compare(sendMessageButton.visible, false)
+                compare(sendMessageButton.enabled, false)
 
                 // Both are cleared
                 messageBarTextArea.clearText()
-                compare(sendMessageButton.visible, false)
+                compare(sendMessageButton.enabled, false)
             }
         }
     }
-- 
GitLab