From cb829676e3dfb4f3a3d82800fdb2905f3b08f210 Mon Sep 17 00:00:00 2001
From: Andreas Hatziiliou <andreas.hatziiliou@savoirfairelinux.com>
Date: Tue, 1 Oct 2024 17:59:26 -0400
Subject: [PATCH] file_attachments: fix behaviour when changing conversations

Fixes an issue where the files that were loaded are not cleared
when switching conversations. Implements the correct behavior
for restoring the files as was done with text drafts.

GitLab: #1847
GitLab: #1528

Change-Id: Id04c9820d08f25ef247002da66d99ae893d8495a
---
 src/app/conversationlistmodelbase.cpp          |  4 ++--
 src/app/lrcinstance.cpp                        | 18 ++++++++++++------
 src/app/lrcinstance.h                          |  7 +++++--
 src/app/mainview/components/ChatViewFooter.qml | 18 ++++++++++++++++--
 src/libclient/typedefs.h                       |  1 +
 5 files changed, 36 insertions(+), 12 deletions(-)

diff --git a/src/app/conversationlistmodelbase.cpp b/src/app/conversationlistmodelbase.cpp
index 2a169463e..3d17a7594 100644
--- a/src/app/conversationlistmodelbase.cpp
+++ b/src/app/conversationlistmodelbase.cpp
@@ -99,7 +99,7 @@ ConversationListModelBase::dataForItem(item_t item, int role) const
     }
     case Role::Draft: {
         if (!item.uid.isEmpty())
-            return lrcInstance_->getContentDraft(item.uid, item.accountId);
+            return lrcInstance_->getContentDraft(item.uid, item.accountId)["text"];
         return {};
     }
     case Role::ActiveCallsCount: {
@@ -137,7 +137,7 @@ ConversationListModelBase::dataForItem(item_t item, int role) const
                 auto bestName = interaction.authorUri == accInfo.profileInfo.uri
                                     ? accInfo.accountModel->bestNameForAccount(accInfo.id)
                                     : accInfo.contactModel->bestNameForContact(
-                                        interaction.authorUri);
+                                          interaction.authorUri);
                 lastInteractionBody
                     = interaction::getContactInteractionString(bestName,
                                                                interaction::to_action(
diff --git a/src/app/lrcinstance.cpp b/src/app/lrcinstance.cpp
index e7c381ad5..e2f87e644 100644
--- a/src/app/lrcinstance.cpp
+++ b/src/app/lrcinstance.cpp
@@ -352,30 +352,36 @@ LRCInstance::stopAudioMeter()
     });
 }
 
-QString
+QVariantMap
 LRCInstance::getContentDraft(const QString& convUid, const QString& accountId)
 {
     auto draftKey = accountId + "_" + convUid;
-    return contentDrafts_[draftKey];
+    QVariantMap draftMap;
+    draftMap["text"] = contentDrafts_[draftKey];
+    draftMap["files"] = fileDrafts_[draftKey];
+
+    return draftMap;
 }
 
 void
 LRCInstance::setContentDraft(const QString& convUid,
                              const QString& accountId,
-                             const QString& content)
+                             const QString& textDraft,
+                             const QList<QString>& filePathDraft)
 {
     if (accountId.isEmpty() || convUid.isEmpty()) {
         return;
     }
-
     auto draftKey = accountId + "_" + convUid;
 
     // prevent a senseless dataChanged signal from the
     // model if nothing has changed
-    if (contentDrafts_[draftKey] == content)
+    if (contentDrafts_[draftKey] == textDraft && fileDrafts_[draftKey] == filePathDraft) {
         return;
+    }
 
-    contentDrafts_[draftKey] = content;
+    contentDrafts_[draftKey] = textDraft;
+    fileDrafts_[draftKey] = filePathDraft;
     // this signal is only needed to update the current smartlist
     Q_EMIT draftSaved(convUid);
 }
