From 58ffa3ed8262cc7ec0233ce61bceb1217ee297de Mon Sep 17 00:00:00 2001
From: kkostiuk <kateryna.kostiuk@savoirfairelinux.com>
Date: Thu, 11 Mar 2021 16:31:10 -0500
Subject: [PATCH] swarm: transfer model per account

Change-Id: Iac73a4ae43fec2228e04f3156239ca9a4ebeab85
---
 src/api/account.h           |  2 +
 src/api/datatransfermodel.h |  7 ----
 src/api/lrc.h               |  5 ---
 src/api/newaccountmodel.h   | 16 +++++---
 src/callbackshandler.cpp    |  9 ++++-
 src/conversationmodel.cpp   | 74 ++++++++++++++++++++++++-------------
 src/lrc.cpp                 |  8 ----
 src/newaccountmodel.cpp     |  2 +
 8 files changed, 71 insertions(+), 52 deletions(-)

diff --git a/src/api/account.h b/src/api/account.h
index 1a7924dd..59deb661 100644
--- a/src/api/account.h
+++ b/src/api/account.h
@@ -37,6 +37,7 @@ class NewAccountModel;
 class NewDeviceModel;
 class NewCodecModel;
 class PeerDiscoveryModel;
+class DataTransferModel;
 
 namespace account {
 Q_NAMESPACE
@@ -224,6 +225,7 @@ struct Info
     std::unique_ptr<lrc::api::NewDeviceModel> deviceModel;
     std::unique_ptr<lrc::api::NewCodecModel> codecModel;
     std::unique_ptr<lrc::api::PeerDiscoveryModel> peerDiscoveryModel;
+    std::unique_ptr<DataTransferModel> dataTransferModel;
     NewAccountModel* accountModel {nullptr};
 
     // daemon config
diff --git a/src/api/datatransfermodel.h b/src/api/datatransfermodel.h
index 2794bfad..1e6fadf0 100644
--- a/src/api/datatransfermodel.h
+++ b/src/api/datatransfermodel.h
@@ -47,7 +47,6 @@ class Info;
 class LIB_EXPORT DataTransferModel : public QObject
 {
     Q_OBJECT
-    Q_PROPERTY(QString downloadDirectory_qml MEMBER downloadDirectory)
 public:
     DataTransferModel();
     ~DataTransferModel();
@@ -85,12 +84,6 @@ public:
 
     DataTransferId getDringIdFromInteractionId(const QString& interactionId);
 
-    /**
-     * Used when images < 20 Mb are automatically accepted and downloaded
-     * Should contains the full directory with the end marker (/ on linux for example)
-     */
-    QString downloadDirectory;
-
     /**
      *  Creates APPDATA/received and return the path
      */
diff --git a/src/api/lrc.h b/src/api/lrc.h
index 6ee0355a..96cf7641 100644
--- a/src/api/lrc.h
+++ b/src/api/lrc.h
@@ -59,11 +59,6 @@ public:
      * @return a BehaviorController&.
      */
     BehaviorController& getBehaviorController() const;
-    /**
-     * get a reference on the DataTransfer controller.
-     * @return a DataTransferModel&.
-     */
-    DataTransferModel& getDataTransferModel() const;
     /**
      * get a reference on the audio-video controller.
      * @return a AVModel&.
diff --git a/src/api/newaccountmodel.h b/src/api/newaccountmodel.h
index 148e2feb..c8a0e17a 100644
--- a/src/api/newaccountmodel.h
+++ b/src/api/newaccountmodel.h
@@ -48,6 +48,7 @@ class BehaviorController;
 class LIB_EXPORT NewAccountModel : public QObject
 {
     Q_OBJECT
+    Q_PROPERTY(QString downloadDirectory_qml MEMBER downloadDirectory)
 public:
     NewAccountModel(Lrc& lrc,
                     const CallbacksHandler& callbackHandler,
@@ -70,6 +71,12 @@ public:
      * flag account corresponding to passed id as freeable.
      */
     void flagFreeable(const QString& accountId) const;
+
+    /**
+     * Used when images < 20 Mb are automatically accepted and downloaded
+     * Should contains the full directory with the end marker (/ on linux for example)
+     */
+    QString downloadDirectory;
     /**
      * set account enable/disable, save config and do unregister for account
      * @param accountId.
@@ -154,11 +161,10 @@ public:
      * @param config
      * @return the account id
      */
-    static QString connectToAccountManager(
-        const QString& username,
-        const QString& password,
-        const QString& serverUri,
-        const MapStringString& config = MapStringString());
+    static QString connectToAccountManager(const QString& username,
+                                           const QString& password,
+                                           const QString& serverUri,
+                                           const MapStringString& config = MapStringString());
     /**
      * Create a new Ring or SIP account
      * @param type determine if the new account will be a Ring account or a SIP one
diff --git a/src/callbackshandler.cpp b/src/callbackshandler.cpp
index 01ee01be..0101b60d 100644
--- a/src/callbackshandler.cpp
+++ b/src/callbackshandler.cpp
@@ -519,12 +519,17 @@ CallbacksHandler::slotAccountMessageStatusChanged(const QString& accountId,
 }
 
 void
-CallbacksHandler::slotDataTransferEvent(const QString& accountId, const QString& conversationId, DataTransferId dringId, uint codeStatus)
+CallbacksHandler::slotDataTransferEvent(const QString& accountId,
+                                        const QString& conversationId,
+                                        DataTransferId dringId,
+                                        uint codeStatus)
 {
     auto event = DRing::DataTransferEventCode(codeStatus);
 
     api::datatransfer::Info info;
-    parent.getDataTransferModel().transferInfo(accountId, conversationId, dringId, info);
+    parent.getAccountModel()
+        .getAccountInfo(accountId)
+        .dataTransferModel->transferInfo(accountId, conversationId, dringId, info);
 
     // WARNING: info.status could be INVALID in case of async signaling
     // So listeners must only take account of dringId in such case.
diff --git a/src/conversationmodel.cpp b/src/conversationmodel.cpp
index 0738adeb..40c80c85 100644
--- a/src/conversationmodel.cpp
+++ b/src/conversationmodel.cpp
@@ -2160,7 +2160,10 @@ ConversationModelPimpl::slotMessageReceived(const QString& accountId,
             // conversation id and db id
             QString transferId = message["tid"];
             transferIdInt = std::stoull(message["tid"].toStdString());
-            lrc.getDataTransferModel().transferInfo(accountId, conversationId, transferIdInt, info);
+            linked.owner.dataTransferModel->transferInfo(accountId,
+                                                         conversationId,
+                                                         transferIdInt,
+                                                         info);
             // create db entry for valid data transfer
             if (info.status != datatransfer::Status::INVALID) {
                 msg.body = info.path;
@@ -2168,12 +2171,10 @@ ConversationModelPimpl::slotMessageReceived(const QString& accountId,
                               && !interaction::isOutgoing(msg))
                                  ? interaction::Status::TRANSFER_AWAITING_HOST
                                  : interaction::Status::TRANSFER_CREATED;
-                auto interactionId = storage::addDataTransferToConversation(db,
-                                                                            conversationId,
-                                                                            info);
-                transfIdToDbIntId[transferId] = interactionId;
-                lrc.getDataTransferModel().registerTransferId(transferIdInt, msgId);
             }
+            auto interactionId = storage::addDataTransferToConversation(db, conversationId, info);
+            transfIdToDbIntId[transferId] = interactionId;
+            linked.owner.dataTransferModel->registerTransferId(transferIdInt, msgId);
         } else if (msg.type == interaction::Type::CALL) {
             msg.body = storage::getCallInteractionString(msg.authorUri, msg.duration);
         } else if (msg.type == interaction::Type::TEXT
@@ -3244,7 +3245,7 @@ ConversationModel::sendFile(const QString& convUid, const QString& path, const Q
          conversationReady callback could be updated to ONE_TO_ONE. We still use conversationReady
          callback for one_to_one conversation to check if contact is blocked*/
         if (peers.size() > 1) {
-            pimpl_->lrc.getDataTransferModel().sendFile(owner.id, "", convUid, path, filename);
+            owner.dataTransferModel->sendFile(owner.id, "", convUid, path, filename);
         }
         const auto peerId = peers.front();
         bool isTemporary = peerId == convUid;
@@ -3257,7 +3258,7 @@ ConversationModel::sendFile(const QString& convUid, const QString& path, const Q
 
         pimpl_->sendContactRequest(peerId);
 
-        auto cb = ([this, isTemporary, peerId, path, filename](QString conversationId) {
+        auto cb = ([this, peerId, path, filename](QString conversationId) {
             try {
                 auto conversationOpt = getConversationForUid(conversationId);
                 if (!conversationOpt.has_value()) {
@@ -3272,7 +3273,7 @@ ConversationModel::sendFile(const QString& convUid, const QString& path, const Q
                 auto& conversation = conversationOpt->get();
                 // for non swarm conversation id should be empty, so peerId will be takin in consideration
                 auto id = conversation.mode != conversation::Mode::NON_SWARM ? conversationId : "";
-                pimpl_->lrc.getDataTransferModel().sendFile(owner.id, peerId, id, path, filename);
+                owner.dataTransferModel->sendFile(owner.id, peerId, id, path, filename);
             } catch (...) {
             }
         });
@@ -3346,7 +3347,7 @@ ConversationModel::cancelTransfer(const QString& convUid, const QString& interac
         getTransferInfo(convUid, interactionId, info);
         auto identifier = info.conversationId.isEmpty() ? info.peerUri : convUid;
         // Forward cancel action to daemon (will invoke slotTransferStatusCanceled)
-        pimpl_->lrc.getDataTransferModel().cancel(owner.id, identifier, interactionId);
+        owner.dataTransferModel->cancel(owner.id, identifier, interactionId);
         pimpl_->invalidateModel();
         emit interactionStatusUpdated(convUid, interactionId, itCopy);
         emit pimpl_->behaviorController.newReadInteraction(owner.id, convUid, interactionId);
@@ -3359,8 +3360,12 @@ ConversationModel::getTransferInfo(const QString& conversationId,
                                    datatransfer::Info& info)
 {
     try {
-        auto dringId = pimpl_->lrc.getDataTransferModel().getDringIdFromInteractionId(interactionId);
-        pimpl_->lrc.getDataTransferModel().transferInfo(owner.id, conversationId, dringId, info);
+        auto dringId = pimpl_->linked.owner.dataTransferModel->getDringIdFromInteractionId(
+            interactionId);
+        pimpl_->linked.owner.dataTransferModel->transferInfo(owner.id,
+                                                             conversationId,
+                                                             dringId,
+                                                             info);
     } catch (...) {
         info.status = datatransfer::Status::INVALID;
     }
@@ -3381,7 +3386,7 @@ ConversationModelPimpl::usefulDataFromDataTransfer(DataTransferId dringId,
     if (info.accountId != linked.owner.id)
         return false;
     try {
-        interactionId = lrc.getDataTransferModel().getInteractionIdFromDringId(dringId);
+        interactionId = linked.owner.dataTransferModel->getInteractionIdFromDringId(dringId);
         conversationId = info.conversationId.isEmpty()
                              ? storage::conversationIdFromInteractionId(db, interactionId)
                              : info.conversationId;
@@ -3424,7 +3429,7 @@ ConversationModelPimpl::slotTransferStatusCreated(DataTransferId dringId, datatr
     auto interactionId = storage::addDataTransferToConversation(db, convId, info);
 
     // map dringId and interactionId for latter retrivial from client (that only known the interactionId)
-    lrc.getDataTransferModel().registerTransferId(dringId, interactionId);
+    linked.owner.dataTransferModel->registerTransferId(dringId, interactionId);
 
     auto interaction = interaction::Info {info.isOutgoing ? "" : info.peerUri,
                                           info.isOutgoing ? info.path : info.displayName,
@@ -3462,6 +3467,8 @@ void
 ConversationModelPimpl::slotTransferStatusAwaitingPeer(DataTransferId dringId,
                                                        datatransfer::Info info)
 {
+    if (info.accountId != linked.owner.id)
+        return;
     bool intUpdated;
     updateTransferStatus(dringId, info, interaction::Status::TRANSFER_AWAITING_PEER, intUpdated);
 }
@@ -3470,6 +3477,8 @@ void
 ConversationModelPimpl::slotTransferStatusAwaitingHost(DataTransferId dringId,
                                                        datatransfer::Info info)
 {
+    if (info.accountId != linked.owner.id)
+        return;
     awaitingHost(dringId, info);
 }
 
@@ -3487,6 +3496,8 @@ ConversationModelPimpl::hasOneOneSwarmWith(const QString& participant)
 void
 ConversationModelPimpl::awaitingHost(DataTransferId dringId, datatransfer::Info info)
 {
+    if (info.accountId != linked.owner.id)
+        return;
     QString interactionId;
     QString conversationId;
     if (not usefulDataFromDataTransfer(dringId, info, interactionId, conversationId))
@@ -3506,7 +3517,7 @@ ConversationModelPimpl::awaitingHost(DataTransferId dringId, datatransfer::Info
     auto conversationIdx = indexOf(conversationId);
     auto& peers = peersForConversation(conversations[conversationIdx]);
     // Only accept if contact is added or it is a group conversation
-    if (lrc.getDataTransferModel().acceptFromUnstrusted && peers.size() == 1) {
+    if (linked.owner.dataTransferModel->acceptFromUnstrusted && peers.size() == 1) {
         try {
             auto contactUri = peers.front();
             auto contactInfo = linked.owner.contactModel->getContact(contactUri);
@@ -3517,9 +3528,9 @@ ConversationModelPimpl::awaitingHost(DataTransferId dringId, datatransfer::Info
         }
     }
     // If it's an accepted file type and less than 20 MB, accept transfer.
-    if (lrc.getDataTransferModel().automaticAcceptTransfer) {
-        if (lrc.getDataTransferModel().acceptBehindMb == 0
-            || info.totalSize < lrc.getDataTransferModel().acceptBehindMb * 1024 * 1024) {
+    if (linked.owner.dataTransferModel->automaticAcceptTransfer) {
+        if (linked.owner.dataTransferModel->acceptBehindMb == 0
+            || info.totalSize < linked.owner.dataTransferModel->acceptBehindMb * 1024 * 1024) {
             acceptTransfer(conversationId, interactionId, info.displayName);
         }
     }
@@ -3530,7 +3541,7 @@ ConversationModelPimpl::acceptTransfer(const QString& convUid,
                                        const QString& interactionId,
                                        const QString& path)
 {
-    auto destinationDir = lrc.getDataTransferModel().downloadDirectory;
+    auto destinationDir = linked.owner.accountModel->downloadDirectory;
     if (destinationDir.isEmpty()) {
         return;
     }
@@ -3547,12 +3558,12 @@ ConversationModelPimpl::acceptTransfer(const QString& convUid,
     auto identifier = conversation.mode != conversation::Mode::NON_SWARM
                           ? convUid
                           : peersForConversation(conversation).front();
-    auto acceptedFilePath = lrc.getDataTransferModel().accept(linked.owner.id,
-                                                              identifier,
-                                                              interactionId,
-                                                              destinationDir + path,
-                                                              0);
-    auto dringId = lrc.getDataTransferModel().getDringIdFromInteractionId(interactionId);
+    auto acceptedFilePath = linked.owner.dataTransferModel->accept(linked.owner.id,
+                                                                   identifier,
+                                                                   interactionId,
+                                                                   destinationDir + path,
+                                                                   0);
+    auto dringId = linked.owner.dataTransferModel->getDringIdFromInteractionId(interactionId);
     if (transfIdToDbIntId.find(QString::number(dringId)) != transfIdToDbIntId.end()) {
         auto dbInteractionId = transfIdToDbIntId[QString::number(dringId)];
         storage::updateInteractionBody(db, dbInteractionId, acceptedFilePath);
@@ -3598,6 +3609,8 @@ ConversationModelPimpl::invalidateModel()
 void
 ConversationModelPimpl::slotTransferStatusOngoing(DataTransferId dringId, datatransfer::Info info)
 {
+    if (info.accountId != linked.owner.id)
+        return;
     QString interactionId;
     QString conversationId;
     if (not usefulDataFromDataTransfer(dringId, info, interactionId, conversationId))
@@ -3621,6 +3634,8 @@ ConversationModelPimpl::slotTransferStatusOngoing(DataTransferId dringId, datatr
 void
 ConversationModelPimpl::slotTransferStatusFinished(DataTransferId dringId, datatransfer::Info info)
 {
+    if (info.accountId != linked.owner.id)
+        return;
     QString interactionId;
     QString conversationId;
     if (not usefulDataFromDataTransfer(dringId, info, interactionId, conversationId))
@@ -3664,6 +3679,8 @@ ConversationModelPimpl::slotTransferStatusFinished(DataTransferId dringId, datat
 void
 ConversationModelPimpl::slotTransferStatusCanceled(DataTransferId dringId, datatransfer::Info info)
 {
+    if (info.accountId != linked.owner.id)
+        return;
     bool intUpdated;
     updateTransferStatus(dringId, info, interaction::Status::TRANSFER_CANCELED, intUpdated);
 }
@@ -3671,6 +3688,8 @@ ConversationModelPimpl::slotTransferStatusCanceled(DataTransferId dringId, datat
 void
 ConversationModelPimpl::slotTransferStatusError(DataTransferId dringId, datatransfer::Info info)
 {
+    if (info.accountId != linked.owner.id)
+        return;
     bool intUpdated;
     updateTransferStatus(dringId, info, interaction::Status::TRANSFER_ERROR, intUpdated);
 }
@@ -3678,6 +3697,8 @@ ConversationModelPimpl::slotTransferStatusError(DataTransferId dringId, datatran
 void
 ConversationModelPimpl::slotTransferStatusUnjoinable(DataTransferId dringId, datatransfer::Info info)
 {
+    if (info.accountId != linked.owner.id)
+        return;
     bool intUpdated;
     updateTransferStatus(dringId, info, interaction::Status::TRANSFER_UNJOINABLE_PEER, intUpdated);
 }
@@ -3686,6 +3707,8 @@ void
 ConversationModelPimpl::slotTransferStatusTimeoutExpired(DataTransferId dringId,
                                                          datatransfer::Info info)
 {
+    if (info.accountId != linked.owner.id)
+        return;
     bool intUpdated;
     updateTransferStatus(dringId, info, interaction::Status::TRANSFER_TIMEOUT_EXPIRED, intUpdated);
 }
@@ -3724,6 +3747,7 @@ ConversationModelPimpl::updateTransferStatus(DataTransferId dringId,
         if (it != interactions.end()) {
             emitUpdated = true;
             it->second.status = newStatus;
+            it->second.body = info.path;
             itCopy = it->second;
         }
     }
diff --git a/src/lrc.cpp b/src/lrc.cpp
index 74bf381d..74e2e96e 100644
--- a/src/lrc.cpp
+++ b/src/lrc.cpp
@@ -60,7 +60,6 @@ public:
     std::unique_ptr<BehaviorController> behaviorController;
     std::unique_ptr<CallbacksHandler> callbackHandler;
     std::unique_ptr<NewAccountModel> accountModel;
-    std::unique_ptr<DataTransferModel> dataTransferModel;
     std::unique_ptr<AVModel> AVModel_;
     std::unique_ptr<PluginModel> PluginModel_;
 };
@@ -100,12 +99,6 @@ Lrc::getBehaviorController() const
     return *lrcPimpl_->behaviorController;
 }
 
-DataTransferModel&
-Lrc::getDataTransferModel() const
-{
-    return *lrcPimpl_->dataTransferModel;
-}
-
 AVModel&
 Lrc::getAVModel() const
 {
@@ -229,7 +222,6 @@ LrcPimpl::LrcPimpl(Lrc& linked, MigrationCb& willMigrateCb, MigrationCb& didMigr
                                                      *behaviorController,
                                                      willMigrateCb,
                                                      didMigrateCb))
-    , dataTransferModel {std::make_unique<DataTransferModel>()}
     , AVModel_ {std::make_unique<AVModel>(*callbackHandler)}
     , PluginModel_ {std::make_unique<PluginModel>()}
 {}
diff --git a/src/newaccountmodel.cpp b/src/newaccountmodel.cpp
index 45652872..fe644aa6 100644
--- a/src/newaccountmodel.cpp
+++ b/src/newaccountmodel.cpp
@@ -29,6 +29,7 @@
 #include "api/newcodecmodel.h"
 #include "api/newdevicemodel.h"
 #include "api/behaviorcontroller.h"
+#include "api/datatransfermodel.h"
 #include "authority/storagehelper.h"
 #include "callbackshandler.h"
 #include "database.h"
@@ -751,6 +752,7 @@ NewAccountModelPimpl::addToAccounts(const QString& accountId, std::shared_ptr<Da
                                                                          accountId);
     newAccInfo.deviceModel = std::make_unique<NewDeviceModel>(newAccInfo, callbacksHandler);
     newAccInfo.codecModel = std::make_unique<NewCodecModel>(newAccInfo, callbacksHandler);
+    newAccInfo.dataTransferModel = std::make_unique<DataTransferModel>();
 }
 
 void
-- 
GitLab