From 3d3b4612df398b2aa01ec6b18019b07fec34a8c2 Mon Sep 17 00:00:00 2001
From: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
Date: Mon, 22 Jan 2024 18:25:29 -0500
Subject: [PATCH] chat-view: fix loading data transfer items

- Avoids manually building local file URIs which was causing long load times for conversations on Windows.

- Fixes an issue where missing images were caused by a interaction updates erasing the message bodies.

Change-Id: I4c65f73cf9f46da5a9ae899940cb205cb34ffae2
---
 .../DataTransferMessageDelegate.qml           | 32 +++++++++----------
 src/app/mainapplication.cpp                   |  2 +-
 .../mainview/components/DocumentPreview.qml   |  4 +--
 .../mainview/components/MessageListView.qml   |  2 +-
 src/app/webengine/MediaPreviewBase.qml        |  2 +-
 src/app/webengine/VideoPreview.qml            |  2 +-
 src/libclient/api/interaction.h               |  6 ++--
 src/libclient/conversationmodel.cpp           |  5 +--
 src/libclient/messagelistmodel.cpp            |  7 ++--
 9 files changed, 34 insertions(+), 28 deletions(-)

diff --git a/src/app/commoncomponents/DataTransferMessageDelegate.qml b/src/app/commoncomponents/DataTransferMessageDelegate.qml
index f06a02724..fce9697e3 100644
--- a/src/app/commoncomponents/DataTransferMessageDelegate.qml
+++ b/src/app/commoncomponents/DataTransferMessageDelegate.qml
@@ -40,19 +40,20 @@ Loader {
     property int seq: MsgSeq.single
     property string author: Author
     property string body: Body
-    property var transferStatus: Status
-
-    width: ListView.view ? ListView.view.width : 0
-
-    sourceComponent: {
-        if (root.transferStatus === Interaction.Status.TRANSFER_FINISHED) {
-            mediaInfo = MessagesAdapter.getMediaInfo(root.body)
-            if (Object.keys(mediaInfo).length !== 0 && WITH_WEBENGINE)
-                return localMediaMsgComp
+    property int transferStatus: Status
+    onTransferStatusChanged: {
+        if (transferStatus === Interaction.Status.TRANSFER_FINISHED) {
+            mediaInfo = MessagesAdapter.getMediaInfo(root.body);
+            if (Object.keys(mediaInfo).length !== 0 && WITH_WEBENGINE) {
+                sourceComponent = localMediaMsgComp;
+                return;
+            }
         }
-        return dataTransferMsgComp
+        sourceComponent = dataTransferMsgComp;
     }
 
+    width: ListView.view ? ListView.view.width : 0
+
     opacity: 0
     Behavior on opacity { NumberAnimation { duration: 100 } }
     onLoaded: opacity = 1
@@ -294,8 +295,6 @@ Loader {
                         return avComp
                     }
 
-
-
                     Component {
                         id: avComp
 
@@ -304,7 +303,7 @@ Loader {
                                 var qml = WITH_WEBENGINE ?
                                             "qrc:/webengine/MediaPreviewBase.qml" :
                                             "qrc:/nowebengine/MediaPreviewBase.qml"
-                                setSource( qml, { isVideo: mediaInfo.isVideo, html:mediaInfo.html } )
+                                setSource( qml, { isVideo: mediaInfo.isVideo, html: mediaInfo.html } )
                             }
                         }
                     }
@@ -383,9 +382,11 @@ Loader {
                             antialiasing: true
                             autoTransform: true
                             asynchronous: true
-                            source: Body !== undefined ? UtilsAdapter.urlFromLocalPath(Body) : ''
 
-                            Component.onCompleted: localMediaMsgItem.bubble.imgSource = source
+                            Component.onCompleted: {
+                                source = UtilsAdapter.urlFromLocalPath(Body);
+                                localMediaMsgItem.bubble.imgSource = source;
+                            }
 
                             // The sourceSize represents the maximum source dimensions.
                             // This should not be a dynamic binding, as property changes
@@ -401,7 +402,6 @@ Loader {
                                 if (img.status == Image.Ready && aspectRatio) {
                                     height = Qt.binding(() => JamiQmlUtils.clamp(idealWidth / aspectRatio, 64, 256))
                                     width = Qt.binding(() => height * aspectRatio)
-
                                 }
                             }
 
diff --git a/src/app/mainapplication.cpp b/src/app/mainapplication.cpp
index 7a0479efb..48b4fed51 100644
--- a/src/app/mainapplication.cpp
+++ b/src/app/mainapplication.cpp
@@ -70,7 +70,7 @@ messageHandler(QtMsgType type, const QMessageLogContext& context, const QString&
     // In debug mode, always include file URI (including line info).
     // Only do this when the level Info/Debug, as it is already included in the constructed
     // message for the other levels.
-    if (type == QtDebugMsg || type == QtInfoMsg) {
+    if (type == QtDebugMsg || type == QtInfoMsg || !isQml) {
         auto fileName = isQml ? context.file : QUrl::fromLocalFile(context.file).toString();
         fileLineInfo = QString(" %1:%2").arg(!fileName.isEmpty() ? fileName : "unknown",
                                              context.line ? QString::number(context.line) : "0");
diff --git a/src/app/mainview/components/DocumentPreview.qml b/src/app/mainview/components/DocumentPreview.qml
index ae037ddc9..1f3caf6b5 100644
--- a/src/app/mainview/components/DocumentPreview.qml
+++ b/src/app/mainview/components/DocumentPreview.qml
@@ -128,11 +128,11 @@ Item {
                         fillMode: Image.PreserveAspectCrop
 
                         source: {
-                            fileSource = "file://" + Body;
+                            fileSource = UtilsAdapter.urlFromLocalPath(Body);
                             if (!mediaInfo.isImage && !mediaInfo.isAnimatedImage) {
                                 return "";
                             }
-                            return "file://" + Body;
+                            return fileSource;
                         }
                     }
                 }
diff --git a/src/app/mainview/components/MessageListView.qml b/src/app/mainview/components/MessageListView.qml
index 4afa3d188..11961b2b4 100644
--- a/src/app/mainview/components/MessageListView.qml
+++ b/src/app/mainview/components/MessageListView.qml
@@ -147,7 +147,7 @@ JamiListView {
         id: overlay
         anchors.fill: parent
         color: JamiTheme.chatviewBgColor
-        visible: opacity !== 0
+        visible: opacity > 0
         SequentialAnimation {
             id: fadeAnimation
             NumberAnimation {
diff --git a/src/app/webengine/MediaPreviewBase.qml b/src/app/webengine/MediaPreviewBase.qml
index 7c4f8671f..39ac69086 100644
--- a/src/app/webengine/MediaPreviewBase.qml
+++ b/src/app/webengine/MediaPreviewBase.qml
@@ -41,7 +41,7 @@ WebEngineView {
     }
     settings.fullScreenSupportEnabled: isVideo
     settings.javascriptCanOpenWindows: false
-    Component.onCompleted: loadHtml(html, 'file://')
+    Component.onCompleted: loadHtml(html, 'file:///')
     layer.enabled: !isFullScreen
     layer.effect: OpacityMask {
         maskSource: MessageBubble {
diff --git a/src/app/webengine/VideoPreview.qml b/src/app/webengine/VideoPreview.qml
index 32c90c793..7c3dc0601 100644
--- a/src/app/webengine/VideoPreview.qml
+++ b/src/app/webengine/VideoPreview.qml
@@ -35,7 +35,7 @@ Rectangle {
         anchors.topMargin: root.isVideo ? 0 : wev.implicitHeight / 2
         settings.fullScreenSupportEnabled: root.isVideo
         settings.javascriptCanOpenWindows: false
-        Component.onCompleted: loadHtml(root.html, 'file://')
+        Component.onCompleted: loadHtml(root.html, 'file:///')
         onFullScreenRequested: function (request) {
             if (request.toggleOn) {
                 layoutManager.pushFullScreenItem(this, root, null, function () {
diff --git a/src/libclient/api/interaction.h b/src/libclient/api/interaction.h
index f6e747432..8d73329f5 100644
--- a/src/libclient/api/interaction.h
+++ b/src/libclient/api/interaction.h
@@ -443,8 +443,10 @@ struct Info
     Info(const SwarmMessage& msg, const QString& accountUri)
     {
         MapStringString msgBody;
-        for (const auto& key : msg.body.keys()) {
-            msgBody.insert(key, msg.body.value(key));
+        for (auto it = msg.body.cbegin(); it != msg.body.cend(); ++it) {
+            const auto& key = it.key();
+            const auto& value = it.value();
+            msgBody.insert(key, value);
         }
         init(msgBody, accountUri);
         parentId = msg.linearizedParent;
diff --git a/src/libclient/conversationmodel.cpp b/src/libclient/conversationmodel.cpp
index 9b36e52a9..277804e4c 100644
--- a/src/libclient/conversationmodel.cpp
+++ b/src/libclient/conversationmodel.cpp
@@ -2381,7 +2381,8 @@ ConversationModelPimpl::slotMessageReceived(const QString& accountId,
         auto msg = interaction::Info(message, linked.owner.profileInfo.uri);
 
         if (msg.type == interaction::Type::CALL) {
-            msg.body = interaction::getCallInteractionString(msg.authorUri == linked.owner.profileInfo.uri,
+            msg.body = interaction::getCallInteractionString(msg.authorUri
+                                                                 == linked.owner.profileInfo.uri,
                                                              msg);
         } else if (msg.type == interaction::Type::DATA_TRANSFER) {
             // save data transfer interaction to db and assosiate daemon id with interaction id,
@@ -2851,7 +2852,7 @@ ConversationModelPimpl::addConversationRequest(const MapStringString& convReques
 void
 ConversationModelPimpl::slotPendingContactAccepted(const QString& uri)
 {
-    profile::Type type;
+    profile::Type type {};
     try {
         type = linked.owner.contactModel->getContact(uri).profileInfo.type;
     } catch (std::out_of_range& e) {
diff --git a/src/libclient/messagelistmodel.cpp b/src/libclient/messagelistmodel.cpp
index c6fc1802a..661e50a8b 100644
--- a/src/libclient/messagelistmodel.cpp
+++ b/src/libclient/messagelistmodel.cpp
@@ -20,7 +20,6 @@
 
 #include "api/accountmodel.h"
 #include "api/contactmodel.h"
-#include "api/conversationmodel.h"
 
 #include <QFileInfo>
 
@@ -186,7 +185,11 @@ MessageListModel::update(const QString& id, const interaction::Info& interaction
             return true;
         }
     }
-    // Just update bodies notify the view.
+    // DataTransfer interactions should not be updated.
+    if (current.type == interaction::Type::DATA_TRANSFER) {
+        return true;
+    }
+    // Just update bodies notify the view otherwise.
     current.body = interaction.body;
     current.previousBodies = interaction.previousBodies;
     current.parsedBody = interaction.parsedBody;
-- 
GitLab