From 7a34209583e863e083b9051d3e6a30c09ccb5517 Mon Sep 17 00:00:00 2001 From: Nicolas Vengeon <nicolas.vengeon@savoirfairelinux.com> Date: Thu, 13 Oct 2022 14:41:28 -0400 Subject: [PATCH] feature: documents flow in the swarmDetailsPanel Change-Id: I24a94b9ced0ec3930a0b9e20f3fa0440e2d8fd00 Signed-off-by: Nicolas Vengeon <nicolas.vengeon@savoirfairelinux.com> --- src/app/constant/JamiTheme.qml | 7 +- .../components/DocumentsScrollview.qml | 84 +++++++ src/app/mainview/components/FilePreview.qml | 113 ++++++++++ src/app/mainview/components/MediaPreview.qml | 205 ++++++++++++++++++ .../mainview/components/SwarmDetailsPanel.qml | 18 +- src/app/messagesadapter.cpp | 49 +++++ src/app/messagesadapter.h | 7 + src/app/qml.qrc | 3 + src/libclient/api/conversationmodel.h | 15 ++ src/libclient/callbackshandler.cpp | 14 +- src/libclient/callbackshandler.h | 8 + src/libclient/conversationmodel.cpp | 59 +++++ .../qtwrapper/configurationmanager_wrap.h | 34 +++ 13 files changed, 610 insertions(+), 6 deletions(-) create mode 100644 src/app/mainview/components/DocumentsScrollview.qml create mode 100644 src/app/mainview/components/FilePreview.qml create mode 100644 src/app/mainview/components/MediaPreview.qml diff --git a/src/app/constant/JamiTheme.qml b/src/app/constant/JamiTheme.qml index 7712b000f..421367575 100644 --- a/src/app/constant/JamiTheme.qml +++ b/src/app/constant/JamiTheme.qml @@ -311,7 +311,6 @@ Item { property real preferredFieldHeight: 32 property real preferredMarginSize: 16 property real settingsMarginSize: 8 - property real swarmDetailsPageTopMargin: 32 property real preferredDialogWidth: 400 property real preferredDialogHeight: 300 property real minimumPreviewWidth: 120 @@ -337,6 +336,12 @@ Item { property real timestampFont: calcSize(12) property int timestampIntervalTime: 120 + //swarmDetailsPage + property real swarmDetailsPageTopMargin: 32 + property real swarmDetailsPageDocumentsMargins: 5 + property real swarmDetailsPageDocumentsMediaRadius: 15 + property real swarmDetailsPageDocumentsPaperClipSize: 24 + property real swarmDetailsPageDocumentsMediaSize: 175 // Jami switch property real switchIndicatorRadius: 30 diff --git a/src/app/mainview/components/DocumentsScrollview.qml b/src/app/mainview/components/DocumentsScrollview.qml new file mode 100644 index 000000000..df516961d --- /dev/null +++ b/src/app/mainview/components/DocumentsScrollview.qml @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2022 Savoir-faire Linux Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import Qt.labs.platform +import Qt5Compat.GraphicalEffects +import QtWebEngine + +import net.jami.Models 1.1 +import net.jami.Adapters 1.1 +import net.jami.Constants 1.1 + +import "../../commoncomponents" +import "../../settingsview/components" + +Flickable { + id: root + + contentHeight: flow.implicitHeight + contentWidth: width + + property int spacingFlow: JamiTheme.swarmDetailsPageDocumentsMargins + property int numberElementsPerRow: { + var sizeW = flow.width + var breakSize = JamiTheme.swarmDetailsPageDocumentsMediaSize + return Math.floor(sizeW / breakSize) + } + property int spacingLength: spacingFlow * (numberElementsPerRow - 1) + + onVisibleChanged: { + if (visible) { + MessagesAdapter.getConvMedias() + } else { + MessagesAdapter.mediaMessageListModel = null + } + } + Flow { + id: flow + + width: parent.width + spacing: spacingFlow + anchors.horizontalCenter: parent.horizontalCenter + + Repeater { + model: MessagesAdapter.mediaMessageListModel + + delegate: Loader { + id: loaderRoot + + sourceComponent: { + if(Status === Interaction.Status.TRANSFER_FINISHED || Status === Interaction.Status.SUCCESS ){ + if (Object.keys(MessagesAdapter.getMediaInfo(Body)).length !== 0 && WITH_WEBENGINE) + return localMediaMsgComp + + return fileMsgComp + } + } + + FilePreview { + id: fileMsgComp + } + MediaPreview { + id: localMediaMsgComp + } + } + } + } +} diff --git a/src/app/mainview/components/FilePreview.qml b/src/app/mainview/components/FilePreview.qml new file mode 100644 index 000000000..57b1ec8b7 --- /dev/null +++ b/src/app/mainview/components/FilePreview.qml @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2022 Savoir-faire Linux Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import Qt.labs.platform +import Qt5Compat.GraphicalEffects +import QtWebEngine + +import net.jami.Models 1.1 +import net.jami.Adapters 1.1 +import net.jami.Constants 1.1 + +import "../../commoncomponents" +import "../../settingsview/components" + +Component { + id: root + + Rectangle { + id: dataTransferRect + + clip: true + width: (documents.width - spacingLength ) / numberElementsPerRow + height: width + color: "transparent" + + ColumnLayout{ + anchors.fill: parent + anchors.margins: JamiTheme.swarmDetailsPageDocumentsMargins + + Text { + id: myText + + text: TransferName + color: JamiTheme.textColor + elide: Text.ElideRight + Layout.fillWidth: true + horizontalAlignment: Text.AlignHCenter + } + Rectangle { + Layout.preferredHeight: parent.height - myText.height - JamiTheme.swarmDetailsPageDocumentsMargins + Layout.preferredWidth: parent.width + Layout.rightMargin: JamiTheme.swarmDetailsPageDocumentsMargins + Layout.bottomMargin: JamiTheme.swarmDetailsPageDocumentsMargins + color: "transparent" + + Rectangle { + id: rectContent + + anchors.fill: parent + anchors.margins: JamiTheme.swarmDetailsPageDocumentsMargins + color: "transparent" + border.color: CurrentConversation.color + border.width: 2 + radius: JamiTheme.swarmDetailsPageDocumentsMediaRadius + layer.enabled: true + + ResponsiveImage { + id: paperClipImage + + source: JamiResources.link_black_24dp_svg + width: parent.width / 2 + height: parent.height / 2 + anchors.centerIn: parent + color: JamiTheme.textColor + + MouseArea { + anchors.fill: parent + hoverEnabled: true + acceptedButtons: Qt.LeftButton | Qt.RightButton + onEntered: { + cursorShape = Qt.PointingHandCursor + } + + onClicked: function (mouse) { + if (mouse.button === Qt.RightButton) { + ctxMenu.x = mouse.x + ctxMenu.y = mouse.y + ctxMenu.openMenu() + } else { + Qt.openUrlExternally("file://" + Body) + } + } + } + SBSContextMenu { + id: ctxMenu + + msgId: Id + location: Body + transferId: Id + transferName: TransferName + } + } + } + } + } + } +} diff --git a/src/app/mainview/components/MediaPreview.qml b/src/app/mainview/components/MediaPreview.qml new file mode 100644 index 000000000..0c33bf3e4 --- /dev/null +++ b/src/app/mainview/components/MediaPreview.qml @@ -0,0 +1,205 @@ +/* + * Copyright (C) 2022 Savoir-faire Linux Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import Qt.labs.platform +import Qt5Compat.GraphicalEffects +import QtWebEngine + +import net.jami.Models 1.1 +import net.jami.Adapters 1.1 +import net.jami.Constants 1.1 + +import "../../commoncomponents" +import "../../settingsview/components" + +Component { + id: root + + Rectangle { + id: localMediaRect + + width: (documents.width - spacingLength) / numberElementsPerRow + height: width + color: "transparent" + + ColumnLayout { + anchors.fill: parent + anchors.margins: JamiTheme.swarmDetailsPageDocumentsMargins + + Text { + id: mediaName + + text: TransferName + color: JamiTheme.textColor + elide: Text.ElideRight + Layout.fillWidth: true + horizontalAlignment: Text.AlignHCenter + } + Rectangle { + Layout.preferredHeight: parent.height - mediaName.height - JamiTheme.swarmDetailsPageDocumentsMargins + Layout.preferredWidth: parent.width + Layout.rightMargin: JamiTheme.swarmDetailsPageDocumentsMargins + Layout.bottomMargin: JamiTheme.swarmDetailsPageDocumentsMargins + color: "transparent" + + Rectangle { + id: rectContent + + anchors.fill: parent + anchors.margins: JamiTheme.swarmDetailsPageDocumentsMargins + color: CurrentConversation.color + layer.enabled: true + layer.effect: OpacityMask { + maskSource: Item { + width: localMediaCompLoader.width + height: localMediaCompLoader.height + Rectangle { + anchors.centerIn: parent + width: localMediaCompLoader.width + height: localMediaCompLoader.height + radius: JamiTheme.swarmDetailsPageDocumentsMediaRadius + } + } + } + + Loader { + id: localMediaCompLoader + + property var mediaInfo: MessagesAdapter.getMediaInfo(Body) + anchors.fill: parent + anchors.margins: 2 + sourceComponent: { + if (mediaInfo.isImage || mediaInfo.isAnimatedImage ) + return imageMediaComp + else if (WITH_WEBENGINE) + return avMediaComp + } + Component { + id: avMediaComp + + Loader { + property real msgRadius: 20 + + Rectangle { + id: videoAudioRect + color: JamiTheme.secondaryBackgroundColor + anchors.fill: parent + + WebEngineView { + id: wev + + property bool isVideo: mediaInfo.isVideo + property string html: mediaInfo.html + + anchors.fill: parent + anchors.verticalCenter: videoAudioRect.verticalCenter + backgroundColor: JamiTheme.secondaryBackgroundColor + anchors.topMargin: isVideo? 0 : wev.implicitHeight / 2 + settings.fullScreenSupportEnabled: isVideo + settings.javascriptCanOpenWindows: false + Component.onCompleted: loadHtml(html, 'file://') + onFullScreenRequested: function(request) { + if (request.toggleOn) { + layoutManager.pushFullScreenItem( + this, + videoAudioRect, + null, + function() { wev.fullScreenCancelled() }) + } else if (!request.toggleOn) { + layoutManager.removeFullScreenItem(this) + } + request.accept() + } + } + + layer.enabled: true + layer.effect: OpacityMask { + maskSource: Item { + width: videoAudioRect.width + height: videoAudioRect.height + Rectangle { + anchors.centerIn: parent + width: videoAudioRect.width + height: videoAudioRect.height + radius: JamiTheme.swarmDetailsPageDocumentsMediaRadius + } + } + } + } + } + } + + Component { + id: imageMediaComp + + Image { + id: fileImage + + anchors.fill: parent + fillMode: Image.PreserveAspectCrop + source: "file://" + Body + layer.enabled: true + layer.effect: OpacityMask { + maskSource: Item { + width: fileImage.width + height: fileImage.height + Rectangle { + anchors.centerIn: parent + width: fileImage.width + height: fileImage.height + radius: JamiTheme.swarmDetailsPageDocumentsMediaRadius + } + } + } + MouseArea { + anchors.fill: parent + hoverEnabled: true + acceptedButtons: Qt.LeftButton | Qt.RightButton + + onEntered: { + cursorShape = Qt.PointingHandCursor + } + + onClicked: function(mouse) { + if (mouse.button === Qt.RightButton) { + ctxMenu.x = mouse.x + ctxMenu.y = mouse.y + ctxMenu.openMenu() + } else { + MessagesAdapter.openUrl(fileImage.source) + } + } + } + + SBSContextMenu { + id: ctxMenu + + msgId: Id + location: Body + transferId: Id + transferName: TransferName + } + } + } + } + } + } + } + } +} diff --git a/src/app/mainview/components/SwarmDetailsPanel.qml b/src/app/mainview/components/SwarmDetailsPanel.qml index 049a3cda4..0dd93bc29 100644 --- a/src/app/mainview/components/SwarmDetailsPanel.qml +++ b/src/app/mainview/components/SwarmDetailsPanel.qml @@ -20,6 +20,8 @@ import QtQuick import QtQuick.Controls import QtQuick.Layouts import Qt.labs.platform +import Qt5Compat.GraphicalEffects +import QtWebEngine import net.jami.Models 1.1 import net.jami.Adapters 1.1 @@ -205,7 +207,7 @@ Rectangle { } } - /*FilterTabButton { + FilterTabButton { id: documentsTabButton backgroundColor: CurrentConversation.color hoverColor: CurrentConversation.color @@ -216,12 +218,12 @@ Rectangle { textColorHovered: UtilsAdapter.luma(root.color) ? JamiTheme.placeholderTextColorWhite : JamiTheme.placeholderTextColor textColor: UtilsAdapter.luma(root.color) ? - JamiTheme.chatviewTextColorLight : - JamiTheme.chatviewTextColorDark + JamiTheme.chatviewTextColorLight : + JamiTheme.chatviewTextColorDark down: tabBar.currentIndex === 2 labelText: JamiStrings.documents - }*/ + } } } @@ -523,6 +525,14 @@ Rectangle { } } } + + DocumentsScrollview { + id: documents + + clip: true + visible: tabBar.currentIndex === 2 + anchors.fill: parent + } } } } diff --git a/src/app/messagesadapter.cpp b/src/app/messagesadapter.cpp index 3d9f70ba6..5f8c0ae99 100644 --- a/src/app/messagesadapter.cpp +++ b/src/app/messagesadapter.cpp @@ -49,6 +49,7 @@ MessagesAdapter::MessagesAdapter(AppSettingsManager* settingsManager, : QmlAdapterBase(instance, parent) , settingsManager_(settingsManager) , previewEngine_(previewEngine) + , mediaInteractions_(std::make_unique<MessageListModel>()) { connect(lrcInstance_, &LRCInstance::selectedConvUidChanged, [this]() { set_replyToId(""); @@ -136,6 +137,12 @@ MessagesAdapter::connectConversationModel() this, &MessagesAdapter::onComposingStatusChanged, Qt::UniqueConnection); + + QObject::connect(currentConversationModel, + &ConversationModel::messagesFoundProcessed, + this, + &MessagesAdapter::onMessagesFoundProcessed, + Qt::UniqueConnection); } void @@ -517,6 +524,33 @@ MessagesAdapter::onComposingStatusChanged(const QString& convId, } } +void +MessagesAdapter::onMessagesFoundProcessed(const QString& accountId, + const VectorMapStringString& messageIds, + const QVector<interaction::Info>& messageInformations) +{ + if (lrcInstance_->get_currentAccountId() != accountId) { + return; + } + bool isSearchInProgress = messageIds.length(); + if (isSearchInProgress) { + int index = -1; + Q_FOREACH (const MapStringString& msg, messageIds) { + index++; + try { + std::pair<QString, interaction::Info> message(msg["id"], + messageInformations.at(index)); + mediaInteractions_->insert(message); + } catch (...) { + qWarning() << "error in onMessagesFoundProcessed, message insertion on index: " + << index; + } + } + } else { + set_mediaMessageListModel(QVariant::fromValue(mediaInteractions_.get())); + } +} + QList<QString> MessagesAdapter::conversationTypersUrlToName(const QSet<QString>& typersSet) { @@ -637,3 +671,18 @@ MessagesAdapter::getFormattedDay(const quint64 timestamp) return dateLocale; } + +void +MessagesAdapter::getConvMedias() +{ + auto accountId = lrcInstance_->get_currentAccountId(); + auto convId = lrcInstance_->get_selectedConvUid(); + + mediaInteractions_.reset(new MessageListModel(this)); + + try { + lrcInstance_->getCurrentConversationModel()->getConvMediasInfos(accountId, convId); + } catch (...) { + qDebug() << "Exception during getConvMedia:"; + } +} diff --git a/src/app/messagesadapter.h b/src/app/messagesadapter.h index b059fc8e6..446f8b61e 100644 --- a/src/app/messagesadapter.h +++ b/src/app/messagesadapter.h @@ -34,6 +34,7 @@ class MessagesAdapter final : public QmlAdapterBase QML_PROPERTY(QString, replyToId) QML_PROPERTY(QString, editId) QML_RO_PROPERTY(QList<QString>, currentConvComposingList) + QML_PROPERTY(QVariant, mediaMessageListModel) public: explicit MessagesAdapter(AppSettingsManager* settingsManager, @@ -94,6 +95,7 @@ protected: Q_INVOKABLE QVariantMap getTransferStats(const QString& messageId, int); Q_INVOKABLE QVariant dataForInteraction(const QString& interactionId, int role = Qt::DisplayRole) const; + Q_INVOKABLE void getConvMedias(); // Run corrsponding js functions, c++ to qml. void setMessagesImageContent(const QString& path, bool isBased64 = false); @@ -110,6 +112,9 @@ private Q_SLOTS: void onComposingStatusChanged(const QString& convId, const QString& contactUri, bool isComposing); + void onMessagesFoundProcessed(const QString& accountId, + const VectorMapStringString& messageIds, + const QVector<interaction::Info>& messageInformations); private: QList<QString> conversationTypersUrlToName(const QSet<QString>& typersSet); @@ -118,4 +123,6 @@ private: PreviewEngine* previewEngine_; static constexpr const int loadChunkSize_ {20}; + + std::unique_ptr<MessageListModel> mediaInteractions_; }; diff --git a/src/app/qml.qrc b/src/app/qml.qrc index 3560ee0bb..8f558284d 100644 --- a/src/app/qml.qrc +++ b/src/app/qml.qrc @@ -209,5 +209,8 @@ <file>commoncomponents/MaterialTextField.qml</file> <file>commoncomponents/ModalTextEdit.qml</file> <file>commoncomponents/UsernameTextEdit.qml</file> + <file>mainview/components/DocumentsScrollview.qml</file> + <file>mainview/components/FilePreview.qml</file> + <file>mainview/components/MediaPreview.qml</file> </qresource> </RCC> diff --git a/src/libclient/api/conversationmodel.h b/src/libclient/api/conversationmodel.h index d0871caac..13e158431 100644 --- a/src/libclient/api/conversationmodel.h +++ b/src/libclient/api/conversationmodel.h @@ -302,6 +302,11 @@ public: void getTransferInfo(const QString& conversationId, const QString& interactionId, api::datatransfer::Info& info) const; + + /** + * Starts a search of all medias and files in a conversation + */ + void getConvMediasInfos(const QString& accountId, const QString& conversationId); /** * @param convUid, uid of the conversation * @return the number of unread messages for the conversation @@ -584,6 +589,16 @@ Q_SIGNALS: */ void dataChanged(int position) const; + /** + * Emitted once a message search has been done and processed + * @param accountId + * @param messageIds ids of all the messages found by the search + * @param messageInformations message datas + */ + void messagesFoundProcessed(const QString& accountId, + const VectorMapStringString& messageIds, + const QVector<interaction::Info>& messageInformations) const; + private: std::unique_ptr<ConversationModelPimpl> pimpl_; }; diff --git a/src/libclient/callbackshandler.cpp b/src/libclient/callbackshandler.cpp index 416842a2d..19e4a4b5b 100644 --- a/src/libclient/callbackshandler.cpp +++ b/src/libclient/callbackshandler.cpp @@ -294,7 +294,6 @@ CallbacksHandler::CallbacksHandler(const Lrc& parent) this, &CallbacksHandler::slotAudioDeviceEvent, Qt::QueuedConnection); - connect(&ConfigurationManager::instance(), &ConfigurationManagerInterface::audioMeter, this, @@ -305,6 +304,11 @@ CallbacksHandler::CallbacksHandler(const Lrc& parent) this, &CallbacksHandler::slotConversationLoaded, Qt::QueuedConnection); + connect(&ConfigurationManager::instance(), + &ConfigurationManagerInterface::messagesFound, + this, + &CallbacksHandler::slotMessagesFound, + Qt::QueuedConnection); connect(&ConfigurationManager::instance(), &ConfigurationManagerInterface::messageReceived, this, @@ -749,6 +753,14 @@ CallbacksHandler::slotConversationLoaded(uint32_t requestId, { Q_EMIT conversationLoaded(requestId, accountId, conversationId, messages); } +void +CallbacksHandler::slotMessagesFound(uint32_t requestId, + const QString& accountId, + const QString& conversationId, + const VectorMapStringString& messages) +{ + Q_EMIT messagesFound(requestId, accountId, conversationId, messages); +} void CallbacksHandler::slotMessageReceived(const QString& accountId, diff --git a/src/libclient/callbackshandler.h b/src/libclient/callbackshandler.h index d14704231..4f3ad2711 100644 --- a/src/libclient/callbackshandler.h +++ b/src/libclient/callbackshandler.h @@ -350,6 +350,10 @@ Q_SIGNALS: const QString& accountId, const QString& conversationId, const VectorMapStringString& messages); + void messagesFound(uint32_t requestId, + const QString& accountId, + const QString& conversationId, + const VectorMapStringString& messages); void messageReceived(const QString& accountId, const QString& conversationId, const MapStringString& message); @@ -668,6 +672,10 @@ private Q_SLOTS: const QString& accountId, const QString& conversationId, const VectorMapStringString& messages); + void slotMessagesFound(uint32_t requestId, + const QString& accountId, + const QString& conversationId, + const VectorMapStringString& messages); void slotMessageReceived(const QString& accountId, const QString& conversationId, const MapStringString& message); diff --git a/src/libclient/conversationmodel.cpp b/src/libclient/conversationmodel.cpp index c904ad1df..5f1bb59b4 100644 --- a/src/libclient/conversationmodel.cpp +++ b/src/libclient/conversationmodel.cpp @@ -246,6 +246,7 @@ public: std::map<QString, std::mutex> interactionsLocks; ///< {convId, mutex} MapStringString transfIdToDbIntId; + uint32_t currentMsgRequestId; public Q_SLOTS: /** @@ -355,6 +356,18 @@ public Q_SLOTS: const QString& accountId, const QString& conversationId, const VectorMapStringString& messages); + /** + * Listen messageFound signal. + * Is the search response from MessagesAdapter::getConvMedias() + * @param requestId token of the request + * @param accountId + * @param conversationId + * @param messages Id of all the messages + */ + void slotMessagesFound(uint32_t requestId, + const QString& accountId, + const QString& conversationId, + const VectorMapStringString& messages); void slotMessageReceived(const QString& accountId, const QString& conversationId, const MapStringString& message); @@ -1865,6 +1878,10 @@ ConversationModelPimpl::ConversationModelPimpl(const ConversationModel& linked, &CallbacksHandler::conversationLoaded, this, &ConversationModelPimpl::slotConversationLoaded); + connect(&callbacksHandler, + &CallbacksHandler::messagesFound, + this, + &ConversationModelPimpl::slotMessagesFound); connect(&callbacksHandler, &CallbacksHandler::messageReceived, this, @@ -2013,6 +2030,10 @@ ConversationModelPimpl::~ConversationModelPimpl() &CallbacksHandler::conversationLoaded, this, &ConversationModelPimpl::slotConversationLoaded); + disconnect(&callbacksHandler, + &CallbacksHandler::messagesFound, + this, + &ConversationModelPimpl::slotMessagesFound); disconnect(&callbacksHandler, &CallbacksHandler::messageReceived, this, @@ -2420,6 +2441,37 @@ ConversationModelPimpl::slotConversationLoaded(uint32_t requestId, } } +void +ConversationModelPimpl::slotMessagesFound(uint32_t requestId, + const QString& accountId, + const QString& conversationId, + const VectorMapStringString& messageIds) +{ + if (requestId != currentMsgRequestId) { + return; + } + QVector<interaction::Info> messageDetailedinformations; + Q_FOREACH (const MapStringString& msg, messageIds) { + auto intInfo = interaction::Info(msg, ""); + if (intInfo.type == interaction::Type::DATA_TRANSFER) { + auto fileId = msg["fileId"]; + + QString path; + qlonglong bytesProgress, totalSize; + linked.owner.dataTransferModel->fileTransferInfo(accountId, + conversationId, + fileId, + path, + totalSize, + bytesProgress); + intInfo.body = path; + } + messageDetailedinformations.append(intInfo); + } + + Q_EMIT linked.messagesFoundProcessed(accountId, messageIds, messageDetailedinformations); +} + void ConversationModelPimpl::slotMessageReceived(const QString& accountId, const QString& conversationId, @@ -3786,6 +3838,13 @@ ConversationModel::sendFile(const QString& convUid, const QString& path, const Q } } +void +ConversationModel::getConvMediasInfos(const QString& accountId, const QString& conversationId) +{ + pimpl_->currentMsgRequestId = ConfigurationManager::instance().searchConversation( + accountId, conversationId, "", "", "", "application/data-transfer+json", 0, 0, 0); +}; + void ConversationModel::acceptTransfer(const QString& convUid, const QString& interactionId) { diff --git a/src/libclient/qtwrapper/configurationmanager_wrap.h b/src/libclient/qtwrapper/configurationmanager_wrap.h index ad7328bf0..b280cea69 100644 --- a/src/libclient/qtwrapper/configurationmanager_wrap.h +++ b/src/libclient/qtwrapper/configurationmanager_wrap.h @@ -280,6 +280,16 @@ public: QString(conversationId.c_str()), convertVecMap(messages)); }), + exportable_callback<ConversationSignal::MessagesFound>( + [this](uint32_t id, + const std::string& accountId, + const std::string& conversationId, + const std::vector<std::map<std::string, std::string>>& messages) { + Q_EMIT messagesFound(id, + QString(accountId.c_str()), + QString(conversationId.c_str()), + convertVecMap(messages)); + }), exportable_callback<ConversationSignal::MessageReceived>( [this](const std::string& accountId, const std::string& conversationId, @@ -1151,6 +1161,26 @@ public Q_SLOTS: // METHODS fromId.toStdString(), authorUri.toStdString()); } + uint32_t searchConversation(const QString& accountId, + const QString& conversationId, + const QString& author, + const QString& lastId, + const QString& regexSearch, + const QString& type, + const int64_t& after, + const int64_t& before, + const uint32_t& maxResult) + { + return DRing::searchConversation(accountId.toStdString(), + conversationId.toStdString(), + author.toStdString(), + lastId.toStdString(), + regexSearch.toStdString(), + type.toStdString(), + after, + before, + maxResult); + } Q_SIGNALS: // SIGNALS void volumeChanged(const QString& device, double value); void accountsChanged(); @@ -1224,6 +1254,10 @@ Q_SIGNALS: // SIGNALS void messageReceived(const QString& accountId, const QString& conversationId, const MapStringString& message); + void messagesFound(uint32_t requestId, + const QString& accountId, + const QString& conversationId, + const VectorMapStringString& messages); void conversationProfileUpdated(const QString& accountId, const QString& conversationId, const MapStringString& profile); -- GitLab