From 397b799cbf4610ff2b5f7f90177444f2c5b964fe Mon Sep 17 00:00:00 2001
From: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
Date: Fri, 23 Jul 2021 16:38:25 -0400
Subject: [PATCH] swarm: swarmify the message view

Change-Id: I85a070e8ea44b108fa75d69a8c6f544e8e2c8581
---
 src/conversationlistmodelbase.cpp             |  3 ++
 src/conversationlistmodelbase.h               |  1 +
 src/conversationsadapter.cpp                  | 25 ++++-----
 src/mainview/MainView.qml                     |  4 +-
 .../components/ConversationListView.qml       | 22 ++++----
 src/mainview/components/InvitationView.qml    | 23 ++++-----
 src/mainview/components/MessageWebView.qml    |  8 +--
 .../components/SmartListItemDelegate.qml      |  2 +-
 src/mainview/components/UserProfile.qml       | 23 ++++-----
 src/messagesadapter.cpp                       | 51 ++++++++-----------
 src/messagesadapter.h                         |  2 +-
 11 files changed, 78 insertions(+), 86 deletions(-)

diff --git a/src/conversationlistmodelbase.cpp b/src/conversationlistmodelbase.cpp
index e43a1d454..4e92d8698 100644
--- a/src/conversationlistmodelbase.cpp
+++ b/src/conversationlistmodelbase.cpp
@@ -129,6 +129,8 @@ ConversationListModelBase::dataForItem(item_t item, int role) const
     }
     case Role::IsSwarm:
         return QVariant(item.isSwarm());
+    case Role::IsCoreDialog:
+        return QVariant(item.isCoreDialog());
     case Role::Mode:
         return QVariant(static_cast<int>(item.mode));
     case Role::UID:
@@ -163,6 +165,7 @@ ConversationListModelBase::dataForItem(item_t item, int role) const
             contactModel = lrcInstance_->getCurrentAccountInfo().contactModel.get();
             contact = contactModel->getContact(peerUri);
         } catch (const std::exception&) {
+            qWarning() << Q_FUNC_INFO << "Can't find contact" << peerUri;
             return {};
         }
 
diff --git a/src/conversationlistmodelbase.h b/src/conversationlistmodelbase.h
index 954baca02..2359d15ca 100644
--- a/src/conversationlistmodelbase.h
+++ b/src/conversationlistmodelbase.h
@@ -35,6 +35,7 @@
     X(LastInteraction) \
     X(ContactType) \
     X(IsSwarm) \
+    X(IsCoreDialog) \
     X(IsBanned) \
     X(UID) \
     X(InCall) \
diff --git a/src/conversationsadapter.cpp b/src/conversationsadapter.cpp
index 4b638d363..497f347bd 100644
--- a/src/conversationsadapter.cpp
+++ b/src/conversationsadapter.cpp
@@ -397,15 +397,17 @@ ConversationsAdapter::getConvInfoMap(const QString& convId)
     const auto& convInfo = lrcInstance_->getConversationFromConvUid(convId);
     if (convInfo.participants.empty())
         return {};
-    auto peerUri = convInfo.participants[0];
-    ContactModel* contactModel {nullptr};
-    contact::Info contact {};
-    try {
-        const auto& accountInfo = lrcInstance_->getAccountInfo(convInfo.accountId);
-        contactModel = accountInfo.contactModel.get();
-        contact = contactModel->getContact(peerUri);
-    } catch (...) {
+    QString peerUri {};
+    QString bestId {};
+    if (convInfo.isCoreDialog()) {
+        try {
+            const auto& accountInfo = lrcInstance_->getAccountInfo(convInfo.accountId);
+            peerUri = accountInfo.conversationModel->peersForConversation(convId).at(0);
+            bestId = accountInfo.contactModel->bestIdForContact(peerUri);
+        } catch (...) {
+        }
     }
+
     bool isAudioOnly {false};
     if (!convInfo.uid.isEmpty()) {
         auto* call = lrcInstance_->getCallInfoForConversation(convInfo);
@@ -426,14 +428,13 @@ ConversationsAdapter::getConvInfoMap(const QString& convId)
                                       || (call.isOutgoing && call.status != call::Status::ENDED));
         callState = call.status;
     }
-    // WARNING: not swarm ready
-    // titles should come from conversation, not contact model
     return {{"convId", convId},
-            {"bestId", contactModel->bestIdForContact(peerUri)},
+            {"bestId", bestId},
             {"title", lrcInstance_->getCurrentConversationModel()->title(convId)},
             {"uri", peerUri},
             {"isSwarm", convInfo.isSwarm()},
-            {"contactType", static_cast<int>(contact.profileInfo.type)},
+            {"isRequest", convInfo.isRequest},
+            {"needsSyncing", convInfo.needsSyncing},
             {"isAudioOnly", isAudioOnly},
             {"callState", static_cast<int>(callState)},
             {"callStackViewShouldShow", callStackViewShouldShow}};
diff --git a/src/mainview/MainView.qml b/src/mainview/MainView.qml
index aeb1886b1..68d9ec2eb 100644
--- a/src/mainview/MainView.qml
+++ b/src/mainview/MainView.qml
@@ -184,7 +184,7 @@ Rectangle {
             if (inSettingsView) {
                 toggleSettingsView()
             }
-            MessagesAdapter.setupChatView(convId)
+            MessagesAdapter.setupChatView(item)
             callStackView.setLinkedWebview(communicationPageMessageWebView)
             callStackView.responsibleAccountId = LRCInstance.currentAccountId
             callStackView.responsibleConvUid = convId
@@ -203,7 +203,7 @@ Rectangle {
         } else if (!inSettingsView) {
             if (currentConvUID !== convId) {
                 callStackView.needToCloseInCallConversationAndPotentialWindow()
-                MessagesAdapter.setupChatView(convId)
+                MessagesAdapter.setupChatView(item)
                 pushCommunicationMessageWebView()
                 communicationPageMessageWebView.focusMessageWebView()
                 currentConvUID = convId
diff --git a/src/mainview/components/ConversationListView.qml b/src/mainview/components/ConversationListView.qml
index 91cf6f546..7ddfff43e 100644
--- a/src/mainview/components/ConversationListView.qml
+++ b/src/mainview/components/ConversationListView.qml
@@ -131,23 +131,23 @@ ListView {
             var item = {
                 "convId": model.dataForRow(row, ConversationList.UID),
                 "displayId": model.dataForRow(row, ConversationList.BestId),
-                "displayName": model.dataForRow(row, ConversationList.Title),
+                "title": model.dataForRow(row, ConversationList.Title),
                 "uri": model.dataForRow(row, ConversationList.URI),
-                "contactType": model.dataForRow(row, ConversationList.ContactType),
-                "isSwarm": model.dataForRow(row, ConversationList.IsSwarm),
+                "isSwarm": model.dataForRow(row, ConversationList.IsSwarm)
             }
 
             responsibleAccountId = LRCInstance.currentAccountId
             responsibleConvUid = item.convId
             isSwarm = item.isSwarm
-            contactType = item.contactType
-
-            userProfile.responsibleConvUid = item.convId
-            userProfile.aliasText = item.displayName
-            userProfile.registeredNameText = item.displayId
-            userProfile.idText = item.uri
-            userProfile.convId = item.convId
-            userProfile.isSwarm = item.isSwarm
+            contactType = LRCInstance.currentAccountType
+
+            if (model.dataForRow(row, ConversationList.IsCoreDialog)) {
+                userProfile.aliasText = item.title
+                userProfile.registeredNameText = item.displayId
+                userProfile.idText = item.uri
+                userProfile.convId = item.convId
+                userProfile.isSwarm = item.isSwarm
+            }
 
             openMenu()
         }
diff --git a/src/mainview/components/InvitationView.qml b/src/mainview/components/InvitationView.qml
index 9926bd193..5056a6cdf 100644
--- a/src/mainview/components/InvitationView.qml
+++ b/src/mainview/components/InvitationView.qml
@@ -30,9 +30,9 @@ import "../../commoncomponents"
 Rectangle {
     id: root
 
-    property string invitationViewImageId
-    property string invitationViewContactTitle
-    property bool invitationViewNeedSyncing: false
+    property alias imageId: avatar.imageId
+    property string title
+    property bool needSyncing
 
     property real marginSize: 20
     property real textMarginSize: 50
@@ -49,7 +49,7 @@ Rectangle {
         width: infoColumnLayout.width - textMarginSize
         height: visible ? contentHeight : 0
 
-        visible: !invitationViewNeedSyncing
+        visible: !needSyncing
 
         horizontalAlignment: Text.AlignHCenter
         verticalAlignment: Text.AlignVCenter
@@ -58,7 +58,7 @@ Rectangle {
         color: JamiTheme.textColor
         wrapMode: Text.Wrap
 
-        text: JamiStrings.invitationViewSentRequest.arg(invitationViewContactTitle)
+        text: JamiStrings.invitationViewSentRequest.arg(title)
     }
 
     ColumnLayout {
@@ -69,7 +69,7 @@ Rectangle {
         width: root.width
 
         Avatar {
-            id: avatarImage
+            id: avatar
 
             Layout.alignment: Qt.AlignHCenter
             Layout.topMargin: invitationViewSentRequestText.visible ? marginSize : 0
@@ -77,8 +77,7 @@ Rectangle {
             Layout.preferredWidth: JamiTheme.invitationViewAvatarSize
 
             showPresenceIndicator: false
-            mode: Avatar.Mode.Contact
-            imageId: invitationViewImageId
+            mode: Avatar.Mode.Conversation
         }
 
         Text {
@@ -96,7 +95,7 @@ Rectangle {
             color: JamiTheme.textColor
             wrapMode: Text.Wrap
 
-            text: root.invitationViewNeedSyncing ?
+            text: needSyncing ?
                       JamiStrings.invitationViewAcceptedConversation :
                       JamiStrings.invitationViewJoinConversation
         }
@@ -109,7 +108,7 @@ Rectangle {
             Layout.preferredWidth: infoColumnLayout.width - textMarginSize
             Layout.preferredHeight: visible ? contentHeight : 0
 
-            visible: invitationViewNeedSyncing
+            visible: needSyncing
 
             horizontalAlignment: Text.AlignHCenter
             verticalAlignment: Text.AlignVCenter
@@ -118,7 +117,7 @@ Rectangle {
             color: JamiTheme.textColor
             wrapMode: Text.Wrap
 
-            text: JamiStrings.invitationViewWaitingForSync.arg(invitationViewContactTitle)
+            text: JamiStrings.invitationViewWaitingForSync.arg(title)
         }
 
         RowLayout {
@@ -129,7 +128,7 @@ Rectangle {
 
             spacing: JamiTheme.invitationViewButtonsSpacing
 
-            visible: !invitationViewNeedSyncing
+            visible: !needSyncing
 
             PushButton {
                 id: blockButton
diff --git a/src/mainview/components/MessageWebView.qml b/src/mainview/components/MessageWebView.qml
index 4068f16bb..35707086a 100644
--- a/src/mainview/components/MessageWebView.qml
+++ b/src/mainview/components/MessageWebView.qml
@@ -115,7 +115,7 @@ Rectangle {
         target: MessagesAdapter
 
         function onChangeInvitationViewRequest(show, isSwarm, needsSyncing,
-                                               contactTitle, contactUri) {
+                                               title, convId) {
             if (show)
                 root.mode = MessageWebView.Mode.Invitation
             else {
@@ -123,9 +123,9 @@ Rectangle {
                 return
             }
 
-            invitationView.invitationViewImageId = contactUri
-            invitationView.invitationViewContactTitle = contactTitle
-            invitationView.invitationViewNeedSyncing = needsSyncing
+            invitationView.imageId = convId
+            invitationView.title = title
+            invitationView.needSyncing = needsSyncing
         }
     }
 
diff --git a/src/mainview/components/SmartListItemDelegate.qml b/src/mainview/components/SmartListItemDelegate.qml
index 3afc6d6b1..52a6ff309 100644
--- a/src/mainview/components/SmartListItemDelegate.qml
+++ b/src/mainview/components/SmartListItemDelegate.qml
@@ -47,7 +47,7 @@ ItemDelegate {
             id: avatar
 
             imageId: UID
-            showPresenceIndicator: Presence
+            showPresenceIndicator: Presence !== undefined ? Presence : false
 
             Layout.preferredWidth: JamiTheme.smartListAvatarSize
             Layout.preferredHeight: JamiTheme.smartListAvatarSize
diff --git a/src/mainview/components/UserProfile.qml b/src/mainview/components/UserProfile.qml
index 4557fd99c..3d535a68f 100644
--- a/src/mainview/components/UserProfile.qml
+++ b/src/mainview/components/UserProfile.qml
@@ -28,12 +28,11 @@ import "../../commoncomponents"
 BaseDialog {
     id: root
 
-    property string responsibleConvUid: ""
-    property string convId: ""
-    property string aliasText: ""
-    property string registeredNameText: ""
-    property string idText: ""
-    property bool isSwarm: false
+    property string convId
+    property string aliasText
+    property string registeredNameText
+    property string idText
+    property bool isSwarm
 
     property int preferredImgSize: 80
 
@@ -200,7 +199,12 @@ BaseDialog {
                 fillMode: Image.PreserveAspectFit
                 sourceSize.width: preferredImgSize
                 sourceSize.height: preferredImgSize
-                mipmap: true
+                mipmap: false
+                smooth: false
+
+                source: convId !== "" ?
+                            "image://qrImage/contact_" + convId :
+                            ""
             }
 
             Text {
@@ -238,9 +242,4 @@ BaseDialog {
             }
         }
     }
-
-    onResponsibleConvUidChanged: {
-        if (responsibleConvUid !== "")
-            contactQrImage.source = "image://qrImage/contact_" + responsibleConvUid
-    }
 }
diff --git a/src/messagesadapter.cpp b/src/messagesadapter.cpp
index 304ac3938..9782c9b83 100644
--- a/src/messagesadapter.cpp
+++ b/src/messagesadapter.cpp
@@ -57,44 +57,31 @@ MessagesAdapter::safeInit()
 }
 
 void
-MessagesAdapter::setupChatView(const QString& convUid)
+MessagesAdapter::setupChatView(const QVariantMap& convInfo)
 {
-    auto* convModel = lrcInstance_->getCurrentConversationModel();
-    if (convModel == nullptr) {
-        return;
-    }
-
-    const auto& convInfo = lrcInstance_->getConversationFromConvUid(convUid);
-    if (convInfo.uid.isEmpty() || convInfo.participants.isEmpty()) {
-        return;
-    }
-
-    QString contactURI = convInfo.participants.at(0);
-
-    auto selectedAccountId = lrcInstance_->get_currentAccountId();
-    auto& accountInfo = lrcInstance_->accountModel().getAccountInfo(selectedAccountId);
+    bool isLegacy = !convInfo["isSwarm"].toBool();
+    bool isRequest = convInfo["isRequest"].toBool();
+    bool needsSyncing = convInfo["needsSyncing"].toBool();
 
     QMetaObject::invokeMethod(qmlObj_,
                               "setSendContactRequestButtonVisible",
-                              Q_ARG(QVariant, convInfo.isLegacy() && convInfo.isRequest));
+                              Q_ARG(QVariant, isLegacy && isRequest));
     QMetaObject::invokeMethod(qmlObj_,
                               "setMessagingHeaderButtonsVisible",
-                              Q_ARG(QVariant,
-                                    !(convInfo.isLegacy()
-                                      && (convInfo.isRequest || convInfo.needsSyncing))));
+                              Q_ARG(QVariant, !(isLegacy && (isRequest || needsSyncing))));
 
     setMessagesVisibility(false);
-    setIsSwarm(convInfo.isSwarm());
-    changeInvitationViewRequest(convInfo.isRequest or convInfo.needsSyncing,
-                                !convInfo.isSwarm(),
-                                convInfo.needsSyncing,
-                                convModel->title(convInfo.uid),
-                                contactURI);
+    setIsSwarm(!isLegacy);
+    Q_EMIT changeInvitationViewRequest(isRequest || needsSyncing,
+                                       isLegacy,
+                                       needsSyncing,
+                                       convInfo["title"].toString(),
+                                       convInfo["convId"].toString());
 
     Utils::oneShotConnect(qmlObj_, SIGNAL(messagesCleared()), this, SLOT(slotMessagesCleared()));
     clearChatView();
 
-    Q_EMIT newMessageBarPlaceholderText(accountInfo.contactModel->bestNameForContact(contactURI));
+    Q_EMIT newMessageBarPlaceholderText(convInfo["title"].toString());
 }
 
 void
@@ -385,13 +372,15 @@ MessagesAdapter::setConversationProfileData(const lrc::api::conversation::Info&
                                         !(convInfo.isSwarm()
                                           && (convInfo.isRequest || convInfo.needsSyncing))));
 
-        changeInvitationViewRequest(convInfo.isRequest or convInfo.needsSyncing,
-                                    convInfo.isSwarm(),
-                                    convInfo.needsSyncing,
-                                    title,
-                                    contactUri);
+        Q_EMIT changeInvitationViewRequest(convInfo.isRequest or convInfo.needsSyncing,
+                                           convInfo.isSwarm(),
+                                           convInfo.needsSyncing,
+                                           title,
+                                           convInfo.uid);
         if (convInfo.isSwarm())
             return;
+
+        // TODO: swarmify me
         auto& contact = accInfo->contactModel->getContact(contactUri);
         bool isPending = contact.profileInfo.type == profile::Type::TEMPORARY;
         QMetaObject::invokeMethod(qmlObj_,
diff --git a/src/messagesadapter.h b/src/messagesadapter.h
index c97d284c0..69f5d0103 100644
--- a/src/messagesadapter.h
+++ b/src/messagesadapter.h
@@ -41,7 +41,7 @@ public:
 protected:
     void safeInit() override;
 
-    Q_INVOKABLE void setupChatView(const QString& convUid);
+    Q_INVOKABLE void setupChatView(const QVariantMap& convInfo);
     Q_INVOKABLE void connectConversationModel();
     Q_INVOKABLE void sendConversationRequest();
     Q_INVOKABLE void removeConversation(const QString& accountId,
-- 
GitLab