diff --git a/src/api/conversationmodel.h b/src/api/conversationmodel.h index 8b2857eea8461291b4fcdfc7362c516adc1b9b11..fb3bfe275aa853c2faea20a043b775353ec78b28 100644 --- a/src/api/conversationmodel.h +++ b/src/api/conversationmodel.h @@ -78,13 +78,18 @@ public: * Get a custom filtered set of conversations * @return conversations filtered */ - const ConversationQueue& getFilteredConversations(const profile::Type& filter = profile::Type::INVALID, bool forceUpdate = false) const; + const ConversationQueue& getFilteredConversations(const profile::Type& filter = profile::Type::INVALID, bool forceUpdate = false, const bool includeBanned = false) const; /** * Get the conversation at row in the filtered conversations * @param row * @return a copy of the conversation */ conversation::Info filteredConversation(unsigned int row) const; + /** + * Emit a filterChanged signal to force the client to refresh the filter. For instance + * this is required when a contact was banned or un-banned. + */ + void refreshFilter(); /** * Make permanent a temporary contact or a pending request. * Ensure that given conversation is stored permanently into the system. diff --git a/src/contactmodel.cpp b/src/contactmodel.cpp index 9dd339c7b4e708ce53a54a541a4b23fa56e27319..257c9a1b7c090cb5cf3b5d35b8299a81ad8b7b01 100644 --- a/src/contactmodel.cpp +++ b/src/contactmodel.cpp @@ -31,6 +31,7 @@ #include "api/contact.h" #include "api/interaction.h" #include "api/newcallmodel.h" +#include "api/conversationmodel.h" #include "callbackshandler.h" #include "accountmodel.h" @@ -521,18 +522,37 @@ ContactModelPimpl::slotContactAdded(const std::string& accountId, const std::str void ContactModelPimpl::slotContactRemoved(const std::string& accountId, const std::string& contactUri, bool banned) { - Q_UNUSED(banned) if (accountId != linked.owner.id) return; + { std::lock_guard<std::mutex> lk(contactsMtx_); - if (contacts.find(contactUri) != contacts.end()) { + + auto contact = contacts.find(contactUri); + if (contact == contacts.end()) return; + + if (banned) { + contact->second.isBanned = true; + + auto* account = AccountModel::instance().getById(linked.owner.id.c_str()); + if (not account) { + qDebug() << "ContactModel::slotContactsAdded(), nullptr"; + return; + } + auto* cm = PhoneDirectoryModel::instance().getNumber(QString(contactUri.c_str()), account); + account->bannedContactModel()->add(cm); + } else { database::removeContact(db, linked.owner.profileInfo.uri, contactUri); contacts.erase(contactUri); - } else - return; + } + } + + if (banned) { + // Update the smartlist + linked.owner.conversationModel->refreshFilter(); + } else { + emit linked.contactRemoved(contactUri); } - emit linked.contactRemoved(contactUri); } void diff --git a/src/conversationmodel.cpp b/src/conversationmodel.cpp index 21fc64294cf33e9d2c7713e1cde4cd58b9f25975..92f0502953bce37c11195f2244a7b51431d6fb8f 100644 --- a/src/conversationmodel.cpp +++ b/src/conversationmodel.cpp @@ -281,7 +281,17 @@ ConversationModel::allFilteredConversations() const pimpl_->filteredConversations.begin(), [this] (const conversation::Info& entry) { auto contactInfo = owner.contactModel->getContact(entry.participants.front()); - // Check type + + /* Check contact */ + // If contact is banned, only match if filter is a perfect match + if (contactInfo.isBanned) { + if (pimpl_->filter == "") return false; + return contactInfo.profileInfo.uri == pimpl_->filter + || contactInfo.profileInfo.alias == pimpl_->filter + || contactInfo.registeredName == pimpl_->filter; + } + + /* Check type */ if (pimpl_->typeFilter != profile::Type::PENDING) { // Remove pending contacts and get the temporary item if filter is not empty if (contactInfo.profileInfo.type == profile::Type::PENDING) @@ -294,7 +304,7 @@ ConversationModel::allFilteredConversations() const return false; } - // Check contact + // Otherwise perform usual regex search try { auto regexFilter = std::regex(pimpl_->filter, std::regex_constants::icase); bool result = std::regex_search(contactInfo.profileInfo.uri, regexFilter) @@ -315,7 +325,7 @@ ConversationModel::allFilteredConversations() const } const ConversationModel::ConversationQueue& -ConversationModel::getFilteredConversations(const profile::Type& filter, bool forceUpdate) const +ConversationModel::getFilteredConversations(const profile::Type& filter, bool forceUpdate, const bool includeBanned) const { if (pimpl_->customTypeFilter == filter && !pimpl_->dirtyConversations.second && !forceUpdate) return pimpl_->customFilteredConversations; @@ -326,8 +336,9 @@ ConversationModel::getFilteredConversations(const profile::Type& filter, bool fo auto it = std::copy_if( pimpl_->conversations.begin(), pimpl_->conversations.end(), pimpl_->customFilteredConversations.begin(), - [this] (const conversation::Info& entry) { + [this, &includeBanned] (const conversation::Info& entry) { auto contactInfo = owner.contactModel->getContact(entry.participants.front()); + if (!includeBanned && contactInfo.isBanned) return false; return (contactInfo.profileInfo.type == pimpl_->customTypeFilter); }); pimpl_->customFilteredConversations.resize(std::distance(pimpl_->customFilteredConversations.begin(), it)); @@ -625,6 +636,13 @@ ConversationModel::sendMessage(const std::string& uid, const std::string& body) emit modelSorted(); } +void +ConversationModel::refreshFilter() +{ + pimpl_->dirtyConversations = {true, true}; + emit filterChanged(); +} + void ConversationModel::setFilter(const std::string& filter) {