From 3d71bfa8ae54ad2cc755883c467ef60e0c25f049 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?S=C3=A9bastien=20Blin?=
 <sebastien.blin@savoirfairelinux.com>
Date: Wed, 12 May 2021 16:55:28 -0400
Subject: [PATCH] swarm: first implementation to follow api changes

- use QString for interactionId

- swarm conversations: use loadConversationMessages and
subscribe to newMessagesAvailable signal

- avoid displaying "merge" and empty "data transfer" messages

- link composing status

Change-Id: Ic524bb786b2ff0471f03b1bb02d41d6da38e716a
---
 src/accountadapter.cpp                        |   2 +-
 src/conversationlistmodelbase.cpp             |   4 +-
 src/conversationsadapter.cpp                  |  30 ++---
 src/conversationsadapter.h                    |   2 +-
 src/lrcinstance.cpp                           |   6 -
 src/lrcinstance.h                             |   1 -
 src/mainapplication.cpp                       |   2 +-
 src/mainview/components/AccountComboBox.qml   |   2 +-
 src/mainview/components/WelcomePage.qml       |   4 +-
 .../components/WelcomePageQrDialog.qml        |   2 +-
 src/messagesadapter.cpp                       | 111 ++++++++++--------
 src/messagesadapter.h                         |  16 +--
 src/settingsadapter.cpp                       |   7 +-
 src/smartlistmodel.cpp                        |   9 +-
 src/utils.cpp                                 |   4 +-
 src/webchathelpers.cpp                        |  21 ++--
 src/webchathelpers.h                          |  12 +-
 tests/qml/main.cpp                            |   2 +-
 18 files changed, 121 insertions(+), 116 deletions(-)

