From 71a4b4a252f72fd8e12985d94c657de640364f9c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?S=C3=A9bastien=20Blin?=
 <sebastien.blin@savoirfairelinux.com>
Date: Wed, 24 Aug 2022 09:55:55 -0400
Subject: [PATCH] revert: readstatus: major cleanup

This patch introduced some issues with file transfer

Change-Id: I6e4852f1f1c0eb1e1f820de8a1ecc8e2a6b28695
---
 src/libclient/api/conversationmodel.h |   9 ++
 src/libclient/conversationmodel.cpp   | 148 ++++++++++++++++++++------
 2 files changed, 124 insertions(+), 33 deletions(-)

diff --git a/src/libclient/api/conversationmodel.h b/src/libclient/api/conversationmodel.h
index 81d257633..7da8d5aa0 100644
--- a/src/libclient/api/conversationmodel.h
+++ b/src/libclient/api/conversationmodel.h
@@ -407,6 +407,15 @@ Q_SIGNALS:
     void newInteraction(const QString& uid,
                         QString& interactionId,
                         const interaction::Info& interactionInfo) const;
+    /**
+     * Emitted when an interaction got a new status
+     * @param convUid conversation which owns the interaction
+     * @param interactionId
+     * @param msg
+     */
+    void interactionStatusUpdated(const QString& convUid,
+                                  const QString& interactionId,
+                                  const api::interaction::Info& msg) const;
     /**
      * Emitted when an interaction got removed from the conversation
      * @param convUid conversation which owns the interaction
diff --git a/src/libclient/conversationmodel.cpp b/src/libclient/conversationmodel.cpp
index d0d8f5452..278ff26e1 100644
--- a/src/libclient/conversationmodel.cpp
+++ b/src/libclient/conversationmodel.cpp
@@ -3452,41 +3452,122 @@ ConversationModelPimpl::slotUpdateInteractionStatus(const QString& accountId,
                                                     const QString& messageId,
                                                     int status)
 {
-    if (accountId != linked.owner.id || conversationId.isEmpty())
+    if (accountId != linked.owner.id) {
+        return;
+    }
+    // it may be not swarm conversation check in db
+    if (conversationId.isEmpty() || conversationId == linked.owner.profileInfo.uri) {
+        auto convIds = storage::getConversationsWithPeer(db, peerId);
+        if (convIds.empty()) {
+            return;
+        }
+        auto conversationIdx = indexOf(convIds[0]);
+        auto& conversation = conversations[conversationIdx];
+        auto newStatus = interaction::Status::INVALID;
+        switch (static_cast<DRing::Account::MessageStates>(status)) {
+        case DRing::Account::MessageStates::SENDING:
+            newStatus = interaction::Status::SENDING;
+            break;
+        case DRing::Account::MessageStates::CANCELLED:
+            newStatus = interaction::Status::TRANSFER_CANCELED;
+            break;
+        case DRing::Account::MessageStates::SENT:
+            newStatus = interaction::Status::SUCCESS;
+            break;
+        case DRing::Account::MessageStates::FAILURE:
+            newStatus = interaction::Status::FAILURE;
+            break;
+        case DRing::Account::MessageStates::DISPLAYED:
+            newStatus = interaction::Status::DISPLAYED;
+            break;
+        case DRing::Account::MessageStates::UNKNOWN:
+        default:
+            newStatus = interaction::Status::UNKNOWN;
+            break;
+        }
+        auto idString = messageId;
+        // for not swarm conversation messageId in hexdesimal string format. Convert to normal string
+        // TODO messageId should be received from daemon in string format
+        if (static_cast<DRing::Account::MessageStates>(status)
+            == DRing::Account::MessageStates::DISPLAYED) {
+            std::istringstream ss(messageId.toStdString());
+            ss >> std::hex;
+            uint64_t id;
+            if (!(ss >> id))
+                return;
+            idString = QString::number(id);
+        }
+        // Update database
+        auto interactionId = storage::getInteractionIdByDaemonId(db, idString);
+        if (interactionId.isEmpty()) {
+            return;
+        }
+        auto msgId = interactionId;
+        storage::updateInteractionStatus(db, msgId, newStatus);
+        // Update conversations
+        bool emitUpdated = false;
+        bool updateDisplayedUid = false;
+        QString oldDisplayedUid = 0;
+        {
+            std::lock_guard<std::mutex> lk(interactionsLocks[conversation.uid]);
+            auto& interactions = conversation.interactions;
+            auto it = interactions->find(msgId);
+            auto messageId = conversation.interactions->getRead(peerId);
+            if (it != interactions->end()) {
+                it->second.status = newStatus;
+                interactions->emitDataChanged(it, {MessageList::Role::Status});
+                bool interactionDisplayed = newStatus == interaction::Status::DISPLAYED
+                                            && isOutgoing(it->second);
+                if (messageId != "") {
+                    auto lastDisplayedIt = interactions->find(messageId);
+                    bool interactionIsLast = lastDisplayedIt == interactions->end()
+                                             || lastDisplayedIt->second.timestamp
+                                                    < it->second.timestamp;
+                    updateDisplayedUid = interactionDisplayed && interactionIsLast;
+                    if (updateDisplayedUid) {
+                        oldDisplayedUid = messageId;
+                        if (peerId != linked.owner.profileInfo.uri)
+                            conversation.interactions->setRead(peerId, it->first);
+                    }
+                } else {
+                    oldDisplayedUid = "";
+                    if (peerId != linked.owner.profileInfo.uri)
+                        conversation.interactions->setRead(peerId, it->first);
+                    updateDisplayedUid = true;
+                }
+                emitUpdated = true;
+            }
+        }
+        if (updateDisplayedUid) {
+            Q_EMIT linked.displayedInteractionChanged(conversation.uid,
+                                                      peerId,
+                                                      oldDisplayedUid,
+                                                      msgId);
+        }
+        if (emitUpdated) {
+            invalidateModel();
+        }
         return;
-    auto newStatus = interaction::Status::INVALID;
-    switch (static_cast<DRing::Account::MessageStates>(status)) {
-    case DRing::Account::MessageStates::SENDING:
-        newStatus = interaction::Status::SENDING;
-        break;
-    case DRing::Account::MessageStates::CANCELLED:
-        newStatus = interaction::Status::TRANSFER_CANCELED;
-        break;
-    case DRing::Account::MessageStates::SENT:
-        newStatus = interaction::Status::SUCCESS;
-        break;
-    case DRing::Account::MessageStates::FAILURE:
-        newStatus = interaction::Status::FAILURE;
-        break;
-    case DRing::Account::MessageStates::DISPLAYED:
-        newStatus = interaction::Status::DISPLAYED;
-        break;
-    case DRing::Account::MessageStates::UNKNOWN:
-    default:
-        newStatus = interaction::Status::UNKNOWN;
-        break;
     }
     try {
-        auto& conversation = conversationId.isEmpty()
-                                 ? getConversationForPeerUri(peerId).get() // SIP
-                                 : getConversationForUid(conversationId).get();
-        std::lock_guard<std::mutex> lk(interactionsLocks[conversation.uid]);
-        auto& interactions = conversation.interactions;
-        auto it = interactions->find(messageId);
-        if (it != interactions->end()) {
-            it->second.status = newStatus;
-            interactions->emitDataChanged(it, {MessageList::Role::Status});
-            if (newStatus == interaction::Status::DISPLAYED) {
+        auto& conversation = getConversationForUid(conversationId).get();
+        if (conversation.mode != conversation::Mode::NON_SWARM) {
+            std::lock_guard<std::mutex> lk(interactionsLocks[conversation.uid]);
+            auto& interactions = conversation.interactions;
+            auto it = interactions->find(messageId);
+            if (it != interactions->end() && it->second.type == interaction::Type::TEXT) {
+                if (static_cast<DRing::Account::MessageStates>(status)
+                    == DRing::Account::MessageStates::SENDING) {
+                    it->second.status = interaction::Status::SENDING;
+                } else if (static_cast<DRing::Account::MessageStates>(status)
+                           == DRing::Account::MessageStates::SENT) {
+                    it->second.status = interaction::Status::SUCCESS;
+                }
+                interactions->emitDataChanged(it, {MessageList::Role::Status});
+            }
+
+            if (static_cast<DRing::Account::MessageStates>(status)
+                == DRing::Account::MessageStates::DISPLAYED) {
                 auto previous = conversation.interactions->getRead(peerId);
                 if (peerId != linked.owner.profileInfo.uri)
                     conversation.interactions->setRead(peerId, messageId);
@@ -4074,8 +4155,9 @@ ConversationModelPimpl::updateTransferStatus(const QString& fileId,
             interactions->emitDataChanged(it, roles);
         }
     }
-    if (emitUpdated)
+    if (emitUpdated) {
         invalidateModel();
+    }
     updated = emitUpdated;
     return true;
 }
-- 
GitLab