From 300ac17db3372cd7e9c52cc77eafca0c63bcbbe2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Blin?= <sebastien.blin@savoirfairelinux.com> Date: Mon, 4 Jul 2022 11:52:55 -0400 Subject: [PATCH] contactmodel: rework ban status And do not ban contact when removing conversation. Change-Id: Ia76c76b265dd2a9d7d3cc8e2f869bf74fd3cbe63 --- src/app/constant/JamiStrings.qml | 1 + src/app/conversationlistmodel.cpp | 2 +- src/app/conversationlistmodelbase.cpp | 5 +++ src/app/currentconversation.cpp | 1 + src/app/currentconversation.h | 1 + src/app/mainview/components/ChatView.qml | 4 +- .../mainview/components/ChatViewHeader.qml | 6 ++- .../components/ConversationListView.qml | 2 + .../ConversationSmartListContextMenu.qml | 16 ++++++-- .../components/SmartListItemDelegate.qml | 11 ++++++ src/app/messagesadapter.cpp | 13 +++++++ src/app/messagesadapter.h | 1 + src/libclient/contactmodel.cpp | 15 +++++++- src/libclient/conversationmodel.cpp | 38 +++++++++++-------- 14 files changed, 91 insertions(+), 25 deletions(-) diff --git a/src/app/constant/JamiStrings.qml b/src/app/constant/JamiStrings.qml index 9377704a6..69e2e18b3 100644 --- a/src/app/constant/JamiStrings.qml +++ b/src/app/constant/JamiStrings.qml @@ -355,6 +355,7 @@ Item { // BannedContacts property string tipBannedContactsDisplay: qsTr("Display banned contacts") + property string banned: qsTr("Banned") property string tipBannedContactsHide: qsTr("Hide banned contacts") // DeleteAccountDialog diff --git a/src/app/conversationlistmodel.cpp b/src/app/conversationlistmodel.cpp index 389729380..88301cb45 100644 --- a/src/app/conversationlistmodel.cpp +++ b/src/app/conversationlistmodel.cpp @@ -120,7 +120,7 @@ ConversationListProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex& s if (ignored_.contains(index.data(Role::UID).toString())) { match = true; } else if (index.data(Role::IsBanned).toBool()) { - if (!rx.isValid()) { + if (!rx.pattern().isEmpty() && rx.isValid()) { Q_FOREACH (const auto& filter, toFilter) { auto matchResult = rx.match(filter); if (matchResult.hasMatch() && matchResult.captured(0) == filter) { diff --git a/src/app/conversationlistmodelbase.cpp b/src/app/conversationlistmodelbase.cpp index 975d725f1..13d69e04f 100644 --- a/src/app/conversationlistmodelbase.cpp +++ b/src/app/conversationlistmodelbase.cpp @@ -128,6 +128,11 @@ ConversationListModelBase::dataForItem(item_t item, int role) const return QVariant(static_cast<int>(item.mode)); case Role::UID: return QVariant(item.uid); + case Role::IsBanned: + if (!item.isCoreDialog()) { + return false; + } + break; case Role::Uris: return QVariant(model_->peersForConversation(item.uid).toList()); case Role::Monikers: { diff --git a/src/app/currentconversation.cpp b/src/app/currentconversation.cpp index 534d6881c..5de28c6bb 100644 --- a/src/app/currentconversation.cpp +++ b/src/app/currentconversation.cpp @@ -84,6 +84,7 @@ CurrentConversation::updateData() if (isCoreDialog_) try { auto& contact = accInfo.contactModel->getContact(members.at(0)); + set_isBanned(contact.isBanned); isContact = contact.profileInfo.type != profile::Type::TEMPORARY; } catch (const std::exception& e) { qInfo() << "Contact not found: " << e.what(); diff --git a/src/app/currentconversation.h b/src/app/currentconversation.h index 58e393c80..6aa85f3d4 100644 --- a/src/app/currentconversation.h +++ b/src/app/currentconversation.h @@ -40,6 +40,7 @@ class CurrentConversation final : public QObject QML_PROPERTY(bool, readOnly) QML_PROPERTY(bool, needsSyncing) QML_PROPERTY(bool, isSip) + QML_PROPERTY(bool, isBanned) QML_PROPERTY(QString, callId) QML_PROPERTY(QString, color) QML_PROPERTY(call::Status, callState) diff --git a/src/app/mainview/components/ChatView.qml b/src/app/mainview/components/ChatView.qml index e3777b146..0dfc8f6d8 100644 --- a/src/app/mainview/components/ChatView.qml +++ b/src/app/mainview/components/ChatView.qml @@ -171,7 +171,9 @@ Rectangle { id: chatViewFooter visible: { - if (CurrentConversation.needsSyncing || CurrentConversation.readOnly) + if (CurrentConversation.isBlocked) + return false + else if (CurrentConversation.needsSyncing || CurrentConversation.readOnly) return false else if (CurrentConversation.isSwarm && CurrentConversation.isRequest) return false diff --git a/src/app/mainview/components/ChatViewHeader.qml b/src/app/mainview/components/ChatViewHeader.qml index 3ad3baaca..8f80044d4 100644 --- a/src/app/mainview/components/ChatViewHeader.qml +++ b/src/app/mainview/components/ChatViewHeader.qml @@ -209,7 +209,7 @@ Rectangle { PushButton { id: sendContactRequestButton - visible: CurrentConversation.isTemporary + visible: CurrentConversation.isTemporary || CurrentConversation.isBanned source: JamiResources.add_people_24dp_svg toolTipText: JamiStrings.addToConversations @@ -217,7 +217,9 @@ Rectangle { normalColor: JamiTheme.chatviewBgColor imageColor: JamiTheme.chatviewButtonColor - onClicked: MessagesAdapter.sendConversationRequest() + onClicked: CurrentConversation.isBanned ? + MessagesAdapter.unbanConversation(CurrentConversation.id) + : MessagesAdapter.sendConversationRequest() } PushButton { diff --git a/src/app/mainview/components/ConversationListView.qml b/src/app/mainview/components/ConversationListView.qml index e1f523ab9..931205b27 100644 --- a/src/app/mainview/components/ConversationListView.qml +++ b/src/app/mainview/components/ConversationListView.qml @@ -128,6 +128,7 @@ JamiListView { "title": model.dataForRow(row, ConversationList.Title), "uri": model.dataForRow(row, ConversationList.URI), "isSwarm": model.dataForRow(row, ConversationList.IsSwarm), + "isBanned": model.dataForRow(row, ConversationList.IsBanned), "mode": model.dataForRow(row, ConversationList.Mode), "readOnly": model.dataForRow(row, ConversationList.ReadOnly) } @@ -135,6 +136,7 @@ JamiListView { responsibleAccountId = LRCInstance.currentAccountId responsibleConvUid = item.convId isSwarm = item.isSwarm + isBanned = item.isBanned mode = item.mode contactType = LRCInstance.currentAccountType readOnly = item.readOnly diff --git a/src/app/mainview/components/ConversationSmartListContextMenu.qml b/src/app/mainview/components/ConversationSmartListContextMenu.qml index 042871dff..e92bd4c6c 100644 --- a/src/app/mainview/components/ConversationSmartListContextMenu.qml +++ b/src/app/mainview/components/ConversationSmartListContextMenu.qml @@ -30,6 +30,7 @@ ContextMenuAutoLoader { property string responsibleAccountId: "" property string responsibleConvUid: "" + property bool isBanned: false property bool isSwarm: false property var mode: undefined property int contactType: Profile.Type.INVALID @@ -70,7 +71,7 @@ ContextMenuAutoLoader { GeneralMenuItem { id: clearConversation - canTrigger: !isSwarm && !hasCall + canTrigger: !isSwarm && !hasCall && !root.isBanned itemName: JamiStrings.clearConversation iconSource: JamiResources.ic_clear_24dp_svg onClicked: MessagesAdapter.clearConversationHistory( @@ -80,7 +81,7 @@ ContextMenuAutoLoader { GeneralMenuItem { id: removeContact - canTrigger: !hasCall + canTrigger: !hasCall && !root.isBanned itemName: { if (mode !== Conversation.Mode.ONE_TO_ONE && mode !== Conversation.Mode.NON_SWARM) return JamiStrings.removeConversation @@ -126,12 +127,21 @@ ContextMenuAutoLoader { GeneralMenuItem { id: blockContact - canTrigger: !hasCall && contactType !== Profile.Type.SIP + canTrigger: !hasCall && contactType !== Profile.Type.SIP && !root.isBanned itemName: !(mode && mode !== Conversation.Mode.ONE_TO_ONE && mode !== Conversation.Mode.NON_SWARM) ? JamiStrings.blockContact : JamiStrings.blockSwarm iconSource: JamiResources.block_black_24dp_svg addMenuSeparatorAfter: contactType !== Profile.Type.SIP onClicked: MessagesAdapter.blockConversation(responsibleConvUid) }, + GeneralMenuItem { + id: unblockContact + + canTrigger: root.isBanned + itemName: JamiStrings.reinstateContact + iconSource: JamiResources.round_remove_circle_24dp_svg + addMenuSeparatorAfter: contactType !== Profile.Type.SIP + onClicked: MessagesAdapter.unbanConversation(responsibleConvUid) + }, GeneralMenuItem { id: contactDetails diff --git a/src/app/mainview/components/SmartListItemDelegate.qml b/src/app/mainview/components/SmartListItemDelegate.qml index 580f15c22..c5f11d612 100644 --- a/src/app/mainview/components/SmartListItemDelegate.qml +++ b/src/app/mainview/components/SmartListItemDelegate.qml @@ -116,6 +116,7 @@ ItemDelegate { } RowLayout { visible: ContactType !== Profile.Type.TEMPORARY + && !IsBanned && LastInteractionDate !== undefined && interactive Layout.fillWidth: true @@ -151,6 +152,16 @@ ItemDelegate { lineHeight: font.family === "Segoe UI Emoji" ? 1.25 : 1 } } + Text { + Layout.fillWidth: true + Layout.preferredHeight: 20 + Layout.alignment: Qt.AlignVCenter + text: JamiStrings.banned + visible: IsBanned + font.pointSize: JamiTheme.smartlistItemFontSize + font.weight: Font.Bold + color: JamiTheme.textColor + } } // read-only conversation indicator diff --git a/src/app/messagesadapter.cpp b/src/app/messagesadapter.cpp index ddea15a62..3ba15c1c7 100644 --- a/src/app/messagesadapter.cpp +++ b/src/app/messagesadapter.cpp @@ -368,6 +368,19 @@ MessagesAdapter::unbanContact(int index) } } +void +MessagesAdapter::unbanConversation(const QString& convUid) +{ + auto& accInfo = lrcInstance_->getCurrentAccountInfo(); + try { + const auto contactUri = accInfo.conversationModel->peersForConversation(convUid).at(0); + auto contactInfo = accInfo.contactModel->getContact(contactUri); + accInfo.contactModel->addContact(contactInfo); + } catch (const std::out_of_range& e) { + qDebug() << e.what(); + } +} + void MessagesAdapter::clearConversationHistory(const QString& accountId, const QString& convUid) { diff --git a/src/app/messagesadapter.h b/src/app/messagesadapter.h index d51ecacf2..3d28af316 100644 --- a/src/app/messagesadapter.h +++ b/src/app/messagesadapter.h @@ -90,6 +90,7 @@ protected: Q_INVOKABLE void refuseInvitation(const QString& convUid = ""); Q_INVOKABLE void blockConversation(const QString& convUid = ""); Q_INVOKABLE void unbanContact(int index); + Q_INVOKABLE void unbanConversation(const QString& convUid); Q_INVOKABLE void sendMessage(const QString& message); Q_INVOKABLE void sendFile(const QString& message); Q_INVOKABLE void acceptFile(const QString& arg); diff --git a/src/libclient/contactmodel.cpp b/src/libclient/contactmodel.cpp index 63e4825db..425b97057 100644 --- a/src/libclient/contactmodel.cpp +++ b/src/libclient/contactmodel.cpp @@ -344,6 +344,15 @@ ContactModel::addToContacts(const QString& contactUri) void ContactModel::removeContact(const QString& contactUri, bool banned) { + try { + const auto& contact = getContact(contactUri); + if (contact.isBanned) { + qWarning() << "Contact already banned"; + return; + } + } catch (...) { + } + bool emitContactRemoved = false; { std::lock_guard<std::mutex> lk(pimpl_->contactsMtx_); @@ -872,8 +881,9 @@ ContactModelPimpl::slotContactRemoved(const QString& accountId, std::lock_guard<std::mutex> lk(contactsMtx_); auto contact = contacts.find(contactUri); - if (contact == contacts.end()) + if (contact == contacts.end()) { return; + } if (contact->profileInfo.type == profile::Type::PENDING) { Q_EMIT behaviorController.trustRequestTreated(linked.owner.id, contactUri); @@ -911,8 +921,9 @@ ContactModelPimpl::slotContactRemoved(const QString& accountId, linked.owner.conversationModel->refreshFilter(); if (banned) { Q_EMIT linked.bannedStatusChanged(contactUri, true); + } else { + Q_EMIT linked.contactRemoved(contactUri); } - Q_EMIT linked.contactRemoved(contactUri); } void diff --git a/src/libclient/conversationmodel.cpp b/src/libclient/conversationmodel.cpp index 6cf865464..6f0029066 100644 --- a/src/libclient/conversationmodel.cpp +++ b/src/libclient/conversationmodel.cpp @@ -814,20 +814,14 @@ ConversationModel::removeConversation(const QString& uid, bool banned) "participant"; return; } - if (conversation.isSwarm()) { + if (!conversation.isCoreDialog()) { if (conversation.isRequest) ConfigurationManager::instance().declineConversationRequest(owner.id, uid); else ConfigurationManager::instance().removeConversation(owner.id, uid); - - // Still some other conversation, do nothing else - if (!banned) - return; + } else { + owner.contactModel->removeContact(peers.front(), banned); } - - if (!conversation.isCoreDialog()) - return; - owner.contactModel->removeContact(peers.front(), banned); } void @@ -2575,21 +2569,33 @@ ConversationModelPimpl::slotConversationRemoved(const QString& accountId, auto& conversation = getConversationForUid(conversationId).get(); auto& peers = peersForConversation(conversation); + if (peers.isEmpty()) { + removeConversation(); + return; + } + auto contactUri = peers.first(); + contact::Info contact; + try { + contact = linked.owner.contactModel->getContact(contactUri); + } catch (...) { + } if (conversation.mode == conversation::Mode::ONE_TO_ONE) { - if (peers.isEmpty()) { - removeConversation(); - return; - } - - auto contactUri = peers.first(); removeConversation(); // If it's a 1:1 conversation and we don't have any more conversation // we can remove the contact auto conv = storage::getConversationsWithPeer(db, contactUri); if (conv.empty()) - linked.owner.contactModel->removeContact(contactUri, true); + linked.owner.contactModel->removeContact(contactUri, false); + + if (contact.isBanned && conv.empty()) { + // Add 1:1 conv for banned + auto c = storage::beginConversationWithPeer(db, contactUri); + addConversationWith(c, contactUri, false); + Q_EMIT linked.conversationReady(c, contactUri); + Q_EMIT linked.newConversation(c); + } } else { removeConversation(); } -- GitLab