diff --git a/src/accountadapter.cpp b/src/accountadapter.cpp
index 1e2fce8eb..4f23825de 100644
--- a/src/accountadapter.cpp
+++ b/src/accountadapter.cpp
@@ -142,7 +142,7 @@ AccountAdapter::createJamiAccount(QString registeredName,
     connectFailure();
 
     QtConcurrent::run([this, settings] {
-        lrcInstance_->accountModel().createNewAccount(lrc::api::profile::Type::RING,
+        lrcInstance_->accountModel().createNewAccount(lrc::api::profile::Type::JAMI,
                                                       settings["alias"].toString(),
                                                       settings["archivePath"].toString(),
                                                       settings["password"].toString(),
diff --git a/src/conversationlistmodelbase.cpp b/src/conversationlistmodelbase.cpp
index f87f5c9d5..189f94c33 100644
--- a/src/conversationlistmodelbase.cpp
+++ b/src/conversationlistmodelbase.cpp
@@ -90,8 +90,8 @@ ConversationListModelBase::dataForItem(item_t item, int role) const
     }
     case Role::LastInteractionDate: {
         if (!item.interactions.empty()) {
-            auto& date = item.interactions.at(item.lastMessageUid).timestamp;
-            return QVariant(Utils::formatTimeString(date));
+            return QVariant(
+                Utils::formatTimeString(item.interactions.at(item.lastMessageUid).timestamp));
         }
         break;
     }
diff --git a/src/conversationsadapter.cpp b/src/conversationsadapter.cpp
index ff20c2c2e..c2b474aa0 100644
--- a/src/conversationsadapter.cpp
+++ b/src/conversationsadapter.cpp
@@ -33,7 +33,7 @@ ConversationsAdapter::ConversationsAdapter(SystemTray* systemTray,
                                            LRCInstance* instance,
                                            QObject* parent)
     : QmlAdapterBase(instance, parent)
-    , currentTypeFilter_(profile::Type::RING)
+    , currentTypeFilter_(profile::Type::JAMI)
     , systemTray_(systemTray)
     , convSrcModel_(new ConversationListModel(lrcInstance_))
     , convModel_(new ConversationListProxyModel(convSrcModel_.get()))
@@ -139,17 +139,17 @@ ConversationsAdapter::safeInit()
 
     Q_EMIT modelChanged(QVariant::fromValue(conversationSmartListModel_));
 
-    connect(&lrcInstance_->behaviorController(),
-            &BehaviorController::newUnreadInteraction,
-            this,
-            &ConversationsAdapter::onNewUnreadInteraction,
-            Qt::UniqueConnection);
+    //    connect(&lrcInstance_->behaviorController(),
+    //            &BehaviorController::newUnreadInteraction,
+    //            this,
+    //            &ConversationsAdapter::onNewUnreadInteraction,
+    //            Qt::UniqueConnection);
 
-    connect(&lrcInstance_->behaviorController(),
-            &BehaviorController::newReadInteraction,
-            this,
-            &ConversationsAdapter::onNewReadInteraction,
-            Qt::UniqueConnection);
+    //  connect(&lrcInstance_->behaviorController(),
+    //          &BehaviorController::newReadInteraction,
+    //          this,
+    //          &ConversationsAdapter::onNewReadInteraction,
+    //          Qt::UniqueConnection);
 
     connect(&lrcInstance_->behaviorController(),
             &BehaviorController::newTrustRequest,
@@ -194,7 +194,7 @@ ConversationsAdapter::onCurrentAccountIdChanged()
 void
 ConversationsAdapter::onNewUnreadInteraction(const QString& accountId,
                                              const QString& convUid,
-                                             uint64_t interactionId,
+                                             const QString& interactionId,
                                              const interaction::Info& interaction)
 {
     if (!interaction.authorUri.isEmpty()
@@ -357,15 +357,15 @@ ConversationsAdapter::updateConversationFilterData()
     int totalUnreadMessages {0};
     if (accountInfo.profileInfo.type != profile::Type::SIP) {
         auto& convModel = accountInfo.conversationModel;
-        auto conversations = convModel->getFilteredConversations(profile::Type::RING, false);
+        auto conversations = convModel->getFilteredConversations(FilterType::JAMI, false);
         conversations.for_each([&totalUnreadMessages](const conversation::Info& conversation) {
             totalUnreadMessages += conversation.unreadMessages;
         });
     }
     set_totalUnreadMessageCount(totalUnreadMessages);
-    set_pendingRequestCount(accountInfo.contactModel->pendingRequestCount());
+    set_pendingRequestCount(accountInfo.conversationModel->pendingRequestCount());
     if (pendingRequestCount_ == 0 && currentTypeFilter_ == profile::Type::PENDING) {
-        set_currentTypeFilter(profile::Type::RING);
+        set_currentTypeFilter(profile::Type::JAMI);
     }
 }
 
diff --git a/src/conversationsadapter.h b/src/conversationsadapter.h
index 11501ab6d..362a6ebe7 100644
--- a/src/conversationsadapter.h
+++ b/src/conversationsadapter.h
@@ -66,7 +66,7 @@ private Q_SLOTS:
     // cross-account slots
     void onNewUnreadInteraction(const QString& accountId,
                                 const QString& convUid,
-                                uint64_t interactionId,
+                                const QString& interactionId,
                                 const interaction::Info& interaction);
     void onNewReadInteraction(const QString& accountId,
                               const QString& convUid,
diff --git a/src/lrcinstance.cpp b/src/lrcinstance.cpp
index bf4caccf0..a96a5e935 100644
--- a/src/lrcinstance.cpp
+++ b/src/lrcinstance.cpp
@@ -76,12 +76,6 @@ LRCInstance::behaviorController()
     return lrc_->getBehaviorController();
 }
 
-DataTransferModel&
-LRCInstance::dataTransferModel()
-{
-    return lrc_->getDataTransferModel();
-}
-
 AVModel&
 LRCInstance::avModel()
 {
diff --git a/src/lrcinstance.h b/src/lrcinstance.h
index ae8fb4ed8..b308b4db3 100644
--- a/src/lrcinstance.h
+++ b/src/lrcinstance.h
@@ -80,7 +80,6 @@ public:
     AVModel& avModel();
     PluginModel& pluginModel();
     BehaviorController& behaviorController();
-    DataTransferModel& dataTransferModel();
 
     void subscribeToDebugReceived();
     bool isConnected();
diff --git a/src/mainapplication.cpp b/src/mainapplication.cpp
index 0727d8180..d3036e4a1 100644
--- a/src/mainapplication.cpp
+++ b/src/mainapplication.cpp
@@ -259,7 +259,7 @@ MainApplication::init()
     }
 
     auto downloadPath = settingsManager_->getValue(Settings::Key::DownloadPath);
-    lrcInstance_->dataTransferModel().downloadDirectory = downloadPath.toString() + "/";
+    lrcInstance_->accountModel().downloadDirectory = downloadPath.toString() + "/";
 
     initQmlLayer();
     initSystray();
diff --git a/src/mainview/components/AccountComboBox.qml b/src/mainview/components/AccountComboBox.qml
index 74ac5f320..aca6119ed 100644
--- a/src/mainview/components/AccountComboBox.qml
+++ b/src/mainview/components/AccountComboBox.qml
@@ -208,7 +208,7 @@ Label {
                 height: visible ? preferredSize : 0
                 anchors.verticalCenter: parent.verticalCenter
 
-                visible: LRCInstance.currentAccountType === Profile.Type.RING
+                visible: LRCInstance.currentAccountType === Profile.Type.JAMI
                 toolTipText: JamiStrings.displayQRCode
 
                 source: "qrc:/images/icons/share-24px.svg"
diff --git a/src/mainview/components/WelcomePage.qml b/src/mainview/components/WelcomePage.qml
index 7dd1865e2..8263aeceb 100644
--- a/src/mainview/components/WelcomePage.qml
+++ b/src/mainview/components/WelcomePage.qml
@@ -90,7 +90,7 @@ Rectangle {
                 horizontalAlignment: Text.AlignHCenter
                 verticalAlignment: Text.AlignVCenter
 
-                visible: LRCInstance.currentAccountType === Profile.Type.RING
+                visible: LRCInstance.currentAccountType === Profile.Type.JAMI
 
                 text: JamiStrings.shareInvite
                 color: JamiTheme.faddedFontColor
@@ -105,7 +105,7 @@ Rectangle {
 
                 color: JamiTheme.secondaryBackgroundColor
 
-                visible: LRCInstance.currentAccountType === Profile.Type.RING
+                visible: LRCInstance.currentAccountType === Profile.Type.JAMI
 
                 ColumnLayout {
                     id: jamiRegisteredNameRectColumnLayout
diff --git a/src/mainview/components/WelcomePageQrDialog.qml b/src/mainview/components/WelcomePageQrDialog.qml
index d21fb7282..57a4f3b9c 100644
--- a/src/mainview/components/WelcomePageQrDialog.qml
+++ b/src/mainview/components/WelcomePageQrDialog.qml
@@ -50,7 +50,7 @@ ModalPopup {
             fillMode: Image.PreserveAspectFit
             source: {
                 if (LRCInstance.currentAccountId &&
-                        LRCInstance.currentAccountType === Profile.Type.RING)
+                        LRCInstance.currentAccountType === Profile.Type.JAMI)
                     return "image://qrImage/account_" + LRCInstance.currentAccountId
                 return ""
             }
diff --git a/src/messagesadapter.cpp b/src/messagesadapter.cpp
index dc48bbe86..4fd6ff823 100644
--- a/src/messagesadapter.cpp
+++ b/src/messagesadapter.cpp
@@ -129,7 +129,7 @@ MessagesAdapter::connectConversationModel()
         = QObject::connect(currentConversationModel,
                            &lrc::api::ConversationModel::newInteraction,
                            [this](const QString& convUid,
-                                  uint64_t interactionId,
+                                  const QString& interactionId,
                                   const lrc::api::interaction::Info& interaction) {
                                auto accountId = lrcInstance_->getCurrentAccountId();
                                newInteraction(accountId, convUid, interactionId, interaction);
@@ -139,7 +139,7 @@ MessagesAdapter::connectConversationModel()
         currentConversationModel,
         &lrc::api::ConversationModel::interactionStatusUpdated,
         [this](const QString& convUid,
-               uint64_t interactionId,
+               const QString& interactionId,
                const lrc::api::interaction::Info& interaction) {
             auto currentConversationModel = lrcInstance_->getCurrentConversationModel();
             currentConversationModel->clearUnreadInteractions(convUid);
@@ -149,10 +149,27 @@ MessagesAdapter::connectConversationModel()
     interactionRemovedConnection_
         = QObject::connect(currentConversationModel,
                            &lrc::api::ConversationModel::interactionRemoved,
-                           [this](const QString& convUid, uint64_t interactionId) {
+                           [this](const QString& convUid, const QString& interactionId) {
                                Q_UNUSED(convUid);
                                removeInteraction(interactionId);
                            });
+
+    newMessagesAvailableConnection_
+        = QObject::connect(currentConversationModel,
+                           &lrc::api::ConversationModel::newMessagesAvailable,
+                           [this](const QString& accountId, const QString& conversationId) {
+                               auto* convModel = lrcInstance_->accountModel()
+                                                     .getAccountInfo(accountId)
+                                                     .conversationModel.get();
+                               auto optConv = convModel->getConversationForUid(conversationId);
+                               if (!optConv)
+                                   return;
+                               printHistory(*convModel, optConv->get().interactions);
+                               Utils::oneShotConnect(qmlObj_,
+                                                     SIGNAL(messagesLoaded()),
+                                                     this,
+                                                     SLOT(slotMessagesLoaded()));
+                           });
 }
 
 void
@@ -173,7 +190,7 @@ MessagesAdapter::updateConversationForAddedContact()
 
     clear();
     setConversationProfileData(convInfo);
-    printHistory(*convModel, convInfo.interactions);
+    //    printHistory(*convModel, convInfo.interactions);
 }
 
 void
@@ -205,14 +222,18 @@ void
 MessagesAdapter::slotMessagesCleared()
 {
     auto* convModel = lrcInstance_->getCurrentConversationModel();
-    const auto& convInfo = lrcInstance_->getConversationFromConvUid(
-        lrcInstance_->get_selectedConvUid());
-
-    printHistory(*convModel, convInfo.interactions);
-
-    Utils::oneShotConnect(qmlObj_, SIGNAL(messagesLoaded()), this, SLOT(slotMessagesLoaded()));
 
-    setConversationProfileData(convInfo);
+    auto convOpt = convModel->getConversationForUid(lrcInstance_->get_selectedConvUid());
+    if (!convOpt)
+        return;
+    if (convOpt->get().mode != lrc::api::conversation::Mode::NON_SWARM
+        && !convOpt->get().allMessagesLoaded) {
+        convModel->loadConversationMessages(convOpt->get().uid, 0);
+    } else {
+        printHistory(*convModel, convOpt->get().interactions);
+        Utils::oneShotConnect(qmlObj_, SIGNAL(messagesLoaded()), this, SLOT(slotMessagesLoaded()));
+    }
+    setConversationProfileData(convOpt->get());
 }
 
 void
@@ -303,16 +324,10 @@ MessagesAdapter::sendFile(const QString& message)
 }
 
 void
-MessagesAdapter::retryInteraction(const QString& arg)
+MessagesAdapter::retryInteraction(const QString& interactionId)
 {
-    bool ok;
-    uint64_t interactionUid = arg.toULongLong(&ok);
-    if (ok) {
-        lrcInstance_->getCurrentConversationModel()
-            ->retryInteraction(lrcInstance_->get_selectedConvUid(), interactionUid);
-    } else {
-        qDebug() << "retryInteraction - invalid arg" << arg;
-    }
+    lrcInstance_->getCurrentConversationModel()
+        ->retryInteraction(lrcInstance_->get_selectedConvUid(), interactionId);
 }
 
 void
@@ -330,16 +345,10 @@ MessagesAdapter::setNewMessagesContent(const QString& path)
 }
 
 void
-MessagesAdapter::deleteInteraction(const QString& arg)
+MessagesAdapter::deleteInteraction(const QString& interactionId)
 {
-    bool ok;
-    uint64_t interactionUid = arg.toULongLong(&ok);
-    if (ok) {
-        lrcInstance_->getCurrentConversationModel()
-            ->clearInteractionFromConversation(lrcInstance_->get_selectedConvUid(), interactionUid);
-    } else {
-        qDebug() << "DeleteInteraction - invalid arg" << arg;
-    }
+    lrcInstance_->getCurrentConversationModel()
+        ->clearInteractionFromConversation(lrcInstance_->get_selectedConvUid(), interactionId);
 }
 
 void
@@ -360,27 +369,17 @@ MessagesAdapter::openUrl(const QString& url)
 }
 
 void
-MessagesAdapter::acceptFile(const QString& arg)
+MessagesAdapter::acceptFile(const QString& interactionId)
 {
-    try {
-        auto interactionUid = arg.toLongLong();
-        auto convUid = lrcInstance_->get_selectedConvUid();
-        lrcInstance_->getCurrentConversationModel()->acceptTransfer(convUid, interactionUid);
-    } catch (...) {
-        qDebug() << "JS bridging - exception during acceptFile: " << arg;
-    }
+    auto convUid = lrcInstance_->get_selectedConvUid();
+    lrcInstance_->getCurrentConversationModel()->acceptTransfer(convUid, interactionId);
 }
 
 void
-MessagesAdapter::refuseFile(const QString& arg)
+MessagesAdapter::refuseFile(const QString& interactionId)
 {
-    try {
-        auto interactionUid = arg.toLongLong();
-        const auto convUid = lrcInstance_->get_selectedConvUid();
-        lrcInstance_->getCurrentConversationModel()->cancelTransfer(convUid, interactionUid);
-    } catch (...) {
-        qDebug() << "JS bridging - exception during refuseFile:" << arg;
-    }
+    const auto convUid = lrcInstance_->get_selectedConvUid();
+    lrcInstance_->getCurrentConversationModel()->cancelTransfer(convUid, interactionId);
 }
 
 void
@@ -475,7 +474,7 @@ MessagesAdapter::setConversationProfileData(const lrc::api::conversation::Info&
 void
 MessagesAdapter::newInteraction(const QString& accountId,
                                 const QString& convUid,
-                                uint64_t interactionId,
+                                const QString& interactionId,
                                 const interaction::Info& interaction)
 {
     Q_UNUSED(interactionId);
@@ -550,7 +549,7 @@ MessagesAdapter::setDisplayLinks()
 
 void
 MessagesAdapter::printHistory(lrc::api::ConversationModel& conversationModel,
-                              const std::map<uint64_t, lrc::api::interaction::Info> interactions)
+                              MessagesList interactions)
 {
     auto interactionsStr = interactionsToJsonArrayObject(conversationModel, interactions).toUtf8();
     QString s = QString::fromLatin1("printHistory(%1);").arg(interactionsStr.constData());
@@ -573,7 +572,7 @@ MessagesAdapter::setSenderImage(const QString& sender, const QString& senderImag
 
 void
 MessagesAdapter::printNewInteraction(lrc::api::ConversationModel& conversationModel,
-                                     uint64_t msgId,
+                                     const QString& msgId,
                                      const lrc::api::interaction::Info& interaction)
 {
     auto interactionObject
@@ -587,7 +586,7 @@ MessagesAdapter::printNewInteraction(lrc::api::ConversationModel& conversationMo
 
 void
 MessagesAdapter::updateInteraction(lrc::api::ConversationModel& conversationModel,
-                                   uint64_t msgId,
+                                   const QString& msgId,
                                    const lrc::api::interaction::Info& interaction)
 {
     auto interactionObject
@@ -629,9 +628,9 @@ MessagesAdapter::setMessagesFileContent(const QString& path)
 }
 
 void
-MessagesAdapter::removeInteraction(uint64_t interactionId)
+MessagesAdapter::removeInteraction(const QString& interactionId)
 {
-    QString s = QString::fromLatin1("removeInteraction(%1);").arg(QString::number(interactionId));
+    QString s = QString::fromLatin1("removeInteraction(%1);").arg(interactionId);
     QMetaObject::invokeMethod(qmlObj_, "webViewRunJavaScript", Q_ARG(QVariant, s));
 }
 
@@ -644,7 +643,15 @@ MessagesAdapter::setSendMessageContent(const QString& content)
 void
 MessagesAdapter::contactIsComposing(const QString& uid, const QString& contactUri, bool isComposing)
 {
-    if (lrcInstance_->get_selectedConvUid() == uid) {
+    auto* convModel = lrcInstance_->getCurrentConversationModel();
+    auto convInfo = convModel->getConversationForUid(lrcInstance_->get_selectedConvUid());
+    if (!convInfo)
+        return;
+    auto& conv = convInfo->get();
+    bool showIsComposing = conv.mode != lrc::api::conversation::Mode::NON_SWARM
+                               ? uid == conv.uid
+                               : uid.isEmpty() && conv.participants.first() == contactUri;
+    if (showIsComposing) {
         QString s
             = QString::fromLatin1("showTypingIndicator(`%1`, %2);").arg(contactUri).arg(isComposing);
         QMetaObject::invokeMethod(qmlObj_, "webViewRunJavaScript", Q_ARG(QVariant, s));
diff --git a/src/messagesadapter.h b/src/messagesadapter.h
index dd776098f..a5cbb78a5 100644
--- a/src/messagesadapter.h
+++ b/src/messagesadapter.h
@@ -59,8 +59,8 @@ protected:
     Q_INVOKABLE void sendMessage(const QString& message);
     Q_INVOKABLE void sendImage(const QString& message);
     Q_INVOKABLE void sendFile(const QString& message);
-    Q_INVOKABLE void retryInteraction(const QString& arg);
-    Q_INVOKABLE void deleteInteraction(const QString& arg);
+    Q_INVOKABLE void retryInteraction(const QString& interactionId);
+    Q_INVOKABLE void deleteInteraction(const QString& interactionId);
     Q_INVOKABLE void openUrl(const QString& url);
     Q_INVOKABLE void openFile(const QString& arg);
     Q_INVOKABLE void acceptFile(const QString& arg);
@@ -76,18 +76,17 @@ protected:
     void requestSendMessageContent();
     void setInvitation(bool show, const QString& contactUri = {}, const QString& contactId = {});
     void clear();
-    void printHistory(lrc::api::ConversationModel& conversationModel,
-                      const std::map<uint64_t, lrc::api::interaction::Info> interactions);
+    void printHistory(lrc::api::ConversationModel& conversationModel, MessagesList interactions);
     void setSenderImage(const QString& sender, const QString& senderImage);
     void printNewInteraction(lrc::api::ConversationModel& conversationModel,
-                             uint64_t msgId,
+                             const QString& msgId,
                              const lrc::api::interaction::Info& interaction);
     void updateInteraction(lrc::api::ConversationModel& conversationModel,
-                           uint64_t msgId,
+                           const QString& msgId,
                            const lrc::api::interaction::Info& interaction);
     void setMessagesImageContent(const QString& path, bool isBased64 = false);
     void setMessagesFileContent(const QString& path);
-    void removeInteraction(uint64_t interactionId);
+    void removeInteraction(const QString& interactionId);
     void setSendMessageContent(const QString& content);
     void contactIsComposing(const QString& convUid, const QString& contactUri, bool isComposing);
 
@@ -107,7 +106,7 @@ private:
     void setConversationProfileData(const lrc::api::conversation::Info& convInfo);
     void newInteraction(const QString& accountId,
                         const QString& convUid,
-                        uint64_t interactionId,
+                        const QString& interactionId,
                         const interaction::Info& interaction);
 
     QString LastConvUid_;
@@ -119,6 +118,7 @@ private:
     QMetaObject::Connection newInteractionConnection_;
     QMetaObject::Connection interactionStatusUpdatedConnection_;
     QMetaObject::Connection interactionRemovedConnection_;
+    QMetaObject::Connection newMessagesAvailableConnection_;
 
     AppSettingsManager* settingsManager_;
 };
diff --git a/src/settingsadapter.cpp b/src/settingsadapter.cpp
index a489d00bb..ef15a53bd 100644
--- a/src/settingsadapter.cpp
+++ b/src/settingsadapter.cpp
@@ -38,12 +38,11 @@ SettingsAdapter::getDir_Document()
 QString
 SettingsAdapter::getDir_Download()
 {
-    QString downloadPath = QDir::toNativeSeparators(
-        lrcInstance_->dataTransferModel().downloadDirectory);
+    QString downloadPath = QDir::toNativeSeparators(lrcInstance_->accountModel().downloadDirectory);
     if (downloadPath.isEmpty()) {
         downloadPath = lrc::api::DataTransferModel::createDefaultDirectory();
         setDownloadPath(downloadPath);
-        lrcInstance_->dataTransferModel().downloadDirectory = downloadPath;
+        lrcInstance_->accountModel().downloadDirectory = downloadPath;
     }
 #ifdef Q_OS_WIN
     int pos = downloadPath.lastIndexOf(QChar('\\'));
@@ -83,7 +82,7 @@ void
 SettingsAdapter::setDownloadPath(QString dir)
 {
     setAppValue(Settings::Key::DownloadPath, dir);
-    lrcInstance_->dataTransferModel().downloadDirectory = dir + "/";
+    lrcInstance_->accountModel().downloadDirectory = dir + "/";
 }
 
 lrc::api::video::ResRateList
diff --git a/src/smartlistmodel.cpp b/src/smartlistmodel.cpp
index 49d9a83bf..754f9c40b 100644
--- a/src/smartlistmodel.cpp
+++ b/src/smartlistmodel.cpp
@@ -50,8 +50,8 @@ SmartListModel::rowCount(const QModelIndex& parent) const
             lrcInstance_->getCurrentAccountId());
         auto& convModel = accInfo.conversationModel;
         if (listModelType_ == Type::TRANSFER) {
-            auto filterType = accInfo.profileInfo.type;
-            return convModel->getFilteredConversations(filterType).size();
+            //            auto filterType = accInfo.profileInfo.type;
+            //            return convModel->getFilteredConversations(filterType).size();
         } else if (listModelType_ == Type::CONFERENCE) {
             auto calls = conferenceables_[ConferenceableItem::CALL];
             auto contacts = conferenceables_[ConferenceableItem::CONTACT];
@@ -81,8 +81,9 @@ SmartListModel::data(const QModelIndex& index, int role) const
                 lrcInstance_->getCurrentAccountId());
             auto& convModel = currentAccountInfo.conversationModel;
             auto filterType = currentAccountInfo.profileInfo.type;
-            auto& item = convModel->getFilteredConversations(filterType).at(index.row());
-            return dataForItem(item, role);
+            return {};
+            // auto& item = convModel->getFilteredConversations(filterType).at(index.row());
+            // return dataForItem(item, role);
         } catch (const std::exception& e) {
             qWarning() << e.what();
         }
diff --git a/src/utils.cpp b/src/utils.cpp
index 05997bf4d..10494d835 100644
--- a/src/utils.cpp
+++ b/src/utils.cpp
@@ -525,7 +525,7 @@ Utils::isContactValid(const QString& contactUid, const lrc::api::ConversationMod
         const auto contact = model.owner.contactModel->getContact(contactUid);
         return (contact.profileInfo.type == lrc::api::profile::Type::PENDING
                 || contact.profileInfo.type == lrc::api::profile::Type::TEMPORARY
-                || contact.profileInfo.type == lrc::api::profile::Type::RING
+                || contact.profileInfo.type == lrc::api::profile::Type::JAMI
                 || contact.profileInfo.type == lrc::api::profile::Type::SIP)
                && !contact.profileInfo.uri.isEmpty();
     } catch (const std::out_of_range& e) {
@@ -804,7 +804,7 @@ Utils::accountPhoto(LRCInstance* instance,
         QString letterStr = (bestId == bestName || bestName == accountInfo.profileInfo.uri)
                                 ? QString()
                                 : bestName;
-        QString prefix = accountInfo.profileInfo.type == lrc::api::profile::Type::RING ? "ring:"
+        QString prefix = accountInfo.profileInfo.type == lrc::api::profile::Type::JAMI ? "ring:"
                                                                                        : "sip:";
         photo = fallbackAvatar(prefix + accountInfo.profileInfo.uri, letterStr, size);
     }
diff --git a/src/webchathelpers.cpp b/src/webchathelpers.cpp
index 1524d15c2..2d87126ef 100644
--- a/src/webchathelpers.cpp
+++ b/src/webchathelpers.cpp
@@ -23,16 +23,21 @@
 
 QJsonObject
 buildInteractionJson(lrc::api::ConversationModel& conversationModel,
-                     const uint64_t msgId,
+                     const QString msgId,
                      const lrc::api::interaction::Info& inter)
 {
     QRegExp reg(".(jpeg|jpg|gif|png)$");
     auto interaction = inter;
-    if (interaction.type == lrc::api::interaction::Type::DATA_TRANSFER
-        && interaction.body.toLower().contains(reg)) {
-        interaction.body = "file://" + interaction.body;
+    if (interaction.type == lrc::api::interaction::Type::DATA_TRANSFER) {
+        if (interaction.body.isEmpty())
+            return {};
+        else if (interaction.body.toLower().contains(reg))
+            interaction.body = "file://" + interaction.body;
     }
 
+    if (interaction.type == lrc::api::interaction::Type::MERGE)
+        return {};
+
     auto sender = interaction.authorUri;
     auto timestamp = QString::number(interaction.timestamp);
     auto direction = lrc::api::interaction::isOutgoing(interaction) ? QString("out")
@@ -40,7 +45,7 @@ buildInteractionJson(lrc::api::ConversationModel& conversationModel,
 
     QJsonObject interactionObject = QJsonObject();
     interactionObject.insert("text", QJsonValue(interaction.body));
-    interactionObject.insert("id", QJsonValue(QString::number(msgId)));
+    interactionObject.insert("id", QJsonValue(msgId));
     interactionObject.insert("sender", QJsonValue(sender));
     interactionObject.insert("sender_contact_method", QJsonValue(sender));
     interactionObject.insert("timestamp", QJsonValue(timestamp));
@@ -60,7 +65,7 @@ buildInteractionJson(lrc::api::ConversationModel& conversationModel,
     case lrc::api::interaction::Type::DATA_TRANSFER: {
         interactionObject.insert("type", QJsonValue("data_transfer"));
         lrc::api::datatransfer::Info info = {};
-        conversationModel.getTransferInfo(msgId, info);
+        // conversationModel.getTransferInfo(msgId, info);
         if (info.status != lrc::api::datatransfer::Status::INVALID) {
             interactionObject.insert("totalSize", QJsonValue(qint64(info.totalSize)));
             interactionObject.insert("progress", QJsonValue(qint64(info.progress)));
@@ -125,7 +130,7 @@ buildInteractionJson(lrc::api::ConversationModel& conversationModel,
 
 QString
 interactionToJsonInteractionObject(lrc::api::ConversationModel& conversationModel,
-                                   const uint64_t msgId,
+                                   const QString& msgId,
                                    const lrc::api::interaction::Info& interaction)
 {
     auto interactionObject = buildInteractionJson(conversationModel, msgId, interaction);
@@ -134,7 +139,7 @@ interactionToJsonInteractionObject(lrc::api::ConversationModel& conversationMode
 
 QString
 interactionsToJsonArrayObject(lrc::api::ConversationModel& conversationModel,
-                              const std::map<uint64_t, lrc::api::interaction::Info> interactions)
+                              MessagesList interactions)
 {
     QJsonArray array;
     for (const auto& interaction : interactions) {
diff --git a/src/webchathelpers.h b/src/webchathelpers.h
index 0354bc060..a35091250 100644
--- a/src/webchathelpers.h
+++ b/src/webchathelpers.h
@@ -26,14 +26,14 @@
 #include <QJsonDocument>
 #include <QJsonObject>
 
+#include "lrcinstance.h"
 #include "api/conversationmodel.h"
 
 QJsonObject buildInteractionJson(lrc::api::ConversationModel& conversationModel,
-                                 const uint64_t msgId,
-                                 const lrc::api::interaction::Info& interaction);
+                                 const QString& msgId,
+                                 lrc::api::interaction::Info& interaction);
 QString interactionToJsonInteractionObject(lrc::api::ConversationModel& conversationModel,
-                                           const uint64_t msgId,
+                                           const QString& msgId,
                                            const lrc::api::interaction::Info& interaction);
-QString interactionsToJsonArrayObject(
-    lrc::api::ConversationModel& conversationModel,
-    const std::map<uint64_t, lrc::api::interaction::Info> interactions);
+QString interactionsToJsonArrayObject(lrc::api::ConversationModel& conversationModel,
+                                      MessagesList interactions);
diff --git a/tests/qml/main.cpp b/tests/qml/main.cpp
index 93f26b6d6..c99c569ba 100644
--- a/tests/qml/main.cpp
+++ b/tests/qml/main.cpp
@@ -77,7 +77,7 @@ public:
         lrcInstance_->subscribeToDebugReceived();
 
         auto downloadPath = settingsManager_->getValue(Settings::Key::DownloadPath);
-        lrcInstance_->dataTransferModel().downloadDirectory = downloadPath.toString() + "/";
+        lrcInstance_->accountModel().downloadDirectory = downloadPath.toString() + "/";
     }
 
     void qmlEngineRegistration(QQmlEngine* engine)
-- 
GitLab