diff --git a/qml.qrc b/qml.qrc
index db29de3b8b1abe9a38e05d3960851ee564a5efbe..99bff5e8ec0024b2978b55443bc6a5a6059ee674 100644
--- a/qml.qrc
+++ b/qml.qrc
@@ -203,5 +203,6 @@
         <file>src/app/mainview/components/CustomizeTipBox.qml</file>
         <file>src/app/mainview/components/BackupTipBox.qml</file>
         <file>src/app/mainview/components/InformativeTipBox.qml</file>
+        <file>src/app/commoncomponents/TimestampInfo.qml</file>
     </qresource>
 </RCC>
diff --git a/src/app/commoncomponents/ContactMessageDelegate.qml b/src/app/commoncomponents/ContactMessageDelegate.qml
index b79cf28e8621e2f37648797466c4b60b7aaaa2ed..33c82aceb2424bf46721340bbabc1e111cb71620 100644
--- a/src/app/commoncomponents/ContactMessageDelegate.qml
+++ b/src/app/commoncomponents/ContactMessageDelegate.qml
@@ -27,74 +27,67 @@ Column {
     id: root
 
     property bool showTime: false
-    property int seq: MsgSeq.single
-    property alias font: textLabel.font
-
+    property bool showDay: false
+    property int timestamp: Timestamp
+    property string formattedTime: MessagesAdapter.getFormattedTime(Timestamp)
+    property string formattedDay: MessagesAdapter.getFormattedDay(Timestamp)
+    property int seq: MsgSeq.single//a changer par textlabel
     width: ListView.view ? ListView.view.width : 0
-
     spacing: 2
     topPadding: 12
     bottomPadding: 12
 
-    Rectangle {
-        id: msg
-
+    ColumnLayout {
         anchors.horizontalCenter: parent.horizontalCenter
 
-        width: childrenRect.width
-        height: JamiTheme.contactMessageAvatarSize + 12
-        radius: JamiTheme.contactMessageAvatarSize / 2 + 6
-
-        color: "transparent"
-        border.width: 1
-        border.color: CurrentConversation.isCoreDialog ? JamiTheme.messageInBgColor : CurrentConversation.color
-
-        RowLayout {
-            anchors.verticalCenter: parent.verticalCenter
-
-            Avatar {
-                Layout.leftMargin: 6
-
-                width: JamiTheme.contactMessageAvatarSize
-                height: JamiTheme.contactMessageAvatarSize
-                visible: ActionUri !== ""
-
-                imageId: ActionUri !== CurrentAccount.uri ? ActionUri : CurrentAccount.id
-                showPresenceIndicator: false
-                mode: ActionUri !== CurrentAccount.uri ? Avatar.Mode.Contact : Avatar.Mode.Account
-            }
+        TimestampInfo {
+            id:timestampItem
 
-            Label {
-                Layout.rightMargin: 6
-
-                id: textLabel
-                width: parent.width
-                text: Body
-                horizontalAlignment: Qt.AlignHCenter
-                font.pointSize: JamiTheme.contactEventPointSize
-                font.bold: true
-                color: JamiTheme.chatviewTextColor
-            }
+            showDay: root.showDay
+            showTime: root.showTime
+            formattedTime: root.formattedTime
+            formattedDay: root.formattedDay
+            Layout.alignment: Qt.AlignHCenter
         }
-    }
-
-    Item {
-        id: infoCell
 
-        width: parent.width
-        height: childrenRect.height
-
-        Label {
-            text: MessagesAdapter.getFormattedTime(Timestamp)
-            color: JamiTheme.timestampColor
-            visible: showTime || seq === MsgSeq.last
-            height: visible * implicitHeight
-            font.pointSize: 9
-
-            anchors.horizontalCenter: parent.horizontalCenter
+        Rectangle {
+            id: msg
+
+            width: childrenRect.width
+            height: JamiTheme.contactMessageAvatarSize + 12
+            radius: JamiTheme.contactMessageAvatarSize / 2 + 6
+            Layout.alignment: Qt.AlignVCenter
+            color: "transparent"
+            border.width: 1
+            border.color: CurrentConversation.isCoreDialog ? JamiTheme.messageInBgColor : CurrentConversation.color
+
+            RowLayout {
+                anchors.verticalCenter: parent.verticalCenter
+
+                Avatar {
+                    Layout.leftMargin: 6
+                    width: JamiTheme.contactMessageAvatarSize
+                    height: JamiTheme.contactMessageAvatarSize
+                    visible: ActionUri !== ""
+                    imageId: ActionUri !== CurrentAccount.uri ? ActionUri : CurrentAccount.id
+                    showPresenceIndicator: false
+                    mode: ActionUri !== CurrentAccount.uri ? Avatar.Mode.Contact : Avatar.Mode.Account
+                }
+
+                Label {
+                    id: textLabel
+
+                    Layout.rightMargin: 6                    
+                    width: parent.width
+                    text: Body
+                    horizontalAlignment: Qt.AlignHCenter
+                    font.pointSize: JamiTheme.contactEventPointSize
+                    font.bold: true
+                    color: JamiTheme.chatviewTextColor
+                }
+            }
         }
     }
-
     opacity: 0
     Behavior on opacity { NumberAnimation { duration: 100 } }
     Component.onCompleted: opacity = 1
diff --git a/src/app/commoncomponents/DataTransferMessageDelegate.qml b/src/app/commoncomponents/DataTransferMessageDelegate.qml
index 6eb572079d3549ba28e9a0ada21dba54160131d1..d4dd426fa847f1262fa80b8de3d2dd95c4480049 100644
--- a/src/app/commoncomponents/DataTransferMessageDelegate.qml
+++ b/src/app/commoncomponents/DataTransferMessageDelegate.qml
@@ -31,7 +31,12 @@ Loader {
     id: root
 
     property var mediaInfo
-    property bool showTime: false
+    property bool showTime
+    property bool showDay
+    property int timestamp: Timestamp
+    property string formattedTime: MessagesAdapter.getFormattedTime(Timestamp)
+    property string formattedDay: MessagesAdapter.getFormattedDay(Timestamp)
+
     property int seq: MsgSeq.single
     property string author: Author
 
@@ -70,7 +75,9 @@ Loader {
             transferName: TransferName
             transferId: Id
             readers: Readers
-            formattedTime: MessagesAdapter.getFormattedTime(Timestamp)
+            timestamp: root.timestamp
+            formattedTime: root.formattedTime
+            formattedDay: root.formattedTime
             extraHeight: progressBar.visible ? 18 : 0
             innerContent.children: [
                 RowLayout {
@@ -247,6 +254,7 @@ Loader {
             transferId: Id
             readers: Readers
             formattedTime: MessagesAdapter.getFormattedTime(Timestamp)
+            formattedDay: MessagesAdapter.getFormattedDay(Timestamp)
             bubble.visible: false
             innerContent.children: [
                 Loader {
@@ -332,7 +340,7 @@ Loader {
                             sourceSize.width: width
                             sourceSize.height: height
                             source: "file:///" + Body
-                            property real aspectRatio: implicitWidth / implicitHeight
+                            property real aspectRatio: width / implicitHeight
                             property real adjustedWidth: Math.min(maxSize,
                                                                   Math.max(minSize,
                                                                            innerContent.width - senderMargin))
diff --git a/src/app/commoncomponents/GeneratedMessageDelegate.qml b/src/app/commoncomponents/GeneratedMessageDelegate.qml
index fa37c3198c281158f89121cd4527cebca790b58e..d37fc01341cc48fd9f21b80b6687ed9b83e8d478 100644
--- a/src/app/commoncomponents/GeneratedMessageDelegate.qml
+++ b/src/app/commoncomponents/GeneratedMessageDelegate.qml
@@ -29,38 +29,37 @@ Column {
     id: root
 
     property bool showTime: false
+    property bool showDay: false
     property int seq: MsgSeq.single
     property alias font: textLabel.font
-
+    property int timestamp: Timestamp
+    property string formattedTime: MessagesAdapter.getFormattedTime(Timestamp)
+    property string formattedDay: MessagesAdapter.getFormattedDay(Timestamp)
     width: ListView.view ? ListView.view.width : 0
-
     spacing: 2
     topPadding: 12
     bottomPadding: 12
+    ColumnLayout {
 
-    Label {
-        id: textLabel
         width: parent.width
-        text: Body
-        horizontalAlignment: Qt.AlignHCenter
-        font.pointSize: 12
-        color: JamiTheme.chatviewTextColor
-    }
 
-    Item {
-        id: infoCell
+        TimestampInfo {
+            id:timestampItem
 
-        width: parent.width
-        height: childrenRect.height
+            showDay: root.showDay
+            showTime: root.showTime
+            formattedTime: root.formattedTime
+            formattedDay: root.formattedDay
+            Layout.alignment: Qt.AlignHCenter
+        }
 
         Label {
-            text: MessagesAdapter.getFormattedTime(Timestamp)
-            color: JamiTheme.timestampColor
-            visible: showTime || seq === MsgSeq.last
-            height: visible * implicitHeight
-            font.pointSize: 9
+            id: textLabel
 
-            anchors.horizontalCenter: parent.horizontalCenter
+            text: Body
+            Layout.alignment: Qt.AlignHCenter
+            font.pointSize: 12
+            color: JamiTheme.chatviewTextColor
         }
     }
 
diff --git a/src/app/commoncomponents/SBSMessageBase.qml b/src/app/commoncomponents/SBSMessageBase.qml
index b4b075435b2dac520111c790bd3295dfcb59e634..a2d1bc3e1716f96c1b45f01f9ea94a98bba6fa63 100644
--- a/src/app/commoncomponents/SBSMessageBase.qml
+++ b/src/app/commoncomponents/SBSMessageBase.qml
@@ -37,26 +37,26 @@ Control {
 
     // these MUST be set but we won't use the 'required' keyword yet
     property bool isOutgoing
-    property bool showTime
+    property bool showTime: false
+    property bool showDay: false
     property int seq
     property string author
     property string transferId
     property string registeredNameText
     property string transferName
-    property string formattedTime
+    property string formattedTime: MessagesAdapter.getFormattedTime(Timestamp)
+    property string formattedDay: MessagesAdapter.getFormattedDay(Timestamp)
     property string location
     property string id: Id
     property string hoveredLink
     property var readers: []
-
+    property int timestamp: Timestamp
     readonly property real senderMargin: 64
     readonly property real avatarSize: 20
     readonly property real msgRadius: 20
     readonly property real hPadding: JamiTheme.sbsMessageBasePreferredPadding
-
     width: ListView.view ? ListView.view.width : 0
     height: mainColumnLayout.implicitHeight
-
     rightPadding: hPadding
     leftPadding: hPadding
 
@@ -64,11 +64,21 @@ Control {
         id: mainColumnLayout
 
         anchors.centerIn: parent
-
         width: parent.width - hPadding * 2
-
         spacing: 0
 
+        TimestampInfo {
+            id: timestampItem
+
+            showDay: root.showDay
+            showTime: root.showTime
+            formattedTime: root.formattedTime
+            formattedDay: root.formattedDay
+            Layout.alignment: Qt.AlignHCenter
+            Layout.fillWidth: true
+            Layout.fillHeight: true
+        }
+
         Item {
 
             id: usernameblock
@@ -78,7 +88,7 @@ Control {
                 id: username
                 text: UtilsAdapter.getBestNameForUri(CurrentAccount.id, Author)
                 font.bold: true
-                visible: (seq === MsgSeq.first || seq === MsgSeq.single) && !isOutgoing
+                visible:(seq === MsgSeq.first || seq === MsgSeq.single) && !isOutgoing
                 font.pixelSize: JamiTheme.usernameBlockFontSize
                 color: JamiTheme.chatviewUsernameColor
                 lineHeight: JamiTheme.usernameBlockLineHeight
@@ -107,17 +117,15 @@ Control {
                 }
             }
 
-
             MouseArea {
                 id: itemMouseArea
-            
+
                 Layout.fillWidth: true
                 Layout.fillHeight: true
-
                 acceptedButtons: Qt.LeftButton | Qt.RightButton
                 onClicked: function (mouse) {
                     if (mouse.button === Qt.RightButton
-                        && (transferId !== "" || Type === Interaction.Type.TEXT)) {
+                            && (transferId !== "" || Type === Interaction.Type.TEXT)) {
                         // Context Menu for Transfers
                         ctxMenu.x = mouse.x
                         ctxMenu.y = mouse.y
@@ -142,8 +150,8 @@ Control {
                     type: seq
                     function getBaseColor() {
                         var baseColor = isOutgoing ? JamiTheme.messageOutBgColor
-                                            : CurrentConversation.isCoreDialog ?
-                                                JamiTheme.messageInBgColor : Qt.lighter(CurrentConversation.color, 1.5)
+                                                   : CurrentConversation.isCoreDialog ?
+                                                         JamiTheme.messageInBgColor : Qt.lighter(CurrentConversation.color, 1.5)
                         if (Id === MessagesAdapter.replyToId) {
                             // If we are replying to
                             return Qt.darker(baseColor, 1.5)
@@ -194,6 +202,7 @@ Control {
                     id: readsOne
 
                     visible: root.readers.length === 1 && CurrentAccount.sendReadReceipt
+
                     width: {
                         if (root.readers.length === 0)
                             return 0
@@ -216,28 +225,12 @@ Control {
             orientation: ListView.Horizontal
             Layout.preferredHeight: {
                 if (showTime || seq === MsgSeq.last)
-                    return contentHeight + formattedTimeLabel.contentHeight
+                    return contentHeight + timestampItem.contentHeight
                 else if (readsMultiple.visible)
                     return JamiTheme.avatarReadReceiptSize
                 return 0
             }
 
-
-            Label {
-                id: formattedTimeLabel
-
-                text: formattedTime
-                color: JamiTheme.timestampColor
-                visible: showTime || seq === MsgSeq.last
-                height: visible * implicitHeight
-                font.pointSize: 9
-                topPadding : 4
-                anchors.rightMargin: status.width
-                anchors.right: !isOutgoing ? undefined : readsMultiple.left
-                anchors.left: isOutgoing ? undefined : parent.left
-                anchors.leftMargin: avatarBlockWidth + 6
-            }
-
             ReadStatus {
                 id: readsMultiple
                 visible: root.readers.length > 1 && CurrentAccount.sendReadReceipt
@@ -254,7 +247,6 @@ Control {
                 anchors.topMargin: 1
                 readers: root.readers
             }
-
         }
     }
 
diff --git a/src/app/commoncomponents/TextMessageDelegate.qml b/src/app/commoncomponents/TextMessageDelegate.qml
index 35b95d2fb2f5a00a47b2e902acc69c69420b634c..0177699767b9c880086e776e1f97173272c64a09 100644
--- a/src/app/commoncomponents/TextMessageDelegate.qml
+++ b/src/app/commoncomponents/TextMessageDelegate.qml
@@ -21,7 +21,6 @@ import QtQuick
 import QtQuick.Controls
 import QtQuick.Layouts
 import Qt5Compat.GraphicalEffects
-
 import net.jami.Models 1.1
 import net.jami.Adapters 1.1
 import net.jami.Constants 1.1
@@ -31,25 +30,21 @@ SBSMessageBase {
     id : root
 
     property bool isRemoteImage
-
     property real maxMsgWidth: root.width - senderMargin - 2 * hPadding - avatarBlockWidth
-
     isOutgoing: Author === ""
     author: Author
     readers: Readers
+    timestamp: Timestamp
     formattedTime: MessagesAdapter.getFormattedTime(Timestamp)
+    formattedDay: MessagesAdapter.getFormattedDay(Timestamp)
     extraHeight: extraContent.active && !isRemoteImage ? msgRadius : -isRemoteImage
 
     innerContent.children: [
         TextEdit {
-
             padding: JamiTheme.preferredMarginSize
             anchors.right: isOutgoing ? parent.right : undefined
-
             text: Body
-
             horizontalAlignment: Text.AlignLeft
-
             width: {
                 if (extraContent.active)
                     Math.max(extraContent.width,
@@ -62,9 +57,7 @@ SBSMessageBase {
             height: implicitHeight
             wrapMode: Label.WrapAtWordBoundaryOrAnywhere
             selectByMouse: true
-
             font.pixelSize: JamiTheme.chatviewFontSize
-
             font.hintingPreference: Font.PreferNoHinting
             renderType: Text.NativeRendering
             textFormat: Text.MarkdownText
diff --git a/src/app/commoncomponents/TimestampInfo.qml b/src/app/commoncomponents/TimestampInfo.qml
new file mode 100644
index 0000000000000000000000000000000000000000..8ba9e3a53147b0d0157858596681ac5e8a60d2de
--- /dev/null
+++ b/src/app/commoncomponents/TimestampInfo.qml
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2022 Savoir-faire Linux Inc.
+ * Author: Nicolas Vengeon <nicolas.vengeon@savoirfairelinux.com>
+ *
+ * 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 "../mainview/components/"
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Layouts
+import net.jami.Models 1.1
+import net.jami.Adapters 1.1
+import net.jami.Constants 1.1
+
+ColumnLayout{
+    id: root
+
+    property bool showTime
+    property bool showDay
+    property string formattedTime
+    property string formattedDay
+    property real detailsOpacity: 0.6
+
+    Connections {
+        target: MessagesAdapter.messageListModel
+        function onTimestampUpdate() {
+            if (showTime || showDay) {
+                formattedTime = MessagesAdapter.getFormattedTime(Timestamp)
+            }
+        }
+    }
+
+    Item {
+        visible: showDay
+        Layout.alignment: Qt.AlignHCenter
+        Layout.fillHeight: true
+        Layout.fillWidth: true
+        Layout.topMargin: JamiTheme.dayTimestampTopMargin
+
+        Rectangle {
+            id: line
+
+            height: 1
+            opacity: detailsOpacity
+            color:JamiTheme.timestampColor
+            width: chatView.width - JamiTheme.timestampLinePadding
+            anchors.centerIn: parent
+        }
+
+        Rectangle {
+            id: dayRectangle
+
+            width: borderRectangle.width
+            height: borderRectangle.height
+            radius: 5
+            color: JamiTheme.chatviewBgColor
+            Layout.fillHeight: true
+            anchors.centerIn: parent
+
+            Rectangle {
+                id: borderRectangle
+
+                border { color:  JamiTheme.timestampColor; width: 1}
+                opacity: detailsOpacity
+                width: formattedDayLabel.width + JamiTheme.dayTimestampVPadding
+                height: formattedDayLabel.height + JamiTheme.dayTimestampHPadding
+                radius: dayRectangle.radius
+                color: JamiTheme.transparentColor
+            }
+
+            Text {
+                id: formattedDayLabel
+
+                color: JamiTheme.chatviewTextColor
+                anchors { verticalCenter: parent.verticalCenter; horizontalCenter: parent.horizontalCenter}
+                text: formattedDay
+                font.pointSize: JamiTheme.timestampFont
+            }
+        }
+    }
+
+    Label {
+        id: formattedTimeLabel
+
+        text: formattedTime
+        Layout.bottomMargin: JamiTheme.timestampBottomMargin
+        Layout.topMargin: JamiTheme.timestampTopMargin
+        Layout.alignment: Qt.AlignHCenter
+        color: JamiTheme.timestampColor
+        visible: showTime
+        height: visible * implicitHeight
+        font.pointSize: JamiTheme.timestampFont
+    }
+}
diff --git a/src/app/constant/JamiTheme.qml b/src/app/constant/JamiTheme.qml
index 509e056183b886b18321514bbd5bfab85f9264eb..0bccb0fef408e2b5b3c811af3e3d068bd51f1b0d 100644
--- a/src/app/constant/JamiTheme.qml
+++ b/src/app/constant/JamiTheme.qml
@@ -321,6 +321,16 @@ Item {
     property real lineEditContextMenuItemsWidth: 100
     property real lineEditContextMenuSeparatorsHeight: 2
 
+    //TimestampInfo
+    property int timestampLinePadding: 40
+    property int dayTimestampTopMargin: 30
+    property int timestampBottomMargin: 42
+    property int timestampTopMargin: 20
+    property int dayTimestampHPadding: 16
+    property real dayTimestampVPadding: 32
+    property real timestampFont: calcSize(12)
+    property int timestampIntervalTime: 120
+
 
     // Jami switch
     property real switchIndicatorRadius: 30
diff --git a/src/app/mainview/components/MessageListView.qml b/src/app/mainview/components/MessageListView.qml
index 4ba0b162e226712216d117a791f5e3e6d36c64f3..0c4357035e22917a73793a72fb87890faffb24cf 100644
--- a/src/app/mainview/components/MessageListView.qml
+++ b/src/app/mainview/components/MessageListView.qml
@@ -44,105 +44,95 @@ JamiListView {
             MessagesAdapter.loadMoreMessages()
     }
 
-    // sequencing/timestamps (2-sided style)
-    function computeTimestampVisibility(item, itemIndex) {
-        if (root === undefined)
-            return
-        var nItem = root.itemAtIndex(itemIndex - 1)
-        if (nItem && itemIndex !== root.count - 1) {
-            item.showTime = (nItem.timestamp - item.timestamp) > 60 &&
-                    nItem.formattedTime !== item.formattedTime
-        } else {
-            item.showTime = true
-            var pItem = root.itemAtIndex(itemIndex + 1)
-            if (pItem) {
-                pItem.showTime = (item.timestamp - pItem.timestamp) > 60 &&
-                        pItem.formattedTime !== item.formattedTime
+
+    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
+            }else {
+                item2.showTime = item2.timestamp - item1.timestamp > JamiTheme.timestampIntervalTime
+                item2.showDay = item2.formattedDay !== item1.formattedDay
             }
+            return true
         }
+        return false
     }
 
-    function computeSequencing(computeItem, computeItemIndex) {
-        if (root === undefined)
-            return
-        var cItem = {
-            'author': computeItem.author,
-            'showTime': computeItem.showTime
+    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
+        //Middle insertion
+        if (pItem && nItem) {
+            computeTimestampVisibility(item, itemIndex, nItem, nItemIndex)
+            computeSequencing(nItemIndex, nItem, root.itemAtIndex(itemIndex + 2), item)
         }
-        var pItem = root.itemAtIndex(computeItemIndex + 1)
-        var nItem = root.itemAtIndex(computeItemIndex - 1)
-
-        let isSeq = (item0, item1) =>
-            item0.author === item1.author && !item0.showTime
-
-        let setSeq = function (newSeq, item) {
-            if (item === undefined)
-                computeItem.seq = newSeq
-            else
-                item.seq = newSeq
+        //top buffer insertion = scroll up
+        if (pItem && !nItem) {
+            computeTimestampVisibility(item, itemIndex, pItem, pItemIndex)
+            computeSequencing(pItemIndex, pItem, item, root.itemAtIndex(itemIndex - 2))
         }
-
-        let rAdjustSeq = function (item) {
-            if (item.seq === MsgSeq.last)
-                item.seq = MsgSeq.middle
-            else if (item.seq === MsgSeq.single)
-                setSeq(MsgSeq.first, item)
+        //bottom buffer insertion = scroll down
+        if (!pItem && nItem) {
+            computeTimestampVisibility(item, itemIndex, nItem, nItemIndex)
+            computeSequencing(nItemIndex, nItem, root.itemAtIndex(itemIndex + 2), item)
         }
-
-        let adjustSeq = function (item) {
-            if (item.seq === MsgSeq.first)
-                item.seq = MsgSeq.middle
-            else if (item.seq === MsgSeq.single)
-                setSeq(MsgSeq.last, item)
+        //index 0 insertion = new message
+        if (itemIndex === 0) {
+            Qt.callLater(computeSequencing, itemIndex, item, root.itemAtIndex(itemIndex + 1), null)
+            if (! computeTimestampVisibility(item, itemIndex, nItem, nItemIndex)) {
+                Qt.callLater(computeChatview, item, itemIndex)
+            }
+        }
+        //top element
+        if(itemIndex === root.count - 1 && CurrentConversation.allMessagesLoaded) {
+            item.showTime = true
+            item.showDay = true
         }
+    }
 
-        if (pItem && !nItem) {
-            if (!isSeq(pItem, cItem)) {
-                computeItem.seq = MsgSeq.single
-            } else {
-                computeItem.seq = MsgSeq.last
-                rAdjustSeq(pItem)
-            }
-        } else if (nItem && !pItem) {
-            if (!isSeq(cItem, nItem)) {
-                computeItem.seq = MsgSeq.single
-            } else {
-                setSeq(MsgSeq.first)
-                adjustSeq(nItem)
-            }
-        } else if (!nItem && !pItem) {
-            computeItem.seq = MsgSeq.single
-        } else {
-            if (isSeq(pItem, nItem)) {
-                if (isSeq(pItem, cItem)) {
-                    computeItem.seq = MsgSeq.middle
-                } else {
-                    computeItem.seq = MsgSeq.single
-
-                    if (pItem.seq === MsgSeq.first)
-                        pItem.seq = MsgSeq.single
-                    else if (item.seq === MsgSeq.middle)
-                        pItem.seq = MsgSeq.last
-
-                    if (nItem.seq === MsgSeq.last)
-                        nItem.seq = MsgSeq.single
-                    else if (nItem.seq === MsgSeq.middle)
-                        nItem.seq = MsgSeq.first
+    function computeSequencing(index, item, nItem, pItem) {
+        if (root === undefined || !item)
+            return
+
+        function isFirst() {
+            if (!nItem) return true
+            else{
+                if (item.showTime) {
+                    return true
                 }
-            } else {
-                if (!isSeq(pItem, cItem)) {
-                    computeItem.seq = MsgSeq.first
-                    adjustSeq(pItem)
-                } else {
-                    computeItem.seq = MsgSeq.last
-                    rAdjustSeq(nItem)
+                if (nItem.author !== item.author) {
+                    return true
                 }
             }
+            return false
         }
 
-        if (computeItem.seq === MsgSeq.last) {
-            computeItem.showTime = true
+        function isLast() {
+            if (!pItem) return true
+            else{
+                if (pItem.showTime) {
+                    return true
+                }
+                if (pItem.author !== item.author) {
+                    return true
+                }
+            }
+            return false
         }
+
+        if (isLast() && isFirst())
+            item.seq = MsgSeq.single
+        if (!isLast() && isFirst())
+            item.seq = MsgSeq.first
+        if (isLast() && !isFirst())
+            item.seq = MsgSeq.last
+        if (!isLast() && !isFirst())
+            item.seq = MsgSeq.middle
     }
 
     // fade-in mechanism
@@ -189,6 +179,7 @@ JamiListView {
     width: parent.width
     // this offscreen caching is pretty huge
     // displayMarginEnd may be removed
+
     displayMarginBeginning: 2048
     displayMarginEnd: 2048
     maximumFlickVelocity: 2048
@@ -216,65 +207,55 @@ JamiListView {
         id: delegateChooser
 
         role: "Type"
+
         DelegateChoice {
+            id: delegateChoice
+
             roleValue: Interaction.Type.TEXT
+
             TextMessageDelegate {
-                Component.onCompleted: {
-                    if (index) {
-                        computeTimestampVisibility(this, index)
-                        computeSequencing(this, index)
-                    } else {
-                        Qt.callLater(computeTimestampVisibility, this, index)
-                        Qt.callLater(computeSequencing, this, index)
-                    }
+                Component.onCompleted:  {
+                    computeChatview(this,index)
                 }
             }
         }
+
         DelegateChoice {
             roleValue: Interaction.Type.CALL
+
             GeneratedMessageDelegate {
-                Component.onCompleted: {
-                    if (index)
-                        computeTimestampVisibility(this, index)
-                    else
-                        Qt.callLater(computeTimestampVisibility, this, index)
+                Component.onCompleted:  {
+                    computeChatview(this,index)
                 }
             }
         }
+
         DelegateChoice {
             roleValue: Interaction.Type.CONTACT
+
             ContactMessageDelegate {
-                Component.onCompleted: {
-                    if (index)
-                        computeTimestampVisibility(this, index)
-                    else
-                        Qt.callLater(computeTimestampVisibility, this, index)
+                Component.onCompleted:  {
+                    computeChatview(this,index)
                 }
             }
         }
+
         DelegateChoice {
             roleValue: Interaction.Type.INITIAL
+
             GeneratedMessageDelegate {
                 font.bold: true
-                Component.onCompleted: {
-                    if (index)
-                        computeTimestampVisibility(this, index)
-                    else
-                        Qt.callLater(computeTimestampVisibility, this, index)
+                Component.onCompleted:  {
+                    computeChatview(this,index)
                 }
             }
         }
         DelegateChoice {
             roleValue: Interaction.Type.DATA_TRANSFER
+
             DataTransferMessageDelegate {
-                Component.onCompleted: {
-                    if (index) {
-                        computeTimestampVisibility(this, index)
-                        computeSequencing(this, index)
-                    } else {
-                        Qt.callLater(computeTimestampVisibility, this, index)
-                        Qt.callLater(computeSequencing, this, index)
-                    }
+                Component.onCompleted:  {
+                    computeChatview(this,index)
                 }
             }
         }
@@ -382,8 +363,8 @@ JamiListView {
                     else {
                         var textSize = JamiQmlUtils.getTextBoundingRect(font, text).width
                         var typingContentWidth = typingDots.width + typingDots.anchors.leftMargin
-                                               + typeIndicatorNameText.anchors.leftMargin
-                                               + typeIndicatorEndingText.contentWidth
+                                + typeIndicatorNameText.anchors.leftMargin
+                                + typeIndicatorEndingText.contentWidth
                         typeIndicatorNameText.Layout.preferredWidth =
                                 Math.min(typeIndicatorContainer.width - 5 - typingContentWidth,
                                          textSize)
diff --git a/src/app/messagesadapter.cpp b/src/app/messagesadapter.cpp
index fd37fcc14e785cabd791cadc1b3e9f0914e17c97..b3ae25b315235eb1341dd5f40f271715d536ed9d 100644
--- a/src/app/messagesadapter.cpp
+++ b/src/app/messagesadapter.cpp
@@ -581,21 +581,41 @@ MessagesAdapter::getFormattedTime(const quint64 timestamp)
 {
     const auto now = QDateTime::currentDateTime();
     const auto seconds = now.toSecsSinceEpoch() - timestamp;
-    auto interval = qFloor(seconds / (3600 * 24));
-    if (interval > 5)
-        return QLocale::system().toString(QDateTime::fromSecsSinceEpoch(timestamp),
-                                          QLocale::ShortFormat);
-    if (interval > 1)
-        return QObject::tr("%1 days ago").arg(interval);
-    if (interval == 1)
-        return QObject::tr("one day ago");
-    interval = qFloor(seconds / 3600);
-    if (interval > 1)
-        return QObject::tr("%1 hours ago").arg(interval);
-    if (interval == 1)
-        return QObject::tr("one hour ago");
-    interval = qFloor(seconds / 60);
-    if (interval > 1)
-        return QObject::tr("%1 minutes ago").arg(interval);
+    auto interval = qFloor(seconds / 60);
+
+    if (interval > 1) {
+        auto curLang = settingsManager_->getValue(Settings::Key::LANG);
+        auto curLocal(QLocale(curLang.toString()));
+        auto curTime = QDateTime::fromSecsSinceEpoch(timestamp).time();
+        QString timeLocale;
+        if (curLang == "SYSTEM")
+            timeLocale = QLocale::system().toString(curTime, QLocale::system().ShortFormat);
+        else
+            timeLocale = curLocal.toString(curTime, curLocal.ShortFormat);
+
+        return timeLocale;
+    }
     return QObject::tr("just now");
 }
+
+QString
+MessagesAdapter::getFormattedDay(const quint64 timestamp)
+{
+    auto now = QDate::currentDate();
+    auto before = QDateTime::fromSecsSinceEpoch(timestamp).date();
+    if (before == now)
+        return QObject::tr("Today");
+    if (before.daysTo(now) == 1)
+        return QObject::tr("Yesterday");
+
+    auto curLang = settingsManager_->getValue(Settings::Key::LANG);
+    auto curLocal(QLocale(curLang.toString()));
+    auto curDate = QDateTime::fromSecsSinceEpoch(timestamp).date();
+    QString dateLocale;
+    if (curLang == "SYSTEM")
+        dateLocale = QLocale::system().toString(curDate, QLocale::system().ShortFormat);
+    else
+        dateLocale = curLocal.toString(curDate, curLocal.ShortFormat);
+
+    return dateLocale;
+}
diff --git a/src/app/messagesadapter.h b/src/app/messagesadapter.h
index a01f1d12e84c8dd39954e524cb911d29167807fa..21097934740140bbce9c82933c20b6c995501b10 100644
--- a/src/app/messagesadapter.h
+++ b/src/app/messagesadapter.h
@@ -79,6 +79,7 @@ protected:
     Q_INVOKABLE QVariantMap isLocalImage(const QString& mimeName);
     Q_INVOKABLE QVariantMap getMediaInfo(const QString& msg);
     Q_INVOKABLE bool isRemoteImage(const QString& msg);
+    Q_INVOKABLE QString getFormattedDay(const quint64 timestamp);
     Q_INVOKABLE QString getFormattedTime(const quint64 timestamp);
     Q_INVOKABLE void parseMessageUrls(const QString& messageId,
                                       const QString& msg,
diff --git a/src/app/settingsview/components/SettingSpinBox.qml b/src/app/settingsview/components/SettingSpinBox.qml
index 1685f41756e5673b0d3784bf06f40dc7e07d8cdf..0c4329853428b97252dca17f3817762ec000f580 100644
--- a/src/app/settingsview/components/SettingSpinBox.qml
+++ b/src/app/settingsview/components/SettingSpinBox.qml
@@ -62,7 +62,6 @@ RowLayout {
         Layout.preferredWidth: root.itemWidth
         Layout.preferredHeight: JamiTheme.preferredFieldHeight
         Layout.alignment: Qt.AlignCenter
-
         font.pointSize: JamiTheme.buttonFontSize
         font.kerning: true
 
@@ -91,7 +90,6 @@ RowLayout {
 
         MaterialToolTip {
             id: toolTip
-
             parent: textField
             visible: textField.hovered && (root.tooltipText.length > 0)
             delay: Qt.styleHints.mousePressAndHoldInterval
diff --git a/src/libclient/messagelistmodel.cpp b/src/libclient/messagelistmodel.cpp
index affb368aa97b383e7217ea4ddcb9ad9b6848acbc..f796f6fdc79b0e1ee198f6028e02789318047806 100644
--- a/src/libclient/messagelistmodel.cpp
+++ b/src/libclient/messagelistmodel.cpp
@@ -36,7 +36,11 @@ using reverseIterator = MessageListModel::reverseIterator;
 
 MessageListModel::MessageListModel(QObject* parent)
     : QAbstractListModel(parent)
-{}
+    , timestampTimer_(new QTimer(this))
+{
+    connect(timestampTimer_, &QTimer::timeout, this, &MessageListModel::timestampUpdate);
+    timestampTimer_->start(1000);
+}
 
 QPair<iterator, bool>
 MessageListModel::emplace(const QString& msgId, interaction::Info message, bool beginning)
diff --git a/src/libclient/messagelistmodel.h b/src/libclient/messagelistmodel.h
index ba7cadac71b60cf9913b79169d9b245413df001e..88028550fbeda72f5ede99c39c01dc7422602099 100644
--- a/src/libclient/messagelistmodel.h
+++ b/src/libclient/messagelistmodel.h
@@ -22,6 +22,7 @@
 #include "api/interaction.h"
 
 #include <QAbstractListModel>
+#include <QTimer>
 
 namespace lrc {
 namespace api {
@@ -125,6 +126,8 @@ public:
     void emitDataChanged(iterator it, VectorInt roles = {});
     void emitDataChanged(const QString& msgId, VectorInt roles = {});
 
+    Q_SIGNAL void timestampUpdate();
+
 protected:
     using Role = MessageList::Role;
 
@@ -144,6 +147,8 @@ private:
     iterator insertMessage(iterator it, item_t& message);
     void removeMessage(int index, iterator it);
     void moveMessage(int from, int to);
+
+    QTimer* timestampTimer_ {nullptr};
 };
 } // namespace api
 } // namespace lrc