diff --git a/src/app/calladapter.cpp b/src/app/calladapter.cpp index 7de173e45038b28cd776322986a4c3d0669cca81..3bc658ff2bc2361ede1c07eae3888ce65b9ab5ee 100644 --- a/src/app/calladapter.cpp +++ b/src/app/calladapter.cpp @@ -572,6 +572,11 @@ CallAdapter::showNotification(const QString& accountId, const QString& convUid) auto& accInfo = lrcInstance_->getAccountInfo(accountId); auto title = accInfo.conversationModel->title(convUid); + auto preferences = accInfo.conversationModel->getConversationPreferences(convUid); + // Ignore notifications for this conversation + if (preferences["ignoreNotifications"] == "true") + return; + #ifdef Q_OS_LINUX auto convAvatar = Utils::conversationAvatar(lrcInstance_, convUid, QSize(50, 50), accountId); auto notifId = QString("%1;%2").arg(accountId).arg(convUid); diff --git a/src/app/conversationsadapter.cpp b/src/app/conversationsadapter.cpp index 02fa2368de52636e545808ba6137d05fb5c1e6df..6f973726f2142027d6861a0875ad8471aae1e60d 100644 --- a/src/app/conversationsadapter.cpp +++ b/src/app/conversationsadapter.cpp @@ -168,6 +168,11 @@ ConversationsAdapter::onNewUnreadInteraction(const QString& accountId, || convUid != lrcInstance_->get_selectedConvUid())) { auto& accountInfo = lrcInstance_->getAccountInfo(accountId); auto from = accountInfo.contactModel->bestNameForContact(interaction.authorUri); + + auto preferences = accountInfo.conversationModel->getConversationPreferences(convUid); + // Ignore notifications for this conversation + if (preferences["ignoreNotifications"] == "true") + return; #ifdef Q_OS_LINUX auto contactPhoto = Utils::contactPhoto(lrcInstance_, interaction.authorUri, @@ -226,6 +231,11 @@ ConversationsAdapter::onNewTrustRequest(const QString& accountId, } auto& accInfo = lrcInstance_->getAccountInfo(accountId); auto from = accInfo.contactModel->bestNameForContact(peerUri); + + auto preferences = accInfo.conversationModel->getConversationPreferences(convId); + // Ignore notifications for this conversation + if (preferences["ignoreNotifications"] == "true") + return; auto contactPhoto = Utils::contactPhoto(lrcInstance_, peerUri, QSize(50, 50), accountId); auto notifId = QString("%1;%2").arg(accountId).arg(conv); systemTray_->showNotification(notifId, diff --git a/src/app/currentconversation.cpp b/src/app/currentconversation.cpp index 42c9a9fccb2a525f958533e3fec8dccb555b8aba..5852570e0abac9f71281bfda8d50d22a194643af 100644 --- a/src/app/currentconversation.cpp +++ b/src/app/currentconversation.cpp @@ -17,6 +17,9 @@ */ #include "currentconversation.h" +#include "qmlregister.h" + +#include <api/conversationmodel.h> CurrentConversation::CurrentConversation(LRCInstance* lrcInstance, QObject* parent) : QObject(parent) @@ -58,7 +61,7 @@ CurrentConversation::updateData() set_isCoreDialog(convInfo.isCoreDialog()); set_isRequest(convInfo.isRequest); set_needsSyncing(convInfo.needsSyncing); - set_color(Utils::getAvatarColor(convId).name()); + updateConversationPreferences(convId); set_isSip(accInfo.profileInfo.type == profile::Type::SIP); set_callId(convInfo.getCallId()); set_allMessagesLoaded(convInfo.allMessagesLoaded); @@ -107,6 +110,33 @@ CurrentConversation::updateData() updateErrors(convId); } +void +CurrentConversation::setPreference(const QString& key, const QString& value) +{ + auto accountId = lrcInstance_->get_currentAccountId(); + const auto& accInfo = lrcInstance_->accountModel().getAccountInfo(accountId); + auto convId = lrcInstance_->get_selectedConvUid(); + if (auto optConv = accInfo.conversationModel->getConversationForUid(convId)) { + auto& convInfo = optConv->get(); + auto preferences = convInfo.preferences; + preferences[key] = value; + accInfo.conversationModel->setConversationPreferences(convId, preferences); + } +} + +QString +CurrentConversation::getPreference(const QString& key) const +{ + auto accountId = lrcInstance_->get_currentAccountId(); + const auto& accInfo = lrcInstance_->accountModel().getAccountInfo(accountId); + auto convId = lrcInstance_->get_selectedConvUid(); + if (auto optConv = accInfo.conversationModel->getConversationForUid(convId)) { + auto& convInfo = optConv->get(); + return convInfo.preferences[key]; + } + return {}; +} + void CurrentConversation::onConversationUpdated(const QString& convId) { @@ -126,6 +156,27 @@ CurrentConversation::onProfileUpdated(const QString& convId) set_description(lrcInstance_->getCurrentConversationModel()->description(convId)); } +void +CurrentConversation::updateConversationPreferences(const QString& convId) +{ + if (convId != lrcInstance_->get_selectedConvUid()) + return; + auto accountId = lrcInstance_->get_currentAccountId(); + const auto& accInfo = lrcInstance_->accountModel().getAccountInfo(accountId); + if (auto optConv = accInfo.conversationModel->getConversationForUid(convId)) { + auto& convInfo = optConv->get(); + auto preferences = convInfo.preferences; + auto color = Utils::getAvatarColor(convId).name(); + if (convInfo.preferences.contains("color")) { + color = convInfo.preferences["color"]; + } + set_color(color); + if (convInfo.preferences.contains("ignoreNotifications")) { + set_ignoreNotifications(convInfo.preferences["ignoreNotifications"] == "true"); + } + } +} + void CurrentConversation::connectModel() { @@ -148,6 +199,11 @@ CurrentConversation::connectModel() this, &CurrentConversation::updateErrors, Qt::UniqueConnection); + connect(lrcInstance_->getCurrentConversationModel(), + &ConversationModel::conversationPreferencesUpdated, + this, + &CurrentConversation::updateConversationPreferences, + Qt::UniqueConnection); } void diff --git a/src/app/currentconversation.h b/src/app/currentconversation.h index 37259baa4e56e12a75210e5f2478fc73f377f70c..01fd610277e7cd8ecea1229ef29115fb150f5d88 100644 --- a/src/app/currentconversation.h +++ b/src/app/currentconversation.h @@ -40,6 +40,7 @@ class CurrentConversation final : public QObject QML_PROPERTY(bool, needsSyncing) QML_PROPERTY(bool, isSip) QML_PROPERTY(bool, isBanned) + QML_PROPERTY(bool, ignoreNotifications) QML_PROPERTY(QString, callId) QML_PROPERTY(QString, color) QML_PROPERTY(call::Status, callState) @@ -60,6 +61,8 @@ public: ~CurrentConversation() = default; Q_INVOKABLE void scrollToMsg(const QString& msgId); Q_INVOKABLE void showSwarmDetails() const; + Q_INVOKABLE void setPreference(const QString& key, const QString& value); + Q_INVOKABLE QString getPreference(const QString& key) const; Q_SIGNALS: void scrollTo(const QString& msgId); @@ -70,6 +73,7 @@ private Q_SLOTS: void onConversationUpdated(const QString& convId); void onProfileUpdated(const QString& convId); void updateErrors(const QString& convId); + void updateConversationPreferences(const QString& convId); private: LRCInstance* lrcInstance_; diff --git a/src/app/mainview/components/SwarmDetailsPanel.qml b/src/app/mainview/components/SwarmDetailsPanel.qml index 03f023fe786b18c3fcb23cb41d272d80cbee69a7..ca0e65834c5e5b4b4f100b5839768ac803f38bb9 100644 --- a/src/app/mainview/components/SwarmDetailsPanel.qml +++ b/src/app/mainview/components/SwarmDetailsPanel.qml @@ -229,8 +229,7 @@ Rectangle { id: colorDialog title: JamiStrings.chooseAColor onAccepted: { - console.warn("TODO SAVE preference") - CurrentConversation.color = colorDialog.color + CurrentConversation.setPreference("color", colorDialog.color) } } @@ -258,7 +257,7 @@ Rectangle { anchors.fill: parent anchors.leftMargin: JamiTheme.preferredMarginSize - checked: false // TODO + checked: CurrentConversation.ignoreNotifications labelText: JamiStrings.ignoreTheSwarm fontPointSize: JamiTheme.settingsFontSize @@ -266,7 +265,7 @@ Rectangle { tooltipText: JamiStrings.ignoreTheSwarmTooltip onSwitchToggled: { - // TODO + CurrentConversation.setPreference("ignoreNotifications", checked ? "true" : "false") } } } diff --git a/src/libclient/api/conversation.h b/src/libclient/api/conversation.h index 26743e61106652402d2b8cb0c1a2baa881180e67..51911788ea28d60febca6364d0dcd6505de5a8aa 100644 --- a/src/libclient/api/conversation.h +++ b/src/libclient/api/conversation.h @@ -82,6 +82,7 @@ struct Info QSet<QString> typers; MapStringString infos {}; + MapStringString preferences {}; QString getCallId() const { diff --git a/src/libclient/api/conversationmodel.h b/src/libclient/api/conversationmodel.h index cb5595031c1dc5dc6114d58a41b71e94cd1fe802..29907bb8d04b6829a921ac3948f8299cbb9c26ba 100644 --- a/src/libclient/api/conversationmodel.h +++ b/src/libclient/api/conversationmodel.h @@ -332,11 +332,17 @@ public: */ void removeConversationMember(const QString& conversationId, const QString& memberId); /** - * get conversation info + * get conversation's info * @param conversationId conversation's id * @return conversation info */ MapStringString getConversationInfos(const QString& conversationId); + /** + * get conversation's preferences + * @param conversationId conversation's id + * @return conversation preferences + */ + MapStringString getConversationPreferences(const QString& conversationId); /** * create a new swarm conversation * @param participants conversation's participants @@ -346,9 +352,15 @@ public: /** * update conversation info * @param conversationId conversation's id - * @param info + * @param infos */ void updateConversationInfos(const QString& conversationId, MapStringString info); + /** + * update conversation's preferences + * @param conversationId conversation's id + * @param preferences + */ + void setConversationPreferences(const QString& conversationId, MapStringString preferences); /** * Remove first error * @param conversationId @@ -438,6 +450,11 @@ Q_SIGNALS: * @param uid */ void onConversationErrorsUpdated(const QString& uid) const; + /** + * Emitted when conversation's preferences has been updated + * @param uid + */ + void conversationPreferencesUpdated(const QString& uid) const; /** * Emitted when conversation's profile has been updated * @param uid diff --git a/src/libclient/callbackshandler.cpp b/src/libclient/callbackshandler.cpp index b0e085d1479f816a68d46e09c4baddd7ecf04caa..416842a2d27d1e353305fbb9e94febdcefe010a6 100644 --- a/src/libclient/callbackshandler.cpp +++ b/src/libclient/callbackshandler.cpp @@ -345,6 +345,11 @@ CallbacksHandler::CallbacksHandler(const Lrc& parent) this, &CallbacksHandler::slotOnConversationError, Qt::QueuedConnection); + connect(&ConfigurationManager::instance(), + &ConfigurationManagerInterface::conversationPreferencesUpdated, + this, + &CallbacksHandler::slotConversationPreferencesUpdated, + Qt::QueuedConnection); } CallbacksHandler::~CallbacksHandler() {} @@ -806,4 +811,12 @@ CallbacksHandler::slotOnConversationError(const QString& accountId, Q_EMIT conversationError(accountId, conversationId, code, what); } +void +CallbacksHandler::slotConversationPreferencesUpdated(const QString& accountId, + const QString& conversationId, + const MapStringString& preferences) +{ + Q_EMIT conversationPreferencesUpdated(accountId, conversationId, preferences); +} + } // namespace lrc diff --git a/src/libclient/callbackshandler.h b/src/libclient/callbackshandler.h index b39b6334ac2a22ab4d1d1b8cf9e82d9754845e42..d14704231b52281183b8931d7c8e6a62c7b72eb7 100644 --- a/src/libclient/callbackshandler.h +++ b/src/libclient/callbackshandler.h @@ -367,9 +367,12 @@ Q_SIGNALS: const QString& memberId, int event); void conversationError(const QString& accountId, - const QString& conversationId, - int code, - const QString& what); + const QString& conversationId, + int code, + const QString& what); + void conversationPreferencesUpdated(const QString& accountId, + const QString& conversationId, + const MapStringString& preferences); private Q_SLOTS: /** @@ -674,6 +677,9 @@ private Q_SLOTS: void slotConversationRequestReceived(const QString& accountId, const QString& conversationId, const MapStringString& metadatas); + void slotConversationPreferencesUpdated(const QString& accountId, + const QString& conversationId, + const MapStringString& preferences); void slotConversationRequestDeclined(const QString& accountId, const QString& conversationId); void slotConversationReady(const QString& accountId, const QString& conversationId); void slotConversationRemoved(const QString& accountId, const QString& conversationId); diff --git a/src/libclient/conversationmodel.cpp b/src/libclient/conversationmodel.cpp index fac188aa6828c185641e146142d7eac0d371dd63..2a3fab0ff7604f0b89f4b4d4c89558dc8a25b396 100644 --- a/src/libclient/conversationmodel.cpp +++ b/src/libclient/conversationmodel.cpp @@ -374,6 +374,9 @@ public Q_SLOTS: const QString& what); void slotConversationReady(const QString& accountId, const QString& conversationId); void slotConversationRemoved(const QString& accountId, const QString& conversationId); + void slotConversationPreferencesUpdated(const QString& accountId, + const QString& conversationId, + const MapStringString& preferences); }; ConversationModel::ConversationModel(const account::Info& owner, @@ -966,6 +969,14 @@ ConversationModel::getConversationInfos(const QString& conversationId) return ret; } +MapStringString +ConversationModel::getConversationPreferences(const QString& conversationId) +{ + MapStringString ret = ConfigurationManager::instance() + .getConversationPreferences(owner.id, conversationId); + return ret; +} + void ConversationModel::createConversation(const VectorString& participants, const MapStringString& infos) { @@ -982,12 +993,13 @@ ConversationModel::createConversation(const VectorString& participants, const Ma } void -ConversationModel::updateConversationInfos(const QString& conversationId, const MapStringString info) +ConversationModel::updateConversationInfos(const QString& conversationId, + const MapStringString infos) { - MapStringString newInfos = info; + MapStringString newInfos = infos; // Compress avatar as it will be sent in the conversation's request over the DHT - if (info.contains("avatar")) - newInfos["avatar"] = storage::vcard::compressedAvatar(info["avatar"]); + if (infos.contains("avatar")) + newInfos["avatar"] = storage::vcard::compressedAvatar(infos["avatar"]); ConfigurationManager::instance().updateConversationInfos(owner.id, conversationId, newInfos); } @@ -1003,6 +1015,13 @@ ConversationModel::popFrontError(const QString& conversationId) Q_EMIT onConversationErrorsUpdated(conversationId); } +void +ConversationModel::setConversationPreferences(const QString& conversationId, + const MapStringString prefs) +{ + ConfigurationManager::instance().setConversationPreferences(owner.id, conversationId, prefs); +} + bool ConversationModel::hasPendingRequests() const { @@ -1865,6 +1884,10 @@ ConversationModelPimpl::ConversationModelPimpl(const ConversationModel& linked, &CallbacksHandler::conversationError, this, &ConversationModelPimpl::slotOnConversationError); + connect(&callbacksHandler, + &CallbacksHandler::conversationPreferencesUpdated, + this, + &ConversationModelPimpl::slotConversationPreferencesUpdated); } ConversationModelPimpl::~ConversationModelPimpl() @@ -2009,6 +2032,10 @@ ConversationModelPimpl::~ConversationModelPimpl() &CallbacksHandler::conversationError, this, &ConversationModelPimpl::slotOnConversationError); + disconnect(&callbacksHandler, + &CallbacksHandler::conversationPreferencesUpdated, + this, + &ConversationModelPimpl::slotConversationPreferencesUpdated); } void @@ -2577,6 +2604,9 @@ ConversationModelPimpl::slotConversationReady(const QString& accountId, const MapStringString& details = ConfigurationManager::instance() .conversationInfos(accountId, conversationId); conversation.infos = details; + const MapStringString& preferences + = ConfigurationManager::instance().getConversationPreferences(accountId, conversationId); + conversation.preferences = preferences; conversation.mode = conversation::to_mode(details["mode"].toInt()); conversation.isRequest = false; conversation.needsSyncing = false; @@ -2983,6 +3013,9 @@ ConversationModelPimpl::addSwarmConversation(const QString& convId) } conversation.participants = participants; conversation.mode = mode; + const MapStringString& preferences = ConfigurationManager::instance() + .getConversationPreferences(linked.owner.id, convId); + conversation.preferences = preferences; conversation.unreadMessages = ConfigurationManager::instance().countInteractions(linked.owner.id, convId, lastRead, @@ -4198,6 +4231,19 @@ ConversationModelPimpl::updateTransferProgress(QTimer* timer, timer->deleteLater(); } +void +ConversationModelPimpl::slotConversationPreferencesUpdated(const QString&, + const QString& conversationId, + const MapStringString& preferences) +{ + auto conversationIdx = indexOf(conversationId); + if (conversationIdx < 0) + return; + auto& conversation = conversations[conversationIdx]; + conversation.preferences = preferences; + Q_EMIT linked.conversationPreferencesUpdated(conversationId); +} + } // namespace lrc #include "api/moc_conversationmodel.cpp" diff --git a/src/libclient/qtwrapper/configurationmanager_wrap.h b/src/libclient/qtwrapper/configurationmanager_wrap.h index ae1093b291b311bfb16eee305372958a7d356458..4946e86a5f987e88b6ecf91c394e103a9cb9aa42 100644 --- a/src/libclient/qtwrapper/configurationmanager_wrap.h +++ b/src/libclient/qtwrapper/configurationmanager_wrap.h @@ -319,6 +319,14 @@ public: Q_EMIT conversationRemoved(QString(accountId.c_str()), QString(conversationId.c_str())); }), + exportable_callback<ConversationSignal::ConversationPreferencesUpdated>( + [this](const std::string& accountId, + const std::string& conversationId, + const std::map<std::string, std::string>& preferences) { + Q_EMIT conversationPreferencesUpdated(QString(accountId.c_str()), + QString(conversationId.c_str()), + convertMap(preferences)); + }), exportable_callback<ConversationSignal::ConversationMemberEvent>( [this](const std::string& accountId, const std::string& conversationId, @@ -1103,6 +1111,13 @@ public Q_SLOTS: // METHODS DRing::conversationInfos(accountId.toStdString(), conversationId.toStdString())); } + MapStringString getConversationPreferences(const QString& accountId, + const QString& conversationId) + { + return convertMap(DRing::getConversationPreferences(accountId.toStdString(), + conversationId.toStdString())); + } + void updateConversationInfos(const QString& accountId, const QString& conversationId, const MapStringString& info) @@ -1112,6 +1127,15 @@ public Q_SLOTS: // METHODS convertMap(info)); } + void setConversationPreferences(const QString& accountId, + const QString& conversationId, + const MapStringString& prefs) + { + DRing::setConversationPreferences(accountId.toStdString(), + conversationId.toStdString(), + convertMap(prefs)); + } + uint32_t countInteractions(const QString& accountId, const QString& conversationId, const QString& toId, @@ -1214,6 +1238,9 @@ Q_SIGNALS: // SIGNALS const QString& conversationId, int code, const QString& what); + void conversationPreferencesUpdated(const QString& accountId, + const QString& conversationId, + const MapStringString& message); }; namespace org {