From f69df3416cf76ee5180300e878596dcd0b0b6634 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?S=C3=A9bastien=20Blin?=
 <sebastien.blin@savoirfairelinux.com>
Date: Tue, 2 Nov 2021 15:07:02 -0400
Subject: [PATCH] messages: add read receipt support

Change-Id: Ide4b1336a13972a9291cb1e9e2bf881b32b97198
GitLab: #468
---
 qml.qrc                                       |  1 +
 src/appsettingsmanager.h                      |  1 +
 .../DataTransferMessageDelegate.qml           |  2 +
 src/commoncomponents/ReadStatus.qml           | 46 +++++++++++++++++++
 src/commoncomponents/SBSMessageBase.qml       | 27 +++++++++--
 src/commoncomponents/TextMessageDelegate.qml  |  1 +
 src/constant/JamiTheme.qml                    |  1 +
 7 files changed, 76 insertions(+), 3 deletions(-)
 create mode 100644 src/commoncomponents/ReadStatus.qml

diff --git a/qml.qrc b/qml.qrc
index 04b8a564e..52bc9a41c 100644
--- a/qml.qrc
+++ b/qml.qrc
@@ -167,6 +167,7 @@
         <file>src/constant/MsgSeq.qml</file>
         <file>src/commoncomponents/SBSContextMenu.qml</file>
         <file>src/commoncomponents/SBSMessageBase.qml</file>
+        <file>src/commoncomponents/ReadStatus.qml</file>
         <file>src/commoncomponents/GeneratedMessageDelegate.qml</file>
         <file>src/commoncomponents/DataTransferMessageDelegate.qml</file>
         <file>src/mainview/components/ScrollToBottomButton.qml</file>
diff --git a/src/appsettingsmanager.h b/src/appsettingsmanager.h
index 6c4f5d0dc..668b1e50d 100644
--- a/src/appsettingsmanager.h
+++ b/src/appsettingsmanager.h
@@ -36,6 +36,7 @@ const QString defaultDownloadPath = QStandardPaths::writableLocation(
     X(DownloadPath, defaultDownloadPath) \
     X(EnableNotifications, true) \
     X(EnableTypingIndicator, true) \
+    X(EnableReadReceipt, true) \
     X(AllowFromUntrusted, false) \
     X(AcceptTransferBelow, 20) \
     X(AutoAcceptFiles, true) \
diff --git a/src/commoncomponents/DataTransferMessageDelegate.qml b/src/commoncomponents/DataTransferMessageDelegate.qml
index 6a908c5e1..6e5fff3d7 100644
--- a/src/commoncomponents/DataTransferMessageDelegate.qml
+++ b/src/commoncomponents/DataTransferMessageDelegate.qml
@@ -70,6 +70,7 @@ Loader {
             location: Body
             transferName: TransferName
             transferId: Id
+            readers: Readers
             formattedTime: MessagesAdapter.getFormattedTime(Timestamp)
             extraHeight: progressBar.visible ? 18 : 0
             innerContent.children: [
@@ -239,6 +240,7 @@ Loader {
             location: Body
             transferName: TransferName
             transferId: Id
+            readers: Readers
             formattedTime: MessagesAdapter.getFormattedTime(Timestamp)
             bubble.visible: false
             innerContent.children: [
diff --git a/src/commoncomponents/ReadStatus.qml b/src/commoncomponents/ReadStatus.qml
new file mode 100644
index 000000000..fcef8130c
--- /dev/null
+++ b/src/commoncomponents/ReadStatus.qml
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 by Savoir-faire Linux
+ * Author: Sébastien Blin <sebastien.blin@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 QtQuick 2.15
+import QtQuick.Controls 2.15
+import QtQuick.Layouts 1.15
+import QtGraphicalEffects 1.15
+
+import net.jami.Models 1.1
+import net.jami.Adapters 1.1
+import net.jami.Constants 1.1
+
+ListView {
+    id: root
+
+    property var readers: []
+    model: readers
+    orientation: ListView.Horizontal
+    Layout.alignment: Qt.AlignRight
+    spacing: -(JamiTheme.avatarReadReceiptSize/3)
+
+    delegate: Avatar {
+        width: JamiTheme.avatarReadReceiptSize
+        height: JamiTheme.avatarReadReceiptSize
+        z: -index
+
+        imageId: modelData
+        showPresenceIndicator: false
+        mode: Avatar.Mode.Contact
+    }
+}
\ No newline at end of file
diff --git a/src/commoncomponents/SBSMessageBase.qml b/src/commoncomponents/SBSMessageBase.qml
index 669b5ba31..2de0fe34c 100644
--- a/src/commoncomponents/SBSMessageBase.qml
+++ b/src/commoncomponents/SBSMessageBase.qml
@@ -43,6 +43,7 @@ Control {
     property string formattedTime
     property string location
     property string hoveredLink
+    property var readers: []
 
     readonly property real senderMargin: 64
     readonly property real avatarSize: 32
@@ -106,11 +107,18 @@ Control {
                 }
             }
         }
-        Item {
+        ListView {
             id: infoCell
 
             Layout.fillWidth: true
-            Layout.preferredHeight: childrenRect.height
+            orientation: ListView.Horizontal
+            Layout.preferredHeight: {
+                if (showTime || seq === MsgSeq.last)
+                    return childrenRect.height
+                else if (reads.visible)
+                    return JamiTheme.avatarReadReceiptSize
+                return 0
+            }
 
             Label {
                 text: formattedTime
@@ -119,11 +127,24 @@ Control {
                 height: visible * implicitHeight
                 font.pointSize: 9
 
-                anchors.right: !isOutgoing ? undefined : parent.right
+                anchors.right: !isOutgoing ? undefined : reads.left
                 anchors.rightMargin: 8
                 anchors.left: isOutgoing ? undefined : parent.left
                 anchors.leftMargin: avatarBlockWidth + 6
             }
+            ReadStatus {
+                id: reads
+                visible: root.readers.length !== 0 && CurrentAccount.sendReadReceipt
+                width: {
+                    if (root.readers.length === 0)
+                        return 0
+                    var nbAvatars = root.readers.length
+                    var margin = JamiTheme.avatarReadReceiptSize / 3
+                    return nbAvatars * JamiTheme.avatarReadReceiptSize - (nbAvatars - 1) * margin
+                }
+                anchors.right: parent.right
+                readers: root.readers
+            }
         }
     }
 
diff --git a/src/commoncomponents/TextMessageDelegate.qml b/src/commoncomponents/TextMessageDelegate.qml
index e9c4e2106..fe66900df 100644
--- a/src/commoncomponents/TextMessageDelegate.qml
+++ b/src/commoncomponents/TextMessageDelegate.qml
@@ -35,6 +35,7 @@ SBSMessageBase {
 
     isOutgoing: Author === ""
     author: Author
+    readers: Readers
     formattedTime: MessagesAdapter.getFormattedTime(Timestamp)
     extraHeight: extraContent.active && !isRemoteImage ? msgRadius : -isRemoteImage
     innerContent.children: [
diff --git a/src/constant/JamiTheme.qml b/src/constant/JamiTheme.qml
index 79ff8055d..bed92a175 100644
--- a/src/constant/JamiTheme.qml
+++ b/src/constant/JamiTheme.qml
@@ -242,6 +242,7 @@ Item {
     property int mosaicButtonPreferredWidth: 70
     property int mosaicButtonMaxWidth: 100
     property real avatarPresenceRatio: 0.26
+    property int avatarReadReceiptSize: 18
 
     property int menuItemsPreferredWidth: 220
     property int menuItemsPreferredHeight: 48
-- 
GitLab