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.
This commit is contained in:
Eric Mastro 2021-09-21 08:07:31 +10:00 committed by Iuri Matias
parent 0c73febf2c
commit 233d1f4da4
6 changed files with 73 additions and 24 deletions

View File

@ -71,6 +71,14 @@ proc init*(self: ChatController) =
self.view.handleProtocolUri(self.uriToOpen) self.view.handleProtocolUri(self.uriToOpen)
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) = proc loadInitialMessagesForChannel*(self: ChatController, channelId: string) =
if (channelId.len == 0): if (channelId.len == 0):
info "empty channel id set for loading initial messages" info "empty channel id set for loading initial messages"

View File

@ -46,6 +46,7 @@ type
GapTo = UserRole + 33 GapTo = UserRole + 33
Replace = UserRole + 34 Replace = UserRole + 34
IsEdited = UserRole + 35 IsEdited = UserRole + 35
Hide = UserRole + 36
QtObject: QtObject:
type type
@ -60,6 +61,7 @@ QtObject:
userList*: UserListView userList*: UserListView
loadingHistoryMessages: bool loadingHistoryMessages: bool
initialMessagesLoaded: bool initialMessagesLoaded: bool
blockedContacts: seq[string]
proc delete*(self: ChatMessageList) = proc delete*(self: ChatMessageList) =
self.messages = @[] self.messages = @[]
@ -81,7 +83,7 @@ QtObject:
self.messages.add(self.fetchMoreMessagesButton()) self.messages.add(self.fetchMoreMessagesButton())
self.messages.add(self.chatIdentifier(self.id)) 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.messages = @[]
self.id = chatId self.id = chatId
self.loadingHistoryMessages = false self.loadingHistoryMessages = false
@ -95,12 +97,13 @@ QtObject:
self.isEdited = initTable[string, bool]() self.isEdited = initTable[string, bool]()
self.userList = newUserListView(status) self.userList = newUserListView(status)
self.status = status self.status = status
self.blockedContacts = blockedContacts
self.QAbstractListModel.setup 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) new(result, delete)
result.setup(chatId, status, addFakeMessages) result.setup(chatId, status, addFakeMessages, blockedContacts)
################################################# #################################################
# Properties # Properties
@ -174,6 +177,13 @@ QtObject:
for message in messages: for message in messages:
discard self.deleteMessage(message.id) 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) = proc replaceMessage*(self: ChatMessageList, message: Message) =
let msgIdx = self.messageIndex[message.id] let msgIdx = self.messageIndex[message.id]
let topLeft = self.createIndex(msgIdx, 0, nil) let topLeft = self.createIndex(msgIdx, 0, nil)
@ -262,6 +272,7 @@ QtObject:
of ChatMessageRoles.GapTo: result = newQVariant(message.gapTo) of ChatMessageRoles.GapTo: result = newQVariant(message.gapTo)
of ChatMessageRoles.Replace: result = newQVariant(message.replace) of ChatMessageRoles.Replace: result = newQVariant(message.replace)
of ChatMessageRoles.IsEdited: result = newQVariant(isEdited) of ChatMessageRoles.IsEdited: result = newQVariant(isEdited)
of ChatMessageRoles.Hide: result = newQVariant(message.hide)
method roleNames(self: ChatMessageList): Table[int, string] = method roleNames(self: ChatMessageList): Table[int, string] =
{ {
@ -298,7 +309,8 @@ QtObject:
ChatMessageRoles.GapFrom.int:"gapFrom", ChatMessageRoles.GapFrom.int:"gapFrom",
ChatMessageRoles.GapTo.int:"gapTo", ChatMessageRoles.GapTo.int:"gapTo",
ChatMessageRoles.Replace.int:"replaces", ChatMessageRoles.Replace.int:"replaces",
ChatMessageRoles.IsEdited.int:"isEdited" ChatMessageRoles.IsEdited.int:"isEdited",
ChatMessageRoles.Hide.int:"hide"
}.toTable }.toTable
proc getMessageIndex*(self: ChatMessageList, messageId: string): int {.slot.} = proc getMessageIndex*(self: ChatMessageList, messageId: string): int {.slot.} =
@ -331,9 +343,13 @@ QtObject:
proc addChatMembers*(self: ChatMessageList, members: seq[ChatMember]) = proc addChatMembers*(self: ChatMessageList, members: seq[ChatMember]) =
self.userList.add(members) 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 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": if message.editedAt != "0":
self.isEdited[message.id] = true self.isEdited[message.id] = true
if self.messageIndex.hasKey(message.id): if self.messageIndex.hasKey(message.id):
@ -348,10 +364,12 @@ QtObject:
self.endInsertRows() self.endInsertRows()
self.countChanged() 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) 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.messageIndex.hasKey(message.id): continue
if self.blockedContacts.contains(message.fromAuthor):
message.hide = true
self.messageIndex[message.id] = self.messages.len self.messageIndex[message.id] = self.messages.len
self.messages.add(message) self.messages.add(message)
self.userList.add(message) self.userList.add(message)
@ -429,13 +447,20 @@ QtObject:
self.dataChanged(topLeft, bottomRight, @[ChatMessageRoles.Username.int]) 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] = @[] var msgIdxToDelete: seq[string] = @[]
for m in self.messages.items: for m in self.messages.mitems:
if m.fromAuthor == publicKey: # Can't delete on a loop if m.fromAuthor == publicKey:
msgIdxToDelete.add(m.id) m.hide = hide
for m in msgIdxToDelete: self.toggleMessage(m.id, hide)
discard self.deleteMessage(m)
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.} = proc getID*(self: ChatMessageList):string {.slot.} =
self.id self.id

View File

@ -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/[status, contacts]
import status/messages as status_messages import status/messages as status_messages
import status/utils as status_utils import status/utils as status_utils
import status/chat/[chat] import status/chat/[chat]
import status/profile/[profile]
import status/types/[message] import status/types/[message]
import ../../../app_service/[main] import ../../../app_service/[main]
import ../../../app_service/tasks/[qt, threadpool] import ../../../app_service/tasks/[qt, threadpool]
import ../../../app_service/tasks/marathon/mailserver/worker 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: logScope:
topics = "messages-view" topics = "messages-view"
@ -170,19 +171,29 @@ QtObject:
self.messageList[id].clear(not channel.isNil and channel.chatType != ChatType.Profile) self.messageList[id].clear(not channel.isNil and channel.chatType != ChatType.Profile)
self.messagesCleared() 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) = proc upsertChannel*(self: MessageView, channel: string) =
var chat: Chat = nil var chat: Chat = nil
if self.status.chat.channels.hasKey(channel): if self.status.chat.channels.hasKey(channel):
chat = self.status.chat.channels[channel] chat = self.status.chat.channels[channel]
else: else:
chat = self.communities.getChannel(channel) 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): if not self.messageList.hasKey(channel):
self.beginInsertRows(newQModelIndex(), self.messageList.len, self.messageList.len) 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.channelOpenTime[channel] = now().toTime.toUnix * 1000
self.endInsertRows(); self.endInsertRows();
if not self.pinnedMessagesList.hasKey(channel): 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]) = proc pushPinnedMessages*(self:MessageView, pinnedMessages: var seq[Message]) =
for msg in pinnedMessages.mitems: for msg in pinnedMessages.mitems:
@ -199,9 +210,9 @@ QtObject:
proc isAddedContact*(self: MessageView, id: string): bool {.slot.} = proc isAddedContact*(self: MessageView, id: string): bool {.slot.} =
result = self.status.contacts.isAdded(id) result = self.status.contacts.isAdded(id)
proc messageNotificationPushed*(self: MessageView, messageId: string, proc messageNotificationPushed*(self: MessageView, messageId: string,
communityId: string, chatId: string, text: string, contentType: int, communityId: string, chatId: string, text: string, contentType: int,
chatType: int, timestamp: string, identicon: string, username: string, chatType: int, timestamp: string, identicon: string, username: string,
hasMention: bool, isAddedContact: bool, channelName: string) {.signal.} hasMention: bool, isAddedContact: bool, channelName: string) {.signal.}
proc pushMembers*(self:MessageView, chats: seq[Chat]) = proc pushMembers*(self:MessageView, chats: seq[Chat]) =
@ -376,9 +387,13 @@ QtObject:
if (result): if (result):
self.hideMessage(msgIdToBeDeleted) self.hideMessage(msgIdToBeDeleted)
proc removeMessagesByUserId(self: MessageView, publicKey: string) {.slot.} = proc blockContact*(self: MessageView, contactId: string) =
for k in self.messageList.keys: 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.} = proc getMessageListIndex(self: MessageView): int {.slot.} =
var idx = -1 var idx = -1

View File

@ -303,6 +303,7 @@ Item {
pinnedBy: model.pinnedBy pinnedBy: model.pinnedBy
gapFrom: model.gapFrom gapFrom: model.gapFrom
gapTo: model.gapTo gapTo: model.gapTo
visible: !model.hide
Component.onCompleted: { Component.onCompleted: {
if ((root.countOnStartUp > 0) && (root.countOnStartUp - 1) < index) { if ((root.countOnStartUp > 0) && (root.countOnStartUp - 1) < index) {
//new message, increment z order //new message, increment z order

View File

@ -10,7 +10,7 @@ Item {
id: root id: root
width: parent.width width: parent.width
anchors.right: !isCurrentUser ? undefined : parent.right anchors.right: !isCurrentUser ? undefined : parent.right
height: childrenRect.height height: visible ? childrenRect.height : 0
z: (typeof chatLogView === "undefined") ? 1 : (chatLogView.count - index) z: (typeof chatLogView === "undefined") ? 1 : (chatLogView.count - index)
property string fromAuthor: "0x0011223344556677889910" property string fromAuthor: "0x0011223344556677889910"
property string userName: "Jotaro Kujo" property string userName: "Jotaro Kujo"

2
vendor/status-lib vendored

@ -1 +1 @@
Subproject commit 4f7e899953843a316336fa72ae049f7880f6f7bd Subproject commit aa1fdf8a2ff469760c9857ab5eeedf976cd1c43a