diff --git a/src/libclient/CMakeLists.txt b/src/libclient/CMakeLists.txt index b1ca5784a452732ff1409dd080f174eb14ebaed9..233cfd3e0f5510ef12275f7abd369253a6f78e68 100644 --- a/src/libclient/CMakeLists.txt +++ b/src/libclient/CMakeLists.txt @@ -275,6 +275,7 @@ set(LIBCLIENT_SOURCES # other avmodel.cpp pluginmodel.cpp + interaction.cpp namedirectory.cpp renderer.cpp) diff --git a/src/libclient/api/interaction.h b/src/libclient/api/interaction.h index 5c184305ee52941af5bd4f7c4c3011a48381bfc7..87b5535ff55d097708ad671d1c02268b4e579c51 100644 --- a/src/libclient/api/interaction.h +++ b/src/libclient/api/interaction.h @@ -24,7 +24,6 @@ #include <ctime> #include "typedefs.h" -#include "../dbus/configurationmanager.h" namespace lrc { @@ -426,85 +425,21 @@ struct Info Type type, Status status, bool isRead, - TransferStatus transferStatus = TransferStatus::INVALID) - { - this->authorUri = authorUri; - this->body = body; - this->timestamp = timestamp; - this->duration = duration; - this->type = type; - this->status = status; - this->isRead = isRead; - this->transferStatus = transferStatus; - } + TransferStatus transferStatus = TransferStatus::INVALID); - static Info contact(const QString& authorUri, - std::time_t timestamp) - { - return Info(authorUri, "", timestamp, 0, - Type::CONTACT, authorUri.isEmpty() ? Status::UNKNOWN : Status::SUCCESS, - authorUri.isEmpty()); - } + static Info contact(const QString& authorUri, std::time_t timestamp); Info(const Info& other) = default; Info(Info&& other) = default; Info& operator=(const Info& other) = delete; Info& operator=(Info&& other) = default; - bool sent() const - { - return status == Status::SUCCESS || status == Status::DISPLAYED; - } + bool sent() const; void init(const MapStringString& message, const QString& accountURI, const QString& accountId, - const QString& conversationId) - { - type = to_type(message["type"]); - if (message.contains("react-to") && type == Type::TEXT) { - type = to_type("REACTION"); - react_to = message["react-to"]; - } - authorUri = message["author"]; - - if (type == Type::TEXT) { - body = message["body"]; - } - timestamp = message["timestamp"].toInt(); - status = Status::SUCCESS; - parentId = message["linearizedParent"]; - isRead = false; - if (type == Type::CONTACT) { - authorUri = accountURI == message["uri"] ? "" : message["uri"]; - } else if (type == Type::INITIAL) { - if (message["mode"] == "0") { - body = QObject::tr("Private conversation created"); - } else { - body = QObject::tr("Swarm created"); - } - } else if (type == Type::CALL) { - duration = message["duration"].toInt() / 1000; - if (message.contains("confId")) - confId = message["confId"]; - } else if (type == Type::DATA_TRANSFER) { - QString path; - qlonglong bytesProgress, totalSize; - ConfigurationManager::instance().fileTransferInfo(accountId, - conversationId, - message["fileId"], - path, - totalSize, - bytesProgress); - QFileInfo fi(path); - body = fi.isSymLink() ? fi.symLinkTarget() : path; - transferStatus = bytesProgress == 0 ? TransferStatus::TRANSFER_AWAITING_HOST - : bytesProgress == totalSize ? TransferStatus::TRANSFER_FINISHED - : TransferStatus::TRANSFER_ONGOING; - - } - commit = message; - } + const QString& conversationId); // NOTE: The `accountId` and `conversationId` arguments are only used for messages of // type DATA_TRANSFER. They can therefore be omitted if the caller knows that `message` @@ -514,58 +449,12 @@ struct Info Info(const MapStringString& message, const QString& accountURI, const QString& accountId = "", - const QString& conversationId = "") - { - init(message, accountURI, accountId, conversationId); - } + const QString& conversationId = ""); Info(const SwarmMessage& msg, const QString& accountUri, const QString& accountId, - const QString& conversationId) - { - MapStringString msgBody; - 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, accountId, conversationId); - parentId = msg.linearizedParent; - type = to_type(msg.type); - for (const auto& edition : msg.editions) - previousBodies.append(Body {edition.value("id"), - edition.value("body"), - QString(edition.value("timestamp")).toInt()}); - QMap<QString, QVariantList> mapStringEmoji; - for (const auto& reaction : msg.reactions) { - auto author = reaction.value("author"); - auto body = reaction.value("body"); - auto emoji = Emoji {reaction.value("id"), body}; - QVariant variant = QVariant::fromValue(emoji); - mapStringEmoji[author].append(variant); - } - for (auto i = mapStringEmoji.begin(); i != mapStringEmoji.end(); i++) - reactions.insert(i.key(), i.value()); - // Compute the status of the message. - // Basically, we got the status per member. - // We consider the message as sent if at least one member has received it or displayed if - // someone displayed it. - auto maxStatus = 0; - status = Status::SENDING; - for (const auto& member : msg.status.keys()) { - if (member == accountUri) - continue; - auto stValue = msg.status.value(member); - if (stValue > maxStatus) { - maxStatus = stValue; - status = maxStatus <= 1 ? Status::SENDING - : (stValue == 2 ? Status::SUCCESS : Status::DISPLAYED); - } - if (maxStatus == 3) - break; - } - } + const QString& conversationId); }; static inline bool diff --git a/src/libclient/interaction.cpp b/src/libclient/interaction.cpp new file mode 100644 index 0000000000000000000000000000000000000000..81bb6148945d984ab88c6c50ee185e549e8fbe07 --- /dev/null +++ b/src/libclient/interaction.cpp @@ -0,0 +1,172 @@ +/**************************************************************************** + * Copyright (C) 2024 Savoir-faire Linux Inc. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library 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 * + * Lesser 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 <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#include "api/interaction.h" +#include "dbus/configurationmanager.h" + +namespace lrc { + +namespace api { + +namespace interaction { + +Info::Info(QString authorUri, + QString body, + std::time_t timestamp, + std::time_t duration, + Type type, + Status status, + bool isRead, + TransferStatus transferStatus) +{ + this->authorUri = authorUri; + this->body = body; + this->timestamp = timestamp; + this->duration = duration; + this->type = type; + this->status = status; + this->isRead = isRead; + this->transferStatus = transferStatus; +} + +Info +Info::contact(const QString& authorUri, std::time_t timestamp) +{ + return Info(authorUri, + "", + timestamp, + 0, + Type::CONTACT, + authorUri.isEmpty() ? Status::UNKNOWN : Status::SUCCESS, + authorUri.isEmpty()); +} + +bool +Info::sent() const +{ + return status == Status::SUCCESS || status == Status::DISPLAYED; +} + +void +Info::init(const MapStringString& message, + const QString& accountURI, + const QString& accountId, + const QString& conversationId) +{ + type = to_type(message["type"]); + if (message.contains("react-to") && type == Type::TEXT) { + type = to_type("REACTION"); + react_to = message["react-to"]; + } + authorUri = message["author"]; + + if (type == Type::TEXT) { + body = message["body"]; + } + timestamp = message["timestamp"].toInt(); + status = Status::SUCCESS; + parentId = message["linearizedParent"]; + isRead = false; + if (type == Type::CONTACT) { + authorUri = accountURI == message["uri"] ? "" : message["uri"]; + } else if (type == Type::INITIAL) { + if (message["mode"] == "0") { + body = QObject::tr("Private conversation created"); + } else { + body = QObject::tr("Swarm created"); + } + } else if (type == Type::CALL) { + duration = message["duration"].toInt() / 1000; + if (message.contains("confId")) + confId = message["confId"]; + } else if (type == Type::DATA_TRANSFER) { + QString path; + qlonglong bytesProgress, totalSize; + ConfigurationManager::instance().fileTransferInfo(accountId, + conversationId, + message["fileId"], + path, + totalSize, + bytesProgress); + QFileInfo fi(path); + body = fi.isSymLink() ? fi.symLinkTarget() : path; + transferStatus = bytesProgress == 0 ? TransferStatus::TRANSFER_AWAITING_HOST + : bytesProgress == totalSize ? TransferStatus::TRANSFER_FINISHED + : TransferStatus::TRANSFER_ONGOING; + } + commit = message; +} + +Info::Info(const MapStringString& message, + const QString& accountURI, + const QString& accountId, + const QString& conversationId) +{ + init(message, accountURI, accountId, conversationId); +} + +Info::Info(const SwarmMessage& msg, + const QString& accountUri, + const QString& accountId, + const QString& conversationId) +{ + MapStringString msgBody; + 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, accountId, conversationId); + parentId = msg.linearizedParent; + type = to_type(msg.type); + for (const auto& edition : msg.editions) + previousBodies.append(Body {edition.value("id"), + edition.value("body"), + QString(edition.value("timestamp")).toInt()}); + QMap<QString, QVariantList> mapStringEmoji; + for (const auto& reaction : msg.reactions) { + auto author = reaction.value("author"); + auto body = reaction.value("body"); + auto emoji = Emoji {reaction.value("id"), body}; + QVariant variant = QVariant::fromValue(emoji); + mapStringEmoji[author].append(variant); + } + for (auto i = mapStringEmoji.begin(); i != mapStringEmoji.end(); i++) + reactions.insert(i.key(), i.value()); + // Compute the status of the message. + // Basically, we got the status per member. + // We consider the message as sent if at least one member has received it or displayed if + // someone displayed it. + auto maxStatus = 0; + status = Status::SENDING; + for (const auto& member : msg.status.keys()) { + if (member == accountUri) + continue; + auto stValue = msg.status.value(member); + if (stValue > maxStatus) { + maxStatus = stValue; + status = maxStatus <= 1 ? Status::SENDING + : (stValue == 2 ? Status::SUCCESS : Status::DISPLAYED); + } + if (maxStatus == 3) + break; + } +} + +} // namespace interaction +} // namespace api +} // namespace lrc \ No newline at end of file