diff --git a/src/app/lrcinstance.h b/src/app/lrcinstance.h
index 3a853e1da..d1cc85412 100644
--- a/src/app/lrcinstance.h
+++ b/src/app/lrcinstance.h
@@ -102,10 +102,12 @@ public:
     Q_INVOKABLE void deselectConversation();
     Q_INVOKABLE void makeConversationPermanent(const QString& convId = {},
                                                const QString& accountId = {});
-    Q_INVOKABLE QString getContentDraft(const QString& convUid, const QString& accountId);
+    Q_INVOKABLE QVariantMap getContentDraft(const QString& convUid, const QString& accountId);
     Q_INVOKABLE void setContentDraft(const QString& convUid,
                                      const QString& accountId,
-                                     const QString& content);
+                                     const QString& textDraft,
+                                     const QList<QString>& filePathDraft);
+
     Q_INVOKABLE int indexOfActiveCall(const QString& confId,
                                       const QString& uri,
                                       const QString& deviceId);
@@ -157,6 +159,7 @@ private:
     QString selectedConvUid_;
     MapStringString contentDrafts_;
     MapStringString lastConferences_;
+    MapStringListString fileDrafts_;
 
     conversation::Info invalid {"", nullptr};
 
diff --git a/src/app/mainview/components/ChatViewFooter.qml b/src/app/mainview/components/ChatViewFooter.qml
index e9deee613..70dc63c50 100644
--- a/src/app/mainview/components/ChatViewFooter.qml
+++ b/src/app/mainview/components/ChatViewFooter.qml
@@ -43,17 +43,31 @@ Rectangle {
     color: JamiTheme.primaryBackgroundColor
 
     function updateMessageDraft() {
-        LRCInstance.setContentDraft(previousConvId, previousAccountId, messageBar.text);
+        // Store the current files that have not been sent, if any. Do the same for the message draft.
+        var filePathDraft = [];
+        while(messageBar.fileContainer.filesToSendCount > 0) {
+            var currentIndex = messageBar.fileContainer.filesToSendListModel.index(0, 0);
+            var filePath = messageBar.fileContainer.filesToSendListModel.data(currentIndex, FilesToSend.FilePath);
+            filePathDraft.push(filePath);
+            messageBar.fileContainer.filesToSendListModel.removeFromPending(0);
+        }
+        LRCInstance.setContentDraft(previousConvId, previousAccountId, messageBar.text, filePathDraft);
         previousConvId = CurrentConversation.id;
         previousAccountId = CurrentAccount.id;
 
         // turn off the button animations when switching convs
         messageBar.animate = false;
         messageBar.textAreaObj.clearText();
+
+        // restore the draft state of contents for a specific conversation
         var restoredContent = LRCInstance.getContentDraft(CurrentConversation.id, CurrentAccount.id);
         if (restoredContent) {
-            messageBar.textAreaObj.insertText(restoredContent);
+            messageBar.textAreaObj.insertText(restoredContent["text"]);
+            for (var i = 0; i < restoredContent["files"].length; ++i) {
+                messageBar.fileContainer.filesToSendListModel.addToPending(restoredContent["files"][i]);
+            }
         }
+
     }
 
     Connections {
diff --git a/src/libclient/typedefs.h b/src/libclient/typedefs.h
index de6796b11..f32ec36ac 100644
--- a/src/libclient/typedefs.h
+++ b/src/libclient/typedefs.h
@@ -39,6 +39,7 @@ Q_DECLARE_LOGGING_CATEGORY(libclientLog)
 
 // Typedefs (required to avoid '<' and '>' in the DBus XML)
 typedef QMap<QString, QString> MapStringString;
+typedef QMap<QString, QList<QString>> MapStringListString;
 typedef QMap<QString, int> MapStringInt;
 typedef QMap<QString, double> MapStringDouble;
 typedef QMap<QPair<QString, QString>, bool> MapPairStrStrBool;
-- 
GitLab