diff --git a/src/app/chat/event_handling.nim b/src/app/chat/event_handling.nim index 72b4e91e38..a9c38f4c63 100644 --- a/src/app/chat/event_handling.nim +++ b/src/app/chat/event_handling.nim @@ -14,8 +14,8 @@ proc handleChatEvents(self: ChatController) = let evArgs = MsgsLoadedArgs(e) self.view.onMessagesLoaded(evArgs.chatId, evArgs.messages) for statusUpdate in evArgs.statusUpdates: - self.view.communities.updateMemberVisibility(statusUpdate) - + self.view.communities.updateMemberVisibility(statusUpdate) + # Display emoji reactions self.status.events.on("reactionsLoaded") do(e:Args): self.view.reactions.push(ReactionsLoadedArgs(e).reactions) @@ -29,10 +29,6 @@ proc handleChatEvents(self: ChatController) = let notifications = ActivityCenterNotificationsArgs(e).activityCenterNotifications self.view.pushActivityCenterNotifications(notifications) - self.status.events.on("contactBlocked") do(e: Args): - var evArgs = ContactBlockedArgs(e) - self.view.removeChat(evArgs.contact.address) - self.status.events.on("contactUpdate") do(e: Args): var evArgs = ContactUpdateArgs(e) self.view.updateUsernames(evArgs.contacts) diff --git a/src/app/profile/views/contacts.nim b/src/app/profile/views/contacts.nim index 4e94143f11..424f227fae 100644 --- a/src/app/profile/views/contacts.nim +++ b/src/app/profile/views/contacts.nim @@ -77,14 +77,17 @@ QtObject: self.contactList.updateContact(contact) if contact.systemTags.contains(contactAdded): self.addedContacts.updateContact(contact) + if contact.isBlocked(): self.blockedContacts.updateContact(contact) + if contact.requestReceived() and not contact.systemTags.contains(contactAdded) and not contact.systemTags.contains(contactBlocked): self.contactRequests.updateContact(contact) + if not requestAlreadyAdded and contact.requestReceived(): self.contactRequestAdded(status_ens.userNameOrAlias(contact), contact.address) - self.contactListChanged() + self.contactListChanged() proc getContactList(self: ContactsView): QVariant {.slot.} = return newQVariant(self.contactList) @@ -172,7 +175,7 @@ QtObject: return let contact = self.status.contacts.getContactByID(id) - + if contact != nil: self.contactToAdd = contact else: diff --git a/src/status/contacts.nim b/src/status/contacts.nim index 329850eb1a..ffb3690fc1 100644 --- a/src/status/contacts.nim +++ b/src/status/contacts.nim @@ -11,13 +11,10 @@ type ContactModel* = ref object events*: EventEmitter -type +type ContactUpdateArgs* = ref object of Args contacts*: seq[Profile] - ContactBlockedArgs* = ref object of Args - contact*: Profile - proc newContactModel*(events: EventEmitter): ContactModel = result = ContactModel() result.events = events @@ -34,12 +31,8 @@ proc getContactByID*(self: ContactModel, id: string): Profile = proc blockContact*(self: ContactModel, id: string): string = var contact = self.getContactByID(id) contact.systemTags.add(contactBlocked) - let index = contact.systemTags.find(contactAdded) - if (index > -1): - contact.systemTags.delete(index) - discard status_contacts.blockContact(contact) - self.events.emit("contactBlocked", ContactBlockedArgs(contact: contact)) - + discard status_contacts.saveContact(contact.id, contact.ensVerified, contact.ensName, contact.alias, contact.identicon, contact.identityImage.thumbnail, contact.systemTags, contact.localNickname) + self.events.emit("contactBlocked", Args()) proc unblockContact*(self: ContactModel, id: string): string = var contact = self.getContactByID(id) diff --git a/src/status/libstatus/contacts.nim b/src/status/libstatus/contacts.nim index 51fe2e62a0..e55cb50944 100644 --- a/src/status/libstatus/contacts.nim +++ b/src/status/libstatus/contacts.nim @@ -7,18 +7,6 @@ var contactsInited {.threadvar.}: bool dirty: Atomic[bool] -# TODO: remove Profile from here -proc blockContact*(contact: Profile): string = - callPrivateRPC("blockContact".prefix, %* [ - { - "id": contact.id, - "ensVerified": contact.ensVerified, - "alias": contact.alias, - "identicon": contact.identicon, - "systemTags": contact.systemTags - } - ]) - proc getContactByID*(id: string): string = result = callPrivateRPC("getContactByID".prefix, %* [id]) dirty.store(true) diff --git a/src/status/profile/profile.nim b/src/status/profile/profile.nim index 22955d66ae..e74eebcef1 100644 --- a/src/status/profile/profile.nim +++ b/src/status/profile/profile.nim @@ -17,7 +17,7 @@ const contactBlocked* = ":contact/blocked" const contactRequest* = ":contact/request-received" proc isContact*(self: Profile): bool = - result = self.systemTags.contains(contactAdded) and not self.systemTags.contains(":contact/blocked") + result = self.systemTags.contains(contactAdded) proc isBlocked*(self: Profile): bool = result = self.systemTags.contains(contactBlocked) diff --git a/ui/app/AppLayouts/Chat/ChatColumn.qml b/ui/app/AppLayouts/Chat/ChatColumn.qml index 3d22860318..bf455e070e 100644 --- a/ui/app/AppLayouts/Chat/ChatColumn.qml +++ b/ui/app/AppLayouts/Chat/ChatColumn.qml @@ -299,6 +299,24 @@ Item { } } + Rectangle { + id: blockedBanner + Layout.fillWidth: true + height: 40 + Layout.alignment: Qt.AlignHCenter + visible: isBlocked + color: Style.current.red + opacity: 0.1 + } + + Text { + id: blockedText + anchors.centerIn: blockedBanner + visible: isBlocked + color: Style.current.red + text: qsTr("Blocked") + } + StackLayout { id: stackLayoutChatMessages Layout.fillWidth: true @@ -324,6 +342,7 @@ Item { Connections { target: chatsModel.channelView onActiveChannelChanged: { + isBlocked = profileModel.contacts.isContactBlocked(activeChatId); chatInput.suggestions.hide(); chatInput.textInput.forceActiveFocus(Qt.MouseFocusReason) populateSuggestions(); @@ -400,7 +419,7 @@ Item { community.admin || chatsModel.channelView.activeChannel.canPost } - enabled: !isBlocked + isContactBlocked: isBlocked chatInputPlaceholder: isBlocked ? //% "This user has been blocked." qsTrId("this-user-has-been-blocked-") : @@ -443,6 +462,7 @@ Item { } } } + } } diff --git a/ui/app/AppLayouts/Chat/ChatColumn/ChatComponents/InputArea.qml b/ui/app/AppLayouts/Chat/ChatColumn/ChatComponents/InputArea.qml index b1d9931ec0..bdf5e604d9 100644 --- a/ui/app/AppLayouts/Chat/ChatColumn/ChatComponents/InputArea.qml +++ b/ui/app/AppLayouts/Chat/ChatColumn/ChatComponents/InputArea.qml @@ -49,7 +49,7 @@ Item { community.admin || chatsModel.channelView.activeChannel.canPost } - enabled: !isBlocked + isContactBlocked: isBlocked chatInputPlaceholder: isBlocked ? //% "This user has been blocked." qsTrId("this-user-has-been-blocked-") : diff --git a/ui/app/AppLayouts/Chat/components/ContactList.qml b/ui/app/AppLayouts/Chat/components/ContactList.qml index 31dd626f7c..5f494ef4b7 100644 --- a/ui/app/AppLayouts/Chat/components/ContactList.qml +++ b/ui/app/AppLayouts/Chat/components/ContactList.qml @@ -26,9 +26,9 @@ ScrollView { isVisible: { if (selectMode) { return !searchString || model.name.toLowerCase().includes(searchString) - } else { - return isChecked || isUser } + + return isChecked || isUser } showCheckbox: root.selectMode pubKey: model.pubKey diff --git a/ui/app/AppLayouts/Profile/Sections/Contacts/ContactList.qml b/ui/app/AppLayouts/Profile/Sections/Contacts/ContactList.qml index 36784074ea..9b39a090ac 100644 --- a/ui/app/AppLayouts/Profile/Sections/Contacts/ContactList.qml +++ b/ui/app/AppLayouts/Profile/Sections/Contacts/ContactList.qml @@ -14,6 +14,7 @@ ListView { property string searchString: "" property string lowerCaseSearchString: searchString.toLowerCase() property string contactToRemove: "" + property bool hideBlocked: false property Component profilePopupComponent: ProfilePopup { id: profilePopup @@ -23,7 +24,7 @@ ListView { width: parent.width model: contacts - + delegate: Contact { name: Utils.removeStatusEns(model.name) address: model.address @@ -35,9 +36,15 @@ ListView { var popup = profilePopupComponent.createObject(contactList); popup.openPopup(showFooter, userName, fromAuthor, identicon, textParam, nickName); } - visible: searchString === "" || - model.name.toLowerCase().includes(lowerCaseSearchString) || - model.address.toLowerCase().includes(lowerCaseSearchString) + visible: { + if (hideBlocked && model.isBlocked) { + return false + } + + return searchString === "" || + model.name.toLowerCase().includes(lowerCaseSearchString) || + model.address.toLowerCase().includes(lowerCaseSearchString) + } onBlockContactActionTriggered: { blockContactConfirmationDialog.contactName = name blockContactConfirmationDialog.contactAddress = address diff --git a/ui/app/AppLayouts/Profile/Sections/ContactsContainer.qml b/ui/app/AppLayouts/Profile/Sections/ContactsContainer.qml index 80985eac79..64efacb3b7 100644 --- a/ui/app/AppLayouts/Profile/Sections/ContactsContainer.qml +++ b/ui/app/AppLayouts/Profile/Sections/ContactsContainer.qml @@ -219,6 +219,7 @@ Item { anchors.topMargin: Style.current.bigPadding anchors.bottom: parent.bottom contacts: profileModel.contacts.addedContacts + hideBlocked: true searchString: searchBox.text } diff --git a/ui/app/AppMain.qml b/ui/app/AppMain.qml index 1541d5b821..b5e00855b7 100644 --- a/ui/app/AppMain.qml +++ b/ui/app/AppMain.qml @@ -67,6 +67,10 @@ StatusAppLayout { const contacts = [] let contact for (let i = 0; i < nbContacts; i++) { + if (profileModel.contacts.list.rowData(i, "isBlocked") === "true") { + continue + } + contact = { name: profileModel.contacts.list.rowData(i, "name"), localNickname: profileModel.contacts.list.rowData(i, "localNickname"), diff --git a/ui/shared/BlockContactConfirmationDialog.qml b/ui/shared/BlockContactConfirmationDialog.qml index 3607442dde..c287e9f88d 100644 --- a/ui/shared/BlockContactConfirmationDialog.qml +++ b/ui/shared/BlockContactConfirmationDialog.qml @@ -20,14 +20,12 @@ ModalPopup { title: qsTrId("block-user") StyledText { - //% "Blocking will remove any messages you received from %1 and stop new messages from reaching you." - text: qsTrId("blocking-will-remove-any-messages-you-received-from--1-and-stop-new-messages-from-reaching-you-").arg(contactName) + text: qsTr("Blocking will stop new messages from reaching you from %1.").arg(contactName) font.pixelSize: 15 anchors.left: parent.left anchors.right: parent.right wrapMode: Text.WordWrap } - footer: Item { id: footerContainer diff --git a/ui/shared/ExistingContacts.qml b/ui/shared/ExistingContacts.qml index 305f2e2310..c58ca4b671 100644 --- a/ui/shared/ExistingContacts.qml +++ b/ui/shared/ExistingContacts.qml @@ -46,7 +46,7 @@ Item { name: model.name address: model.address identicon: model.thumbnailImage || model.identicon - visible: model.isContact && (root.filterText === "" || + visible: model.isContact && !model.isBlocked && (root.filterText === "" || root.matchesAlias(model.name.toLowerCase(), root.filterText.toLowerCase()) || model.name.toLowerCase().includes(root.filterText.toLowerCase()) || model.address.toLowerCase().includes(root.filterText.toLowerCase())) && diff --git a/ui/shared/status/StatusChatInput.qml b/ui/shared/status/StatusChatInput.qml index f2f6b89b2f..25ffd01b30 100644 --- a/ui/shared/status/StatusChatInput.qml +++ b/ui/shared/status/StatusChatInput.qml @@ -26,6 +26,7 @@ Rectangle { property bool isReply: false property bool isImage: false property bool isEdit: false + property bool isContactBlocked: false property var recentStickers property var stickerPackList @@ -695,6 +696,7 @@ Rectangle { anchors.bottom: parent.bottom anchors.bottomMargin: 16 visible: !isEdit && control.chatType === Constants.chatTypeOneToOne && !control.isStatusUpdateInput + enabled: !control.isContactBlocked onClicked: { highlighted = true chatCommandsPopup.open() @@ -711,7 +713,8 @@ Rectangle { anchors.bottom: parent.bottom anchors.bottomMargin: 16 visible: !isEdit && control.chatType !== Constants.chatTypePublic && !control.isStatusUpdateInput - + enabled: !control.isContactBlocked + onClicked: { highlighted = true imageDialog.open() @@ -720,6 +723,7 @@ Rectangle { Rectangle { id: messageInput + enabled: !control.isContactBlocked property int maxInputFieldHeight: control.isStatusUpdateInput ? 124 : 112 property int defaultInputFieldHeight: control.isStatusUpdateInput ? 56 : 40 anchors.left: imageBtn.visible ? imageBtn.right : parent.left @@ -727,7 +731,7 @@ Rectangle { anchors.top: control.isStatusUpdateInput ? parent.top : undefined anchors.bottom: !control.isStatusUpdateInput ? parent.bottom : undefined anchors.bottomMargin: control.isStatusUpdateInput ? 0 : 12 - anchors.right: parent.right + anchors.right: unblockBtn.visible ? unblockBtn.left : parent.right anchors.rightMargin: Style.current.smallPadding height: { if (messageInputField.implicitHeight <= messageInput.defaultInputFieldHeight) { @@ -859,8 +863,7 @@ Rectangle { font.pixelSize: 15 font.family: Style.current.fontRegular.name wrapMode: TextArea.Wrap - //% "Type a message" - placeholderText: qsTrId("type-a-message") + placeholderText: control.chatInputPlaceholder placeholderTextColor: Style.current.secondaryText selectByMouse: true color: isEdit ? Theme.palette.directColor1 : Style.current.textColor @@ -1110,4 +1113,20 @@ Rectangle { } } } + + StatusButton { + id: unblockBtn + visible: control.isContactBlocked + height: messageInput.height - Style.current.halfPadding + anchors.right: parent.right + anchors.rightMargin: Style.current.halfPadding + anchors.bottom: parent.bottom + anchors.bottomMargin: Style.current.padding + borderRadius: Style.current.radius + text: qsTr("Unblock") + type: "warn" + onClicked: function (event) { + profileModel.contacts.unblockContact(chatsModel.channelView.activeChannel.id) + } + } }