From 233d1f4da45d12d7adc38fef29e5b5cfaa335cf5 Mon Sep 17 00:00:00 2001 From: Eric Mastro Date: Tue, 21 Sep 2021 08:07:31 +1000 Subject: [PATCH] fix: block/unblock contacts not persisting Fixes: #3473. Sometimes when blocking users and changes channels, blocked user messages would still appear. This PR fixes the issue by toggling a `hide` property on messages from a contact when that contact is blocked or unblocked. Previously, the messages were only removed from the view when the contact was blocked, but when the view was reloaded, that state was not tracked correctly. --- src/app/chat/core.nim | 8 +++ src/app/chat/views/message_list.nim | 51 ++++++++++++++----- src/app/chat/views/messages.nim | 33 ++++++++---- .../Chat/ChatColumn/ChatMessages.qml | 1 + ui/app/AppLayouts/Chat/ChatColumn/Message.qml | 2 +- vendor/status-lib | 2 +- 6 files changed, 73 insertions(+), 24 deletions(-) diff --git a/src/app/chat/core.nim b/src/app/chat/core.nim index 159452e4ca..770ff149ce 100644 --- a/src/app/chat/core.nim +++ b/src/app/chat/core.nim @@ -71,6 +71,14 @@ proc init*(self: ChatController) = self.view.handleProtocolUri(self.uriToOpen) self.uriToOpen = "" + self.status.events.on("contactBlocked") do(e: Args): + let contactIdArgs = ContactIdArgs(e) + self.view.messageView.blockContact(contactIdArgs.id) + + self.status.events.on("contactUnblocked") do(e: Args): + let contactIdArgs = ContactIdArgs(e) + self.view.messageView.unblockContact(contactIdArgs.id) + proc loadInitialMessagesForChannel*(self: ChatController, channelId: string) = if (channelId.len == 0): info "empty channel id set for loading initial messages" diff --git a/src/app/chat/views/message_list.nim b/src/app/chat/views/message_list.nim index 76ab650e63..b610f28494 100644 --- a/src/app/chat/views/message_list.nim +++ b/src/app/chat/views/message_list.nim @@ -46,6 +46,7 @@ type GapTo = UserRole + 33 Replace = UserRole + 34 IsEdited = UserRole + 35 + Hide = UserRole + 36 QtObject: type @@ -60,6 +61,7 @@ QtObject: userList*: UserListView loadingHistoryMessages: bool initialMessagesLoaded: bool + blockedContacts: seq[string] proc delete*(self: ChatMessageList) = self.messages = @[] @@ -81,7 +83,7 @@ QtObject: self.messages.add(self.fetchMoreMessagesButton()) self.messages.add(self.chatIdentifier(self.id)) - proc setup*(self: ChatMessageList, chatId: string, status: Status, addFakeMessages: bool) = + proc setup*(self: ChatMessageList, chatId: string, status: Status, addFakeMessages: bool, blockedContacts: seq[string]) = self.messages = @[] self.id = chatId self.loadingHistoryMessages = false @@ -95,12 +97,13 @@ QtObject: self.isEdited = initTable[string, bool]() self.userList = newUserListView(status) self.status = status + self.blockedContacts = blockedContacts self.QAbstractListModel.setup - proc newChatMessageList*(chatId: string, status: Status, addFakeMessages: bool): ChatMessageList = + proc newChatMessageList*(chatId: string, status: Status, addFakeMessages: bool, blockedContacts: seq[string] = @[]): ChatMessageList = new(result, delete) - result.setup(chatId, status, addFakeMessages) + result.setup(chatId, status, addFakeMessages, blockedContacts) ################################################# # Properties @@ -174,6 +177,13 @@ QtObject: for message in messages: discard self.deleteMessage(message.id) + proc toggleMessage*(self: ChatMessageList, messageId: string, hide: bool) = + let msgIdx = self.messageIndex[messageId] + let topLeft = self.createIndex(msgIdx, 0, nil) + let bottomRight = self.createIndex(msgIdx, 0, nil) + self.messages[msgIdx].hide = hide + self.dataChanged(topLeft, bottomRight, @[ChatMessageRoles.Hide.int]) + proc replaceMessage*(self: ChatMessageList, message: Message) = let msgIdx = self.messageIndex[message.id] let topLeft = self.createIndex(msgIdx, 0, nil) @@ -262,6 +272,7 @@ QtObject: of ChatMessageRoles.GapTo: result = newQVariant(message.gapTo) of ChatMessageRoles.Replace: result = newQVariant(message.replace) of ChatMessageRoles.IsEdited: result = newQVariant(isEdited) + of ChatMessageRoles.Hide: result = newQVariant(message.hide) method roleNames(self: ChatMessageList): Table[int, string] = { @@ -298,7 +309,8 @@ QtObject: ChatMessageRoles.GapFrom.int:"gapFrom", ChatMessageRoles.GapTo.int:"gapTo", ChatMessageRoles.Replace.int:"replaces", - ChatMessageRoles.IsEdited.int:"isEdited" + ChatMessageRoles.IsEdited.int:"isEdited", + ChatMessageRoles.Hide.int:"hide" }.toTable proc getMessageIndex*(self: ChatMessageList, messageId: string): int {.slot.} = @@ -331,9 +343,13 @@ QtObject: proc addChatMembers*(self: ChatMessageList, members: seq[ChatMember]) = self.userList.add(members) - proc add*(self: ChatMessageList, message: Message) = + proc add*(self: ChatMessageList, message: var Message) = if self.messageIndex.hasKey(message.id) and message.editedAt == "0": return # duplicated msg + # don't show blocked contact messages + if self.blockedContacts.contains(message.fromAuthor): + message.hide = true + if message.editedAt != "0": self.isEdited[message.id] = true if self.messageIndex.hasKey(message.id): @@ -348,10 +364,12 @@ QtObject: self.endInsertRows() self.countChanged() - proc add*(self: ChatMessageList, messages: seq[Message]) = + proc add*(self: ChatMessageList, messages: var seq[Message]) = self.beginInsertRows(newQModelIndex(), self.messages.len, self.messages.len + messages.len - 1) - for message in messages: + for message in messages.mitems: if self.messageIndex.hasKey(message.id): continue + if self.blockedContacts.contains(message.fromAuthor): + message.hide = true self.messageIndex[message.id] = self.messages.len self.messages.add(message) self.userList.add(message) @@ -429,13 +447,20 @@ QtObject: self.dataChanged(topLeft, bottomRight, @[ChatMessageRoles.Username.int]) - proc removeMessagesByUserId*(self: ChatMessageList, publicKey: string) = + proc toggleMessagesFromUser*(self: ChatMessageList, publicKey: string, hide: bool) = var msgIdxToDelete: seq[string] = @[] - for m in self.messages.items: - if m.fromAuthor == publicKey: # Can't delete on a loop - msgIdxToDelete.add(m.id) - for m in msgIdxToDelete: - discard self.deleteMessage(m) + for m in self.messages.mitems: + if m.fromAuthor == publicKey: + m.hide = hide + self.toggleMessage(m.id, hide) + + proc blockContact*(self: ChatMessageList, contactId: string) = + self.blockedContacts.add contactId + self.toggleMessagesFromUser contactId, true + + proc unblockContact*(self: ChatMessageList, contactId: string) = + self.blockedContacts.keepItIf(it != contactId) + self.toggleMessagesFromUser contactId, false proc getID*(self: ChatMessageList):string {.slot.} = self.id diff --git a/src/app/chat/views/messages.nim b/src/app/chat/views/messages.nim index 28ce9d3369..66352699e7 100644 --- a/src/app/chat/views/messages.nim +++ b/src/app/chat/views/messages.nim @@ -1,15 +1,16 @@ -import NimQml, Tables, json, sequtils, chronicles, times, re, strutils +import NimQml, Tables, json, sequtils, chronicles, times, re, strutils, sugar import status/[status, contacts] import status/messages as status_messages import status/utils as status_utils import status/chat/[chat] +import status/profile/[profile] import status/types/[message] import ../../../app_service/[main] import ../../../app_service/tasks/[qt, threadpool] import ../../../app_service/tasks/marathon/mailserver/worker -import communities, chat_item, channels_list, communities, community_list, user_list, community_members_list, message_list, channel, message_item, message_format +import communities, chat_item, channels_list, communities, user_list, community_members_list, message_list, channel, message_item, message_format logScope: topics = "messages-view" @@ -170,19 +171,29 @@ QtObject: self.messageList[id].clear(not channel.isNil and channel.chatType != ChatType.Profile) self.messagesCleared() + proc getBlockedContacts*(self: MessageView): seq[string] = + return self.status.contacts.getContacts() + .filter(c => c.isBlocked) + .map(c => c.id) + proc upsertChannel*(self: MessageView, channel: string) = var chat: Chat = nil if self.status.chat.channels.hasKey(channel): chat = self.status.chat.channels[channel] else: chat = self.communities.getChannel(channel) + + var blockedContacts: seq[string] = @[] + if not self.messageList.hasKey(channel) or not self.pinnedMessagesList.hasKey(channel): + blockedContacts = self.getBlockedContacts + if not self.messageList.hasKey(channel): self.beginInsertRows(newQModelIndex(), self.messageList.len, self.messageList.len) - self.messageList[channel] = newChatMessageList(channel, self.status, not chat.isNil and chat.chatType != ChatType.Profile) + self.messageList[channel] = newChatMessageList(channel, self.status, not chat.isNil and chat.chatType != ChatType.Profile, blockedContacts) self.channelOpenTime[channel] = now().toTime.toUnix * 1000 self.endInsertRows(); if not self.pinnedMessagesList.hasKey(channel): - self.pinnedMessagesList[channel] = newChatMessageList(channel, self.status, false) + self.pinnedMessagesList[channel] = newChatMessageList(channel, self.status, false, blockedContacts) proc pushPinnedMessages*(self:MessageView, pinnedMessages: var seq[Message]) = for msg in pinnedMessages.mitems: @@ -199,9 +210,9 @@ QtObject: proc isAddedContact*(self: MessageView, id: string): bool {.slot.} = result = self.status.contacts.isAdded(id) - proc messageNotificationPushed*(self: MessageView, messageId: string, - communityId: string, chatId: string, text: string, contentType: int, - chatType: int, timestamp: string, identicon: string, username: string, + proc messageNotificationPushed*(self: MessageView, messageId: string, + communityId: string, chatId: string, text: string, contentType: int, + chatType: int, timestamp: string, identicon: string, username: string, hasMention: bool, isAddedContact: bool, channelName: string) {.signal.} proc pushMembers*(self:MessageView, chats: seq[Chat]) = @@ -376,9 +387,13 @@ QtObject: if (result): self.hideMessage(msgIdToBeDeleted) - proc removeMessagesByUserId(self: MessageView, publicKey: string) {.slot.} = + proc blockContact*(self: MessageView, contactId: string) = for k in self.messageList.keys: - self.messageList[k].removeMessagesByUserId(publicKey) + self.messageList[k].blockContact(contactId) + + proc unblockContact*(self: MessageView, contactId: string) = + for k in self.messageList.keys: + self.messageList[k].unblockContact(contactId) proc getMessageListIndex(self: MessageView): int {.slot.} = var idx = -1 diff --git a/ui/app/AppLayouts/Chat/ChatColumn/ChatMessages.qml b/ui/app/AppLayouts/Chat/ChatColumn/ChatMessages.qml index 2d05b5beb9..abfeb0670b 100644 --- a/ui/app/AppLayouts/Chat/ChatColumn/ChatMessages.qml +++ b/ui/app/AppLayouts/Chat/ChatColumn/ChatMessages.qml @@ -303,6 +303,7 @@ Item { pinnedBy: model.pinnedBy gapFrom: model.gapFrom gapTo: model.gapTo + visible: !model.hide Component.onCompleted: { if ((root.countOnStartUp > 0) && (root.countOnStartUp - 1) < index) { //new message, increment z order diff --git a/ui/app/AppLayouts/Chat/ChatColumn/Message.qml b/ui/app/AppLayouts/Chat/ChatColumn/Message.qml index 8dc166d33e..89e92935c7 100644 --- a/ui/app/AppLayouts/Chat/ChatColumn/Message.qml +++ b/ui/app/AppLayouts/Chat/ChatColumn/Message.qml @@ -10,7 +10,7 @@ Item { id: root width: parent.width anchors.right: !isCurrentUser ? undefined : parent.right - height: childrenRect.height + height: visible ? childrenRect.height : 0 z: (typeof chatLogView === "undefined") ? 1 : (chatLogView.count - index) property string fromAuthor: "0x0011223344556677889910" property string userName: "Jotaro Kujo" diff --git a/vendor/status-lib b/vendor/status-lib index 4f7e899953..aa1fdf8a2f 160000 --- a/vendor/status-lib +++ b/vendor/status-lib @@ -1 +1 @@ -Subproject commit 4f7e899953843a316336fa72ae049f7880f6f7bd +Subproject commit aa1fdf8a2ff469760c9857ab5eeedf976cd1c